/ 最近 .rdf 追記 設定 本棚

脳log[2009-07-05~]



2009年07月05日 (日) FEDERERでした。それまでブレイクしてたのは RODDICKだったのにファイナルセットでできなかった。

[tDiary] makerss.rb: 更新したつもりのないエントリまでが上がってくる理由。

ある日のエントリの一つを更新すると、同じ日の他のエントリまでが更新されたとして上がってくる理由。たぶんそれまでに他のエントリで「ちょっとした修正」を行っていたのだろう。makerss.rbを見てみたら

add_update_proc do
	makerss_update unless @cgi.params['makerss_update'][0] == 'false'
end

ちょっとした修正では日記の更新時に何も行っていない。これを、index.rdfの更新はしないけど cache/makerss.cacheの更新はする、というふうに変えられないだろうか。


目的は、以前に加えたちょっとした修正と、今回の普通の更新で加えた変更とを区別するため。


編集対象のセクションを特定できるなら、cache/makerss.cacheを常に更新することで、以前のちょっとした修正を検出しなくなるようにする必要はないし、むしろ LDRのようにフィードの内容の一字一字を比較するリーダー?(フィードアグリゲータ?)まで騙すことを考えると、cache/makerss.cacheの内容はちょっとした修正以前の古いままにしておく方がいいみたい。


じゃあ、なぜ既にセクション単位で編集を行ってるこの日記で、直前の編集に関係していないセクションまでが上がってくるのか? makerss.rbの変更まで手を回す前にやる気が尽きたから。

update_procに引数の追加が必要なんだけど、改めて具体的に考えてみると単純にセクションナンバー1つを渡せばよいというものでもなさそうだ。セクション2を編集した結果、セクション2がなくなってセクション3が 2に繰り上がってる可能性がある。セクション2が分裂してセクション2と 3になってる可能性がある。

LDRといい update_procの引数といい、万全を期すと二進も三進もいかんなあ。(LDRは使ってないから外せない問題ではないし、update_procは {before=>2, after=>2..3} を渡すだけで済んでしまう気もするけど)


ああ、afterの範囲を確定するのが難しいんだ。変更前に、編集対象のセクションの前にいくつ、後にいくつのセクションがあるかを数えておく手があるけど、場合によったら直前のセクションと結合してしまうことがあるからなあ(セクション2を編集していたはずが、セクション2を削除してセクション1に追記したことになってる可能性がある)。この場合セクション1に変更があったことは無視してセクション2が削除されたことだけを考えていいなら、やっぱり前後のセクション数を数えておく方法でよさそうだ。


makerss.cacheは二つの目的を持ってるんじゃないか。変更のあったセクションを検出する目的と *.rdfのソースにする目的。

そもそも、*.rdfのソースは *.rdf自身で十分じゃないか?(深くわかってるわけじゃないけど) これに変更のあったセクションを特定できる引数が update_procに加わったら makerss.cacheを用済みにできないか。


できない。一日単位の編集機能をなくせるわけじゃないから今と同等の変更検出機能は必要。そうすると *.rdfのソースを makerss.cacheから *.rdfにスイッチする必要もなさそうに思えるけど、……ないかも。(うっかりフィードに紛れ込んだテストコメントは index.rdfからアイテムを削除するのでなく、コメントを非表示にすれば、あとあと甦ってくることもなかったんだ)


 整理。

makerss.cacheは二つの役割を持っている。

  • 変更のあったセクションを検出する。
  • .rdfのソースにする。

変更のあったセクションの検出能力に難があったので改善を試みる。一日単位の編集機能が存在し続け、rdfのエントリの単位がセクションである限り、変更のあったセクションの検出能力の向上は無駄にならない。

makerss.cacheの日記内容をちょっとした修正でも更新する

これでちょっとした修正のあったセクションの誤検出はなくなる。だがこの makerss.cacheをもとに *.rdfを作成するとエントリの内容がちょっとした修正後のものになり、LDRなど RSSリーダーによる過剰検知の原因となる。

*.rdfのソースを *.rdfにする

右から左に流すだけでは過剰検知の起こりようがない。フィードを更新するときにどんな問題が発生するだろう……。手順を考える。

  1. makerss.cacheとの比較を基に、追加、変更のあったセクションを特定する。
  2. .rdf内のエントリから削除された(現在のセクション数から考えられるより大きいセクションナンバーを持つ)セクションを取り除く。
  3. 追加、変更されたセクションを .rdfのエントリに変換する。
  4. .rdf内に対応するエントリがあれば上書き、なければ追加し、.rdfの先頭に移動する。
  5. エントリ数の上限まで書き込み。

問題は、フィードに含まれる日記やコメントを隠したりセクションを削除したりするとエントリ数が上限より少なくなる、だけだろうか。最初は無理そうに思えたけど、なんだったんだろう。


makerss.cacheから読み込んだものと *.rdfから読み込んだものとは Rubyオブジェクトか文字列かという違いがあるんだなあ。でもそれが意味を持つのは MakeRssNoComments#itemで呼ばれる rdfsec.section.respond_to?( :body_to_html )だけみたいだから、ここを rdfsec.id.index("p") に置き換えれば *.rdfから読み込んだ xml文字列だけで makerss.cacheの代わりができそう。


 整理(Plan B)

セクション単位の編集機能があり、makerss.rbが update_procの引数から変更のあったセクションを知ることができれば、今以上の、変更のあったセクション検出能力は特段必要ではない。

makerss.cacheはこれまで通りちょっとした修正では更新されず、LDRをちょっとした修正以前の古い内容でだまし続けることが可能。

日記の書き手はフィードの更新を伴うデリケートな編集作業ではセクション単位の編集を行うことで、余計なセクションが上ってくることを避けられる。

こっちが断然楽そうだ。でも自分の環境で閉じてしまうから代替案なんだよね。


タイトル(脳log)にふさわしい垂れ流しっぷりじゃあないですか?


 をを、バグってる

はるか上の方でこう書いた。

場合によったら直前のセクションと結合してしまうことがあるからなあ(セクション2を編集していたはずが、セクション2を削除してセクション1に追記したことになってる可能性がある)。

何を見て書いていたかというと……

	unless body1.empty?
		current_section = @sections.pop
		if current_section then
			body1 = "#{current_section.body.sub( /\n+\Z/, '' )}\n\n#{body1}"
		end
		@sections << WikiSection::new( body1, author )
	end

解説解説

appendされた Wikiソースがサブタイトルを持っていないもの( body1 )だったら、
最後のセクションを取り除き

最後のセクションの本文( current_section.body, サブタイトルを含まない )と body1を連結し、

新しいセクション( サブタイトルなし )として追加する。

WikiSection#bodyの代わりに WikiSection#to_srcを使わないとサブタイトルが消えてしまう。

			body1 = "#{current_section.to_src.sub( /\n+\Z/, '' )}\n\n#{body1}"

サブタイトルのあるセクションに、サブタイトルのない本文を追加したときに、サブタイトルのないセクションができあがるのを防ぎます > fix_and_test_append_without_subtitle.diff


 Plan B 仮実行中

セクション単位の編集機能が追加されていることが前提。そのせいでこの日記でしか使えないから気乗りしなかったんだけど、第一案が手詰まりなのと一つの実験場として可能性を示すために。

update_procに updated_sectionというパラメータを追加し、makerss.rbが過去のちょっとした修正を誤検出するのを防ぎます > add_param_updated_section_to_update_proc.diff


2009年07月04日 (土) じゃりン子チエを見てる。「チ↘エちゃん」でなく「チ↗エ↘ちゃん」だというのに安心する。とりあえず頭にアクセント置いとけ、とか、英語由来なのにどこに母音が?ってなところにアクセントを置いてたり、だとかが多すぎる気がしてるので。(ラブルとかウェとかグーグとか、頭にアクセントだったり平板な読みが特徴)


2009年07月03日 (金) 時計回り、反時計回りはわかる。右回り、左回りはどっちがどっちかわからない。目の付け所が恣意的ではないか、と小学生のころ思っていた。<< 円を正面から見るのでなく、中心に立ってみればよかったのだ。(やっと訪れた理解)

最終更新: 2009-08-23T05:42+0900

> 500円弱の弱ってどう言う意味? - Yahoo!知恵袋

500円弱の弱ってどう言う意味?

例えば、500円弱って言う場合は、490円(500円より若干少ない)ですか? それとも510円(500円より若干多い)ですか? 前者だとばかりずっと思っていましたが、知人は後者だと思ってたそうです。

国語大辞典によれば、ある数の端数を切り上げたとき、示す数よりは少し、不足があることをいうために、数字のあとに弱を付けて用いる。「一万円弱」。

とあります。ですから、後者が正解ですね。

最近、通じてないな、と感じた経験がある。相手がこの言い方を知らないのならその場で言い換えるチャンスもあるけど、○○弱といったとき○○だけあるのかないのか、という部分をさらっと勘違いされていた。

回答をひとつだけ取り上げたけど、辞典を引いてさえ後者といわれては言葉がない。490円をきりのいい 500円に切り上げる、でも実際の金額がそれより少ないことを示すために弱をくっつけて 500円弱という、んじゃないの。辞典が示してるのは前者でしょ。

500円弱を「500円より少し上」に割り当ててしまったら 500円強の行き場は?「500円より大幅に上」とか?聞いてみたい。

最終更新: 2009-08-25T02:45+0900

[正規表現][Firefox] XRegExp-1.0.1と Firefoxの /(?!)/

20090628p01で書いた Firefoxのバグっぽいものが XRegExpに影響するみたい。

// Firefox 3.0.11 + XRegExp 1.0.1 での実行結果
alert( XRegExp("[]").test("a") ); //=> true
alert(  RegExp("[]").test("a") ); //=> false

[] と [^] の意味するところってなんでしょうね。[] は空の文字集合だから「どれでもない一文字」とマッチする(=空文字列にもマッチせず必ず失敗する)。[^] は空の文字集合の補集合だから「任意の一文字」だろうか。

参考ページを見つけた > 文字クラス(http://suika.fam.cx)

結局、こういうことだ。

  • 主要 4ブラウザのうち [][^] が使えないのは IEだけ。
  • Opera(9.61)は [][^] がおかしい(他と違う)。
  • Firefox(3.0.11, 3.5RC3)は (?!)(?=) がおかしい(他と違うし、自分自身の (?!|)(?=|) とも違う)。

(IEの件を除いて)どのパターンも規格上の正解やデファクトスタンダードがなくて混乱してんじゃないかなあ。こういうのには近づかないに限る。


 追記@2009-07-04 04:44: 内容確認。

正しくコメントが読めてるといいんだけど……。

IEが空の文字セット [] を処理しないのは(ECMAScriptの仕様をすっとばして) Perlその他、JavaScript以外の多くの実装にならっているもので、[ に続く最初の文字を文字通りの文字 ] だとしているから。だから []][\]] と同じ意味になる。

Firefoxで (?!) の代わりに (?!|)(?=) の代わりに (?=|) を使うのは良くなくて、つまりこれらの結果は同じになるべきだけど、どちらになるかは将来の Firefox次第だから。バックトラックの発生にもつながって効率的にも不利。だから (?!) の代わりは \b\B(?=) の代わりは (?:) が良い。

\b\B というのは覚えておこう。


 追記@2009-07-04: はずしてた。

冒頭の指摘ははずしてる。考える前に、気付いたことをただ書いたせいだ。

XRegExpの目的の一つは、ブラウザごとにまちまちな挙動を見せる JavaScriptの正規表現に関するメソッドを仕様に準拠させることだったと思う(String.split()とか RegExp.lastIndexとか)。

だから空の文字セット( [][^] )を提供する第一の目的は 5ブラウザ(IE, Fx, Opera, Safari, Google Chrome)のうち不当にこれを受け付けない IEにおいて、仕様で許された正規表現パターンを利用可能にすること、かもしれない。

その過程で、Firefoxがネイティブに処理する空の文字セットと、XRegExpの提供する空の文字セットの挙動が食い違ってしまっている(1行目 1、2列)、というのが冒頭の指摘。でもこれは重要ではないし、同様の指摘を Operaについても行うことができる(3行目 1、2列と 3、4列)。

そうではなくて、ライブラリ利用者として「仕様に準拠した」「ブラウザ間で統一された」機能を望む視点から、XRegExpの提供する空の文字セットが Firefoxにおいてのみ違う意味になること(2列目)をこそ指摘すべきだった。(実際そうしたんだけど、日記の内容だけが古かったのでこうして追記している)

1列目2列目3列目4列目
RegExp("[]")XRegExp("[]")RegExp("[^]")XRegExp("[^]")
1行目Firefox(3.0.11, 3.5RC3)必ず失敗必ず成功成功したり失敗したり(後述)任意の一文字任意の一文字
2行目IE(8.0)例外必ず失敗例外任意の一文字
3行目Opera(9.64)任意の一文字必ず失敗必ず失敗任意の一文字
4行目Safari(4.0)必ず失敗必ず失敗任意の一文字任意の一文字
5行目Chrome(2.0.172.33)必ず失敗必ず失敗任意の一文字任意の一文字
 すごくおかしな Firefox(3.0.11)の (?!)

全てのパターンに (?!) が含まれているから、本当は全て falseになってほしい。

/(?!)/.test("abc")     //=> true!
/(?!)(?!)/.test("abc") //=> false

/^(?!)/.test("abc")    //=> false
/(?!)$/.test("abc")    //=> true!

/a(?!)/.test("abc")    //=> false
/(?!)a/.test("abc")    //=> true!

/\b(?!)/.test("abc")   //=> false
/(?!)\b/.test("abc")   //=> true!

/(?:)(?!)/.test("abc") //=> true!
/(?!)(?:)/.test("abc") //=> true!

(?!) が実質的にパターンの先頭にあるときだけ、存在しないかのように振る舞っているような。すごく限定された状況でのみ発動するんだったんだ。

ここまで書いてなかったことに気付いたけど、これが XRegExp("[]") に影響するのはこのパターンが内部的に (?!) に書き換えられるから。XRegExp (1.1.0, 2009-07-04)では \b\B に置き換えられるようになっていて、Firefoxのおかしな挙動に影響されて他のブラウザと違う結果になることはなくなっている


もう書かれてた! > http://blog.stevenlevithan.com/archives/xregexp-1-0/comment-page-1#comment-37653


 追記@2009-07-05 04:40: XRegExp-1.0の設計の良さを示す好例 > 20090703c02

自身の機能を XRegExp.addToken()で提供しており、ユーザーも同じ方法で拡張できる。トークンの有効範囲が文字セット [……] の内か外か、その両方かは addToken()の第3引数のビットフラグ( XRegExp.INSIDE_CLASS, XRegExp.OUTSIDE_CLASS )で指定できるし、エスケープシークェンスは予め処理されているので \(?!) を \\b\B に置き換えてしまう心配もない。簡単でしょう。

でも鬼車の \g を追加しようとして、名前付きキャプチャ内部のパターンを手に入れられず、中断。


 追記@2009-07-05 04:40: \gの実装サンプルを見てみた。

その \gの利用例が次。

XRegExp("(?<any_backref>\\3|\\4){0}     \
         (?<smiles>(?::-[D)])+){0}      \
         ([ab]) ([12]) \\g<any_backref>+\
         \\g<smiles>                    ", "x").test("a22aaa:-):-D"); // true

解説すると、まず名前付きキャプチャを使って再利用を前提としたパターンを定義する(any_backrefと smiles)。ポイントは量指定子{0}の存在で、現状ではこれが必ず必要になる。これによりこの名前付きキャプチャはマッチに参加せず、一文字も消費せずに成功する。その存在意義は \g<smiles> のように、後で名前を使ってパターンを再利用できること。

上の例で、実際に文字を消費するパターンは後半分、次の部分だけ。

    /([ab])([12])\g<any_backref>+\g<smiles>/

Rubyで同じ意図を持って書くとこういうふうになる。

irb> any_backref = /\1|\2/
=> /\1|\2/
irb> smiles = /(?::-[D)])+/
=> /(?::-[D)])+/
irb> re = /([ab])([12])#{any_backref}+#{smiles}/
=> /([ab])([12])(?-mix:\1|\2)+(?-mix:(?::-[D)])+)/
irb> re.match( "a22aaa:-):-D" ).to_a
=> ["a22aaa:-):-D", "a", "2"]

さて、パターンの再利用が \g の利用法だけど、個人的にそれが最大の効果を発揮するのは、パターン定義の中でパターンを呼び出したとき、再帰的なパターンを定義できることだと思っている。20080111p01で既に書いているが、

 /%[Qq]?(?<brace>\{[^\{}]*(?:\g<brace>[^\{}]*)*})/

名前付きキャプチャ (?<brace>……) の中に \g<brace> がある。こういう GNUの命名のような再帰的定義ができてこそ \g を利用する価値があると個人的には思う。

addToken()で \g を定義する方法として考えていたのは「パターン文字列を、上限を決めて再帰的に展開する」というもの。このように。

  1. (?<brace>{\g<brace>})
  2. (?<brace>{(?:{\g<brace>})})
  3. (?<brace>{(?:{(?:{(?:{\g<brace>})}))})
  4. (?<brace>{(?:{(?:{(?:{(?:)})}))})

実際の手順は addTokenの第二引数が文字列を返す代わりに toString()を定義したオブジェクトを返し、xregexp.jsの下の引用部分、output.join("") の時点で、名前付きキャプチャ内のパターンを参照してパターン文字列を返そうというもの。

            regex = RegExp(output.join(""), real.replace.call(flags, /[^gimy]+/g, ""));
            regex._xregexp = {
                source:       pattern,

コードの枠組みはこんなの。もちろんこのままでは動かない。

function PatternOfNamedCapture(name) {
	this.name = name;
}
PatternOfNamedCapture.prototype.toString = function(){
	// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
	if(MAX_RECURSION < count++) {
		return "(?:)";
	} else {
		return output.slice(
			defs[this.name].start,
			defs[this.name].end
		).join("");
	}
	// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
};
XRegExp.addToken(
	/\\g<([$\w]+)>/,
	function(match) {
		return new PatternOfNamedCapture(match[1]);
	}
);
本日のツッコミ(全4件) ツッコミを入れる

Steven LevithanActually, IE treats [] and [^] like Perl and almost every ..

Steven LevithanThanks for finding and documenting the Firefox (?!) bugs. ..

Steven LevithanRegarding your latest update (dated 2009-07-05 04:40), Oni..

Steven LevithanI just updated the example page I linked to so that the so..


2009年07月02日 (木) ロケット鉛筆っていまもあるのかな

[] ぺんてる グラフギア1000 0.5mm

今まで、軽い安い細い短いを基準に 100-200円のを使ってたんだけど、シンプルで寸胴なのがかえって見つからなかったりもする。今回初めてちょっと色気を出してみた。

グラフギア1000 0.5 グラフギア1000 0.5

Pentel
¥ 750

ペン先収納機能と大きなクリップが決め手。グリップのイボイボもアクセントとして気に入ってるので、0.5mmの灰色のゴムはすこし地味にすぎる。

唯一にして最大のネックは重さと重心の高さ。ペン先を持って振ってみればいかに頭が重たいか実感できる。長時間の使用には向かないだろうが、そうでなければ満足の品。

あ、素材が真鍮、アルミ、鉄、ステンレスだ。錆びるんじゃなかろうか。

 対抗馬1:

三菱鉛筆 uni SHIFT(シフト)0.5mm【シルバー&ブルー】 M5-1010 26 SV 三菱鉛筆 uni SHIFT(シフト)0.5mm【シルバー&ブルー】 M5-1010 26 SV

三菱鉛筆
¥ 950
こちらもペン先収納。グラフギアのようなダブルノックではなく、ねじるのでもなく、押して回すことでペン先を固定するのが意外に手間。ペン先を収納したときに解放されるグリップのゆるゆる感も頼りない。クリップが小さい。

 対抗馬2

グラフ1000(PG1005) グラフ1000(PG1005)

ぺんてる
¥ 910
ペン先は収納できず、クリップは極小。だが軽い。一番無難で実用的なのだが面白味に欠ける。

 対抗馬3

シャープペン「クルトガ」ハイグレードタイプ 0.5mm【ブラック】 M5-1012 シャープペン「クルトガ」ハイグレードタイプ 0.5mm【ブラック】 M5-1012

三菱鉛筆
¥ 945

面白そうではある。クルトガを実現するために芯が 0.3mm引っ込むのに違和感を覚えるとの声多数。だが慣れるとも聞く。もう一本買うならこれだがシャーペンは一本で十分。


2009年07月01日 (水) クルトガ。「使い初めの頃は、このペン独特のノート等に芯を押しつけると少し芯が戻る仕様が気になります。」(Amazon.co.jpカスタマーレビュー) あー、やっぱり。触ったことないけど 0.1mmでも戻ったら違和感は消えないだろうな。(0.3mmだって > http://www.nikkeibp.co.jp/style/biz/trail/080926_kurutoga1/index4.html ) どうかな?独特だしとりあえず使ってみたいな。


2009年06月28日 (日)

最終更新: 2009-10-28T01:40+0900

[正規表現][Firefox] .NETの正規表現の再帰について(20080111p01の補足)。

再帰っていっていいのかな?鬼車は明らかに再帰だったけど。

.NETの正規表現を利用した経験はありません(念のため)。想像です。

.NETの再帰に関係した部分のドキュメントがあまりにわかりにくかったので整理。(実はわかりにくさの半分は日本語のせいだった。英語の方のドキュメントを読みましょう)

 1.スタックされる名前付きキャプチャグループ: (?<name1>……), (?'name1'……)

キャプチャ内容を読み出す従来の記法が \1, \2。名前付きキャプチャの場合は \k<name1>, \k'name1'など(実装ごとに異なる)。キャプチャグループに量指定子がくっついている場合、これらで読み出せるのは最後のキャプチャ内容だけ。だけどキャプチャの記憶領域はキャプチャグループごとに一つではなくスタックになっていて、その一番上の内容を読み出していると考える(.NETだか Javaだかではプログラムからこのスタックにアクセスできたはず)。

 2.名前付きキャプチャ name1のスタックを POPする: (?<name2-name1>……)

まず、これは name2という名前付きキャプチャグループ。と同時に、name1のキャプチャスタックを POPする。name2を省略して name1を POPするだけも可能。MSDNの日本語ドキュメントを名前の部分だけこちらに合うように書きかえたのが次。

既に定義されていたグループ name1 の定義を削除し、既に定義されていた name1 グループと現在のグループの間隔をグループ name2 に格納します。

実際に name2のキャプチャ内容がどういうものになるのか(直前の name1のキャプチャ内容、name2の……にマッチした部分、その間、がそれぞれ含まれるのかどうか)は読み取れないけど、直前の name1キャプチャをなかったことにし、name1のキャプチャ部分から ……までを name2に保存するという。(覚え方: name2は直前の name1から……まで)

当然のこと、name1のキャプチャスタックが空のとき name2のキャプチャは ……のマッチ正否に関わらず失敗する。

 3.名前付きキャプチャ name1のスタックが空であることをテストするイディオム: (?(name1)(?!))

name1のキャプチャに成功しているかどうかで適用するパターンを変化させる条件分岐 (?(name1)truepattern|falsepattern) と、必ず失敗するパターン (?!) の組み合わせにより、name1のキャプチャスタックが空でないと必ず失敗する。逆に name1のキャプチャスタックが空のときは(省略された空の falsepatternが何にでもマッチして)必ず成功する(はず)。

(?(name1)(?!)) が成功する(=name1のキャプチャスタックが空である)とは、name1に含まれるパターンが開きかっこ、name2のパターンが閉じかっこにマッチし、その間のパターンが開き閉じどちらのかっこにもマッチしないとき、開きかっこと閉じかっこがバランスしている、ということ(MSDNの例がこれ)。

なんてこったい

// Firefox 3.0.11と 3.5RC3のロケーションバーでの実行結果。
javascript:alert(/(?!)/.test("")) //=> true (falseであってほしい)
javascript:alert(/(?=)/.test("")) //=> false (trueであってほしい)
javascript:alert(/(?:)/.test("")) //=>
// Windows Vistaでの JScript(WSH)実行結果。
WScript.Echo(""+ /(?!)/.test("")) //=> false (期待通り)
WScript.Echo(""+ /(?=)/.test("")) //=> true (期待通り)
WScript.Echo(""+ /(?:)/.test("")) //=> true (期待通り)

必ず失敗するパターンを試してみたら Firefoxで真逆の結果が出てしまった。Firefoxが間違っててくれないと困るよ。(ブラウザにより逆の結果がでていることがもう困るけど)

(参考)間違いなく失敗する* > 詳説正規表現第3版 - Google ブック検索, 詳説正規表現第3版 - Google ブック検索

Internet Explorer 8.0.6001.18783 64-bit Edition、Safari 4.0.530.17、Opera 9.64、Google Chrome 2.0.172.33 でもみんな Firefoxとは逆の結果になる。Firefoxだけが 3.0から 3.5RC3になっても違っているのは悪夢だ。

Firefoxに理がないことは次の例からも判断できないか。空のパターンを空と空の選択パターンにするだけで結果がひっくり返ってる。

// Firefox 3.0.11のロケーションバーでの実行結果。
javascript:alert(/(?!)/.test("")) //=> true (下と同じであるべき)
javascript:alert(/(?!|)/.test("")) //=> false (期待通り)

javascript:alert(/(?=)/.test("")) //=> false (下と同じであるべき)
javascript:alert(/(?=|)/.test("")) //=> true (期待通り)

javascript:alert(/(?:)/.test("")) //=> true (期待通り)
javascript:alert(/(?:|)/.test("")) //=> true (期待通り)

* 念のため断っておくと、書籍の文脈では、この断定は Perlと .NETの正規表現に(ちゃんと)限られている。


2009年06月27日 (土) 打ち水ってあるね。ひしゃくで前の道に水をまくような。見たことはないけど。自分でやってみるところを想像したらバケツの水をひっくり返していた。ダメかな。


2009年06月26日 (金)

[Amazon] Product Advertising API

事実と一致するかはおいておいて、Amazonが「デジモノに埋もれる日々」の記事レベルの見解を示していてくれれば抵抗もすくなかったのに。すごく納得できる内容。

既に書かれているけど OpenProxyの注意点は利用規約にも書かれている 1 call per secondの制限を守れるかどうかと、アカウントの停止の危険性だね。Proxy利用者で秘密キーを持ってる人がキーを持ち寄って上限を N call per secondに引き上 げたら……とか考えたけど、それじゃ全然「秘密」キーじゃないわな。

<追記@2009-07-08> DNSラウンドロビンってなんだ、って調べたんじゃなかったか。個人個人がサーバーを立てる、それらを同じ名前で利用する。これで秘密キーとサーバーリソースの両方を持ち寄れる。 </追記>

バイナリファイルでの扱いに関する Amazonの見解。

  • コンパイル型言語で秘密キーを暗号化した上で実行用バイナリ内に埋め込んで、実行用バイナリを公開する。ユーザーは自身のPCで実行用バイナリを実行する。
  • 実行用バイナリをバイナリエディタで覗いた位では秘密キーは解読できないが、実行用バイナリコードをリバースエンジニアリングされれば秘密キーを得ることも可能な状態。

のいずれのケースについても、理想的な方法とは言えませんが、条件付きで利用可能であるという見解となります。

単純な埋め込みは NG。リバースエンジニアリングにより秘密キーが知られうる場合は、理想的ではないが可。

Amazonは PAAPIのどういう利用を想定しているんだろ。サーバー型のサービスとして? 個人が個人の責任で呼び出すものとして? 俺はもう APIを利用してくれるなという Amazonからのメッセージだと受け取っている。(情報が少ないから曲解するんだよ)


2009年06月25日 (木) [SakuraEditor] Mery(テキストエディタ)。タブと多ウィンドウ形式を選べるんだけどどちらもプロセスは一つ。やはりというか、既に Meryを開いていると「svn commit --editor-cmd Mery」でコミットメッセージを編集できない。svnが起動したプロセスはおそらくコマンドラインを既存プロセスに渡してすぐに終了するからだろう。(※これはメモリを食おうとも多プロセスのタブ方式を選んだサクラエディタの提灯カキコです)


2009年06月23日 (火) [正規表現] \rと \nはプラットフォームによってマッチする文字コードが入れ替わる可能性があるから \x0d、\x0aって書いとけって読んだことがある。意図は想像できる。\nを Macでも UNIXでも改行の意味にしたかったんだろう。けど、そんな実装は(あるなら)消えればいいよ。


2009年06月22日 (月) 関数の外の const intと static const intは同じ?

[SakuraEditor] メニューバー右端のメッセージ表示改善

縦書き編集機能とか実装できるほどのスキルがあればいいんだけどねえ。


2chに化けるという書き込みがあって試してみたら表示が消しゴムで消すように欠ける。描画漏れだと思ったんだけど、後で調べたらそもそもメッセージを保存していなくて再描画するつもりがない。だったら改善す"べき"とまでは思えないんだよね。(タイポのようなものの指摘はできても、自分の考えを押しつけることまではできないし)


ステータスバーが非表示のときにメニューバー右端に表示されるメッセージの、再描画に対応。一時メッセージだとしてもメッセージが半欠けの状態で表示されてたらバグととられても仕方ないから。> fix_menubarmessage.diff

この修正中にこんな処理が行われていたことを知ったのだけど……

 // 編集ウィンドウ切替中(タブまとめ時)はタイトルバーのアクティブ/非アクティブ状態をできるだけ変更しないように(1)	// 2007.04.03 ryoji
 // 前面にいるのが編集ウィンドウならアクティブ状態を保持する

タブ切り替え時に二つのサクラエディタウィンドウが重なる瞬間があって、Aero Glass効果が有効だとこの時にタイトルバーの透明度が下がる(色が濃くなる)。結果、対策もむなしくちらついて見える。これに対応した対処法はあるかな?


 ツッコミを受けての追記。

行・列番号の表示よりも右の部分にゴミが表示されます。

Vistaしかないので制御文字が半角空白に置き換えられたときに区別できるように、メッセージの余白を「 」ではなく「*」で埋めて表示してみたけれど表示は変わらない。この、メッセージの余白を埋める文字がすべてゴミになっているのだろうか。2chの

ステータスバーを消すとメニューバーの右端が化けちゃうんだけどどうすれば

というのを読んで俺は表示が欠けることを指して化けると言っているのかと思ったんだけど(繰り返すけど Vistaだとゴミは見えないので)、この書き込み主は Windows2000でも使っていて半角の「・」のことを指して化けると言っている可能性もあるかも(俺がバグを仕込んだのではないと思いたい)。

タブ切り替え時のちらつき防止はノーアイディア(あったら書いてる)。せっかく見映えの細かいところにまで気が配られているのに自分の環境で働いていないってのは悲しいから、Aero Glassにも対応できたらいいよね。


_tcsncpyが、コピー元が短いときにコピー先の末尾に埋める '\0' が「・」に変換されるんだ。Cの林立する文字列操作関数が大嫌いでいつも(といって片手で数えられるほど)は std::stringに逃げるんだよね。元々のソースはちゃんとやってたのに、俺がテケトーなことをしたわけだ。確保した領域の一つ先に書き込むとか言い訳できないミスもしてるし……。

今度は右端に埋め文字(「 」の代わりの「*」)が見えた > fix_menubarmessage(rev2).diff


さらなるチョンボ(泥沼の様相を呈してきました)。さっきの改訂でメッセージが空になることがなくなったので、表示したメッセージのクリアが行われないはずだ。

もう最後にしたい > fix_menubarmessage(rev3).diff

本日のツッコミ(全1件) ツッコミを入れる

ryojiパッチ(fix_menubarmessage.diff)を適用したものだと、 行・列番号の表示よりも右の部分にゴミが..


2009年06月19日 (金) 50音配列は右端があ行だとおもうんだ > QMA DS

[Songbird] Keyboard Ratings 0.3.3.1のこまったちゃん

 日本語キーボードの配列を知らない。

2を Shiftするとダブルクォーテーションになることを知らないから、説明通りのCtrl+Shift+2 では★2つを付けることができない。(代わりに Ctrl+@で★2つを付けられる)

 自動更新スマートプレイリストの曲を評価できなくなる。

  1. スマートプレイリストのフィルタリング条件にレートを含める。
  2. スマートプレイリストの自動更新を有効にする。
  3. スマートプレイリストの再生中に曲を評価する。
  4. その結果その曲がプレイリストから追い出される。
  5. 評価できない (´・ω・`)

2009年06月17日 (水) >http://www.watch.impress.co.jp/eizodirect/fx2431tv/ 「優性遺伝」は「優れた性質が遺伝すること」ではないよ。むしろ世の趨勢がフルHD(1920×1080)パネルな今、WUXGA(1900×1200)は劣性遺伝子ではなくて? それが受け継がれたのを評価するところは同意するが。

> AmazonのAPI認証導入はOSSに対する挑戦だよなぁ(3) - ただのにっき(2009-06-17)

OSSに関しましては、当初御理解の通り、ソースコードが公開されてしまうことから、秘密キーを含む開発者様のキーを埋め込んだまま公開されることは、ライセンス上の問題が発生します。

よって、OSSのユーザ様それぞれにAPIのAccessKeyIDおよび秘密キーを利用開始時に入力いただくという方法を強くお勧めいたします。

だーよーねー。賢い迂回路が用意されてるのかと期待してたのに……。これで特定のサーバーに代理でリクエストしてもらう方法まで禁止されたら Amazonボイコットだべ(個人的に)。チャンスだ。bk1!


コンパイル型言語を使っていても stringsみたいなの、あるいはサクラエディタのようにヌル文字を扱えて正規表現が使えるエディタで「\b[\w\d+/]{40}\b」(文字種は適当です)を検索してみるとかで簡単に秘密キーを抽出できるのでは、という心配は不要なのだろうか。こちらにはパスワードを保護するのと同等の策を講じるような動機がないもんね(アカウントの停止はあるかも)。秘密キーの「秘密」なんてのはとっとと有名無実化すればいいよ。


PROXY設置は構わないんだって。

>Amazon API認証のPROXYを書いたよ(AmazonのAPI認証導入はOSSに対する挑戦だよなぁ(4)) - ただのにっき(2009-06-19)

なんだかなあ。何がしたいんだろう。AccessKeyIdとオプションパラメータの AssociateTagで何が不足だったんだ。他のサービスと統一したかったのか?


もちろん上で挙げた方法は文字列を分割するだとかシーザー暗号を使うだとかで対抗できるけれど、単にバイナリファイルであるというだけで秘密キーを秘密にしていたと言い訳できるんじゃないかと。そして自発的に強固な保護策を講じる動機はないよ。

Amazon Web Services Developer Community : Docs: Product Advertising API (Version 2009-03-31)から引用。

It is important to keep it(Your Secret Access Key) confidential to protect your account.

To provide proof that you truly are the sender of the request, you must also include a digital signature.

AccessKeyID(AWSAccessKeyId/SubscriptionId/DeveloperToken)より確かな識別情報が欲しいだけなの? Proxyの設置が許されてることから、より広範な、例えばブログの書き手個々に SecretAccessKeyを取得してもらって識別する意図はないんだろうし。(だったら Proxyを設置する以外には、そういう対応を利用者にとってもらわなければならないスクリプトはとんだとばっちりだ)

あるいは暗号化? SecretAccessKeyが適切に保護されなければそれも無意味だよ。"YOUR SECRET ACCESS KEY GOES HERE" なサンプルコードばっかりなんだけど。これはない。他に方法がある。

どちらにしろ、手間ひまかけて AccessKeyIDに毛を生やす結果になるだけの気がするから、悪態のひとつもつきたくなるわけ。

うろついてるうちに見つけた(順序が間違ってる!) > Amazon.com Product Advertising API License Agreement

  • 他人の IDでアクセスしたらダメだって。まあ、当たり前。
  • 画像のキャッシュはだめ。画像の URLは 24時間を限度にキャッシュ可。画像以外のキャッシュも 24時間まで。
  • 値段と在庫の情報は鮮度に厳しいようで、いろいろと取り扱い上の注意が……。
  • インストールされたクライアントごとに 1 call per second を超えないこと。などなど

(読んでるうちに) SecretAccessKeyが使い捨て可能なことを思い出した。にょきにょき再生してくるしぶとい毛なのかも。手間をかける価値は……あるかなあ?

期限が来て画像が表示できなくなったら isbn* なメソッドを Amazon以外に置き換えてやろうかしら(手間は一緒だし)。


よくみかける G-Toolsは http://g-tools.com/ でリンクを作成してるのね。つまり今回の変更は利用者には影響がない。はてなダイアリーでも影響がない。tDiary.Netもたぶんない。自前のサーバーでサービスを提供しているところはみんなそう。自分でツールをインストールするような人間は自分で SecretAccessKeyを取得してソースに埋め込むこともできるでしょ、とでも思われているのか数が少なくて無視されているのか。たしかにできるとは思う。やりたくないけど。リンクを作成するのにアマゾンのアカウントをとらないといけないなんて、先に挙げたサービスを利用するのと比べて一段ハードルが高い。代替案の Amazonの手前に(Proxy)サーバーを一台はさむ方は無駄と脆弱性を理由に却下したい。

Amazon自身がリクエストの代行を行うサーバーを設置したらいいんじゃないの。リクエストの Identificationなんてなくなるけど、つきつめればそういう結果になる道を容認したのは自分なんだし。

なんで自分の首を絞めるようなこと(代理リクエストを許可したことを責めているように読めること)まで書いているのか自分でも不思議だったんだけど要は「無駄無駄無駄無駄ッ!」ということなんだろう。Authenticationの導入自体が既に疑問だけど、どうせ導入するなら無駄にならないように手を尽くせ、とこう言いたいらしい。