step1 load.c:147 (rb_feature_p) if (!load_path) load_path = rb_get_expanded_load_path(); step2 load.c:44 (rb_get_expanded_load_path) VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil); step3 Insecure Operation - require (SecurityError)
いました。Ruby1.9.1で SecurityErrorを量産する rb_get_expand_path()が。どうも、汚染された load_pathの一つを展開しようとして SecurityErrorになってる気がする。
$:($LOAD_PATH)の要素が汚染されてるのは、こちらの責任では?と思って確かめてみた。
SecurityErrorの直前で、$:の各要素が tainted?かどうかを TDiary::Config#debugを使って出力した結果。
D, [2009-01-17T23:36:46.289008 #1212] DEBUG -- : false Y:/server_root/www/ds14050/tdiary_on_ruby191 D, [2009-01-17T23:36:46.289008 #1212] DEBUG -- : true Y:/server_root/www/ds14050/tdiary_on_ruby191/misc/lib D, [2009-01-17T23:36:46.289008 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/site_ruby/1.9.1 D, [2009-01-17T23:36:46.289985 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/site_ruby/1.9.1/i386-msvcr90 D, [2009-01-17T23:36:46.289985 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/site_ruby D, [2009-01-17T23:36:46.289985 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/vendor_ruby/1.9.1 D, [2009-01-17T23:36:46.289985 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/vendor_ruby/1.9.1/i386-msvcr90 D, [2009-01-17T23:36:46.290961 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/vendor_ruby D, [2009-01-17T23:36:46.290961 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/1.9.1 D, [2009-01-17T23:36:46.290961 #1212] DEBUG -- : false C:/Program Files (x86)/ruby/lib/ruby19/1.9.1/i386-mswin32_90 D, [2009-01-17T23:36:46.290961 #1212] DEBUG -- : false .
ひとつ、ありましたね。tDiaryが該当パスを $LOAD_PATHに挿入する部分で、下のように untaintをつけるだけで理不尽な SecurityErrorが解決しました。(ただし、ASRでは依然 SecurityErrorになる。解決したのは、20090116p01で書いたように、load.cの 501行目をコメントアウトした Ruby-1.9.1RC1での話)
-tdiary.rb:12: $:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' ) +tdiary.rb:12: $:.insert( 1, File::dirname( __FILE__ ).untaint + '/misc/lib' )
今回の一連の流れ(20090113p01、20090114p01、20090116p01)で、$SAFE=1が、SecurityErrorで使い物にならなくなる(>添付ライブラリの requireにも失敗する)、二つのルートが見つかった。それらは requireするライブラリの拡張子を明示したり、$LOAD_PATHの中身をすべて untaintすることで回避できたり、load.cの一行をコメントアウトしたりで回避できたが、スクリプトで対処すべきものではないと考える。file_expand_pathが $SAFE>0のとき、汚染された入力を一切受け付けないという前提のもと、(rb_)file_expand_pathを呼び出しているコードを見直すか、file_expand_pathが汚染された入力を受け入れて適切に処理するか、どちらかの変更が必要だと思う。「file_expand_path()の結果が汚染された入力や $LOAD_PATHの汚染された一要素に基づくとき、その展開されたパスも汚染されている。」「$SAFE=1のとき、最終的に requireするファイルのパスが、汚染された引数や、$LOAD_PATHの汚染された要素に基づくとき、SecurityError。」というのではいけないのだろうか。Ruby-1.8.7はそのへんうまくやっているのだが……。
改めてドキュメントを読んだら、汚染された文字列を引数にした Fileのクラスメソッド、インスタンスメソッドは禁止されていた。($SAFE=1のとき)
ドキュメントに従うなら rb_file_expand_pathが SecurityErrorを出すのは正しいのかも(Ruby-1.8.7がまちがっている)。それならば、$LOAD_PATHの汚染された要素を不用意に展開しようとして SecurityErrorを出したり(load.c:44:rb_get_expanded_load_path)、もともと汚染されていなかった文字列を複数回展開しようとして SecurityErrorを出したり(load.c:501:search_required)するほうを修正しなければ。
私見では、(最下層で実際の仕事を行う)file_expand_pathは汚染フラグを適切に伝播させるものの SecurityErrorは出さないでおき、(スクリプトから呼ばれる)File.expand_pathの実体である rb_file_s_expand_pathか、file_expand_pathに仕事を丸投げする rb_file_expand_pathでセーフレベルに基づくチェックを行うのが、呼び出し側にとって便利だと思う。
tDiaryのプラグインの recent_list.rbを書き換えたのは、今思えば不要だったみたいだ。(Rubyの方が変わるに違いないもの)
20090113p01や20090114p01で発生したエラーを起こす最小のスクリプトとそれを回避する方法。
>type a.rb puts "a.rb required." >ruby19 -v ruby 1.9.1 (2008-12-30 patchlevel-0 revision 21203) [i386-mswin32_90] >ruby19 -e "$SAFE=1; require 'a'" -e:1:in `require': Insecure operation - require (SecurityError) from -e:1:in `<main>' >ruby19 -e "$SAFE=1; require 'a.rb'" a.rb required.
二つの違いは requireするライブラリの拡張子(.rb)を明示しているかどうか。拡張子なしの場合に発生する SecurityErrorは間違いだと思う。そうでないと $SAFE = 1がまるで使い物にならない。添付ライブラリだってまともに動かなくなるんだから。
ところで、Ruby 1.9 - 1.9.1 RC2 issues - Ruby Issue Tracking Systemにはチケットを作成するためのフォームがない。ruby-dev MLはアーカイブをときどき閲覧しているが購読はしていない。是非ともこの SecurityErrorは消して欲しいのだが、報告を受け付ける間口が狭い。直通ルートがない。どうすべ。
どうすべ、と言ってる間に原因究明。
load.c:500: type = rb_find_file_ext(&tmp, loadable_ext); load.c:501: tmp = rb_file_expand_path(tmp, Qnil);
501行目が不要に思える。そしてこれが SecurityErrorの原因。rb_find_file_extは内部で rb_file_expand_pathや file_expand_pathを呼び、その結果を tmpにコピーしてくれている。二度目を呼ぶ必要はないのでは? rb_file_expand_pathは適宜汚染されたStringオブジェクトを返し、また $SAFE>0のとき、汚染された引数を SecurityErrorで拒絶するので、複数回の (rb_)file_expand_path呼び出しは容易に SecurityErrorを引き起こす。これは Ruby1.9.1の、Ruby1.8.7とは異なっている動作。
>irb irb(main):001:0> File.expand_path("a") => "Y:/a" irb(main):002:0> File.expand_path("a").tainted? => true irb(main):003:0> File.expand_path(File.expand_path("a")) => "Y:/a" irb(main):004:0> $SAFE=1 => 1 irb(main):005:0> File.expand_path(File.expand_path("a")) => "Y:/a" # $SAFE>0で、taintedな文字列でも展開する。(Ruby1.8.7) irb(main):006:0> exit >irb19 irb(main):001:0> File.expand_path("a") => "Y:/a" irb(main):002:0> File.expand_path("a").tainted? => true irb(main):003:0> File.expand_path(File.expand_path("a")) => "Y:/a" irb(main):004:0> $SAFE=1 => 1 irb(main):005:0> File.expand_path(File.expand_path("a")) # $SAFE>0で、taintedな文字列を引数にすると SecurityError (Ruby1.9.1RC1) SecurityError: Insecure operation - expand_path from (irb):5:in `expand_path' from (irb):5 from C:/Program Files (x86)/ruby/bin/irb19.bat:20:in `<main>' irb(main):006:0>
問題設定が間違っていたのか? load.cの一行をコメントアウトしたことで、たしかに一つの SecurityErrorは消えたが tDiaryは動かない。20090114p01のエラーがまだ出る。
ただ、20090114のタイトルにちらっと書いた、open-uriの SecurityErrorはでなくなってる。
>irb19 (野良パッチ済み) irb(main):001:0> $SAFE=1 => 1 irb(main):002:0> require 'open-uri' => true irb(main):003:0> open 'http://www.example.com' => #<StringIO:0x2b8e924> irb(main):004:0>
比較として ASRでエラーが出るのを確認する。ただ、ASRでも二回目以降の openはエラーにならない。謎の挙動。この SecurityErrorも本来発生すべきものではないのだろう。
>"C:\Program Files (x86)\ActiveScriptRuby-1.9.1\bin\irb.bat" irb(main):001:0> $SAFE=1 => 1 irb(main):002:0> require 'open-uri' => true irb(main):003:0> open 'http://www.example.com' SecurityError: Insecure operation - write from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:375:in `write' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:375:in `<<' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:375:in `<<' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:322:in `block (3 levels) in open_http' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/protocol.rb:373:in `call_block' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/protocol.rb:364:in `<<' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/protocol.rb:88:in `read' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:2333:in `read_body_0' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:2288:in `read_body' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:321:in `block (2 levels) in open_http' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:1120:in `block in transport_request' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:2251:in `reading_body' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:1119:in `transport_request' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:1103:in `request' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:312:in `block in open_http' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/net/http.rb:564:in `start' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:306:in `open_http' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:767:in `buffer_open' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:203:in `block in open_loop' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:201:in `catch' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:201:in `open_loop' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:146:in `open_uri' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:669:in `open' from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/open-uri.rb:33:in `open' from (irb):3 from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:21:in `<main>' irb(main):004:0> open 'http://www.example.com' => #<StringIO:0x2b611a4> irb(main):005:0>
引き続き rexml/source.rb:16の requireが SecurityErrorになる原因を探る。(tDiaryを起動しないと再現させられないのが辛い)
方針は昨日書いたとおり、プラグインが自由に日記データを取得できる手段を提供した。
日記を一日書いたとたんにエラーということはなくなったみたい。
$SAFE=1で requireが失敗する(ファイル名の untaintもしているのに)のがそもそもおかしい。open-uriや rexmlで同様に requireで SecurityErrorエラーが生じていることからも、疑惑の目がウチの Rubyに向いてきた。「1.9.1RC1だから」ではなく「ウチでコンパイルしたから」、あるいは(開発者に)利用者が少なそうな 「Windows(それも Vista)だから」なのかもしれない。
ASRをインストールしてみたけどダメだった。同じ。tDiaryをセキュアモードで動かしているわけではないので Rubyのセーフレベルは最高でも 1。taintedな文字列を使った requireが失敗するならわかる。でも rexml/source.rbの 16行目は「require 'stringio'」だ。べったべたのリテラルだ。
500 Internal Server Error Insecure operation - require (SecurityError) C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/source.rb:16:in `require' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/source.rb:16:in `create_from' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/parsers/baseparser.rb:146:in `stream=' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/parsers/baseparser.rb:123:in `initialize' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:9:in `new' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:9:in `initialize' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/document.rb:228:in `new' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/document.rb:228:in `build' C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/rexml/document.rb:43:in `initialize' (plugin/amazon.rb):231:in `new' (plugin/amazon.rb):231:in `amazon_get' (plugin/amazon.rb):322:in `isbn_image' (TDiary::Plugin#eval_src):32:in `block in eval_src' Y:/.../server_root/www/ds14050/tdiary_on_ruby191/tdiary.rb:787:in `eval' Y:/.../server_root/www/ds14050/tdiary_on_ruby191/tdiary.rb:787:in `block in eval_src' Y:/.../server_root/www/ds14050/tdiary_on_ruby191/tdiary.rb:112:in `block in safe'
>clipboard
'clipboard' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。 >clip
情報: "CLIP /?" と入力すると使用法が表示されます。 >clip /?
コマンド ライン ツールの出力を Windows クリップボードにリダイレクトします。(やっぱりあるよねー。手コピしなくてすんでよかった。なお XPには……)最終更新: 2015-07-09T23:54+0900
tdiary/trunk (r3394) を ruby 1.9.1 (2008-12-30 patchlevel-0 revision 21203) [i386-mswin32_90] で動かしてみた。
dot.htaccessと tdiary.conf.beginnerを編集&リネームして、トップページの表示と一通りの設定変更を済ませて、記念すべき最初の書き込み。……トップページすら表示されなくなりました。
Insecure operation - require (SecurityError) Y:/.../tdiary_on_ruby191/tdiary.rb:434:in `require' Y:/.../tdiary_on_ruby191/tdiary.rb:434:in `block in load_styles' Y:/.../tdiary_on_ruby191/tdiary.rb:433:in `glob' Y:/.../tdiary_on_ruby191/tdiary.rb:433:in `load_styles' Y:/.../tdiary_on_ruby191/tdiary/defaultio.rb:142:in `initialize' Y:/.../tdiary_on_ruby191/tdiary.rb:1069:in `new' Y:/.../tdiary_on_ruby191/tdiary.rb:1069:in `initialize' Y:/.../tdiary_on_ruby191/tdiary.rb:1660:in `initialize' Y:/.../tdiary_on_ruby191/tdiary.rb:1858:in `initialize' (plugin/recent_list.rb):39:in `new' (plugin/recent_list.rb):39:in `block (3 levels) in recent_list' (plugin/recent_list.rb):37:in `reverse_each' (plugin/recent_list.rb):37:in `block (2 levels) in recent_list' (plugin/recent_list.rb):36:in `reverse_each' (plugin/recent_list.rb):36:in `block in recent_list' (plugin/recent_list.rb):35:in `catch' (plugin/recent_list.rb):35:in `recent_list' (TDiary::Plugin#eval_src):67:in `block in eval_src' Y:/.../tdiary_on_ruby191/tdiary.rb:787:in `eval' Y:/.../tdiary_on_ruby191/tdiary.rb:787:in `block in eval_src' Y:/.../tdiary_on_ruby191/tdiary.rb:112:in `block in safe'
プラグイン:recent_listが原因。(外したら解決した)
$SAFE==1の状況で TDiaryMonth.new()するのがダメっぽい。
recent_list()を呼ばれたときに、そのたびに、TDiaryMonth.new()するんでなくて、読み込まれたときに必要なデータを準備しておけばいいんじゃないか、とか思ったけど、evalで TDiaryMonthクラスにアクセサを追加したりしているあたり*、反則。泥縄の対応では気が済まない。プラグインが日記データを要求できるようなインターフェイスが求められている(現在は TDiaryXXXX#initializeで読み込まれたもののみ、Plugin@diariesからアクセスできる)。然るべき手段を用意したのち、recent_list.rbはそれを利用するべき。
* 歴史的経緯>http://kitaj.no-ip.com/tdiary/20021106.html#p03
正規表現リテラルの /nseuフラグは正規表現のマッチ動作に影響を与える。(/nseuフラグのいずれも指定しなかった場合は実行時の $KCODEに従う)
/nが指定されていたり $KCODE='NONE'のとき、「.」は改行を除いたり改行を含んだりする 1バイトにマッチするメタ文字だが、/seuフラグが指定されていたり $KCODEが SsEeUuのいずれかで始まる文字列のとき、「.」は日本語を含む、Shift_JIS、EUC-JP、UTF-8の一文字(1-3?バイト)にマッチする。
/nseuフラグや $KCODEは正規表現のパターンの解釈にも影響を与える。
Shift_JISで保存したスクリプトファイルに /表w/ というパターンと '表w' という文字列リテラルがあり、マッチを行った場合。実行時に $KCODE='NONE'であればパターンは /\225\w/ と解釈され、"\225"の後にメタ文字 \wにマッチする文字を探し、失敗する。$KCODE='SJIS'であればパターンは /表w/ と解釈され、"表"のあとに "w"を探し、成功する。
irb(main)> /表w/n =~ '表w' => nil irb(main)> /表w/s =~ '表w' => 0
正規表現パターンの中のマルチバイト文字は文字列の場合と同じく、あくまでバイト列であり、/nseuフラグや $KCODEがどうであれ EUC-JPで保存されたスクリプトの中の正規表現リテラル /あ/ は Shift_JISの「あ」を表すバイト列 "\202\240" にマッチすることはない。
最終更新: 2009-09-01T05:05+0900
このようにハイライトされます。
'%04d-%02d-%02d' % [2008, 5, 8]
(整形した)HTMLソースはこう。
<span class="sh_string">'%04d-%02d-%02d'</span> <span class="sh_string">% [2008, </span> <span class="sh_number">5</span> <span class="sh_symbol">,</span> <span class="sh_number">8</span> <span class="sh_cbracket">]</span>
「% [2008, 」が一つの文字列にされてしまっている。どういう判断なのかと調べれば、%!string! と同じものだと見なされていた。(そのルールは自分で書いたんだけども)
知っていたでしょうか? %リテラルの区切りには空白(改行も!)が使えるのでした。(alnumと mbchar以外なら OKっぽい。変態すぎるよ)
気付いたのは日記を書くときに、カテゴリ名入力支援機能(クリックすると本文にカテゴリが挿入される*)のカテゴリリストに目当てのカテゴリがなかったから。
脱線。何かのソースを見たときに思ったのだけど ERB::Util.u も CGI.escape もエンコードしすぎだと感じてる人がいるみたい。(一部の記号をわざわざ復号していた。たしかに %XX が URLに現れるのは美しくない⁑)
閑休。存在するはずのカテゴリファイルがなくてエラーを出していたのは、ここ(20071208p01)で自分が書いた tdiary/categorizedio.rb だったので誰にでも起こる不具合なのか確証がなかったり。
http://tdiary-users.sourceforge.jp/cgi-bin/wforum/wforum.cgi?mode=allread&no=5718&page=0
tDiary標準のカテゴリモードがどのようになるのかは未確認だったり。
複数のポストを日付で括ってしまう tDiary(<日記だから)はどうしても <title>タグの中身が味気なくなってしまって、ボットにも人間にもアピールが弱いな、とか全然関係ないけど、いま思った。(BlogKitでは解決してそう)
ぼそり。(category.rbは @conf.data_pathと 'category'を連結するときにパスセパレータを二重化してる。問題はレンタルサーバ(FreeBSD)でもローカル(Windows)でも起きていないが、そういうのが気持ちわるい&気にしたくないので自分は File.joinや Scripting.FileSystemObject.BuildPathを必ず使う)
最終更新: 2012-01-26T13:29+0900
Rubyに来たときは意識しなかったが、最近 Ruby側から C++を眺めたときにあまりの違いに恐れおののいたこと(限りあるスタックの使いすぎに注意しようね)。
# Ruby myobject = MyClass.new();
// C++ MyClass myobject; MyClass *pmyobject = &myobject;
Rubyでは MyClass.new()で MyClassのインスタンスを作り、それを後から参照するために myobjectという名札を貼り付けている。C++では MyClass myobject; だけで既にインスタンスが存在していて、名札を貼り付ける行為は二行目が相当する。Rubyには myobjectのようにオブジェクトそのものを表す変数は存在しない*⁑⁂。
書いてて思った。ポインタ(に近いもの。参照。C++の参照とは違うもの)はスクリプト言語では普通に使われている*4。Rubyでは C++の myobjectに相当するものがなく、全てのオブジェクトが一段遠くにあるから、C++でやるように (*pmyobject).hoge() や pmyobject->hoge() というようにポインタをデリファレンスする手間を省いて myobject.hoge() という書き方でメソッドを呼べるが、Rubyの myobjectは C++の、myobjectよりむしろポインタの pmyobjectに一番近い。
* Fixnumは例外。
⁑ これが Rubyに ++、--が存在しない理由かとも思ったが、C++で単項インクリメント/デクリメントをメンバ関数でオーバーロードできることを考えると Rubyでやっていけない理由がわからない。Rubyでも ++相当のメソッドを定義できるということだし、全てがオブジェクト(内部状態を持てる)であることを謳っている Rubyだからこそ制約なしにやっても構わないんじゃ。http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/5323。
⁂ いやいやいや、仮に ++/--というメッセージが追加されても Numericはイミュータブルだという理由で使えなければ 99%の利用場面が奪われる。これをなんとかすると ++が +=のシンタックスシュガーになったり、Fixnumがオブジェクトでない(=変数がオブジェクトへの参照でない)ことが露呈したり、a=b=1; ++b; で a が 2 になったりする。これは違う。
*4 C++の &のような、明示的にアドレスを取得する方法がないので、ポインタのポインタは存在しない。
win32/configure.batが生成する Makefileを編集して* ruby19.exeを作るようにしていると ruby-dev:34000 と同じところで止まっていたのでした。
MLのスレッドを読んで、RUBY_SUFFIXだけでなく RUBY_INSTALL_NAMEも反映して欲しいと思ったら、そのように変更されてコミットされていた。それは手元の Makefile.subと同じです。
* configure.batの引数として与える方が人手を介さない分、良さそう。1.8のときに prefixオプションが効かなくて Makefileの直編集に切り替えたのだった気がするが、1.9.0-1では効いていたと思う。(最初、いつも通りにしたら C:/Program Files (x86)/ruby/Program Files (x86)/rubyにインストールされたのは、prefix=と PREFIX=が両方有効だったからだと思う。)
最終更新: 2010-03-22T05:44+0900
著者は ActiveScriptRubyの arton氏。
この本が出た当時、Mysterious SyndromeWindows Scripting Host Laboratoryの管理人むたぐち氏が、言語は Rubyであるが、COMや WSHの話題は VBScriptや JScriptと共通だし、他にこんなに突っ込んだ類書もないので、と(言葉と内容は全然違うが)自身の掲示板でおすすめされていたのをずっと覚えている。
タイミングを逸していただけなのだ。
Rubyの名前を初めて目にしたのもこの時だったかもしれない。(「何か」(当時)の名前を目にしたのもこの掲示板が……。美耳いいよね)
あくまで目にしていただけで、初めての CGIプログラムはサンプルの多い Perlで書いたし、すぐに嫌気がさして代わりの言語を探したときに Rubyを"再"発見している。そのときに、WSHに親しんでいたことと ActiveScriptRubyの存在が Ruby採用のきっかけになった、というのは多分にありそう。
思い出深い一冊ということ。この本を通して、気付かないまま Rubyとすれ違っていたのだから。
リストを使うと途端にそこから文章に構造がなくなってしまうのが困りもので、できるだけ !!(h4)や !!!(h5)を使うようにしていたのだけど、とうとうリストアイテム内で段落を書けるようにいじってしまった。(少し前の変更で取り除かれた \ エスケープが復活している……)
HikiDoc(r90)のリストアイテムに文章構造(段落)を持ち込むための変更
*li1-p1\ \ li1-p2A\ li1-p2B *li2
li1-p1
li1-p2A li1-p2B
<ul> <li><p>li1-p1</p> <p>li1-p2A li1-p2B</p> </li> <li>li2</li> </ul>
行末の \ は見落としやすいので *-、**-、***- を、前行のリストアイテムを継続する、という意味にするのはどうだろう。
HikiDoc(r90)のリストアイテムに文章構造(段落)を持ち込むための変更2 (以前の変更からの差分なので順番に適用する必要がある)
* li1-p1 *- *-li1-p2A *-li1-p2B *li2
li1-p1
li1-p2A li1-p2B
<ul> <li><p>li1-p1</p> <p>li1-p2A li1-p2B</p> </li> <li>li2</li> </ul>
なぜ *+ でなく *- にしたんだろう……。
最終更新: 2016-11-12T11:41+0900
Rubyの、括弧を使った %記法だって。
irb19> re = /%[Qq]?(?<brace>\{[^\{}]*(?:\g<brace>[^\{}]*)*})/ irb19> strings = %w(%{z}a %{a{b}z}c %{a{b}c{d{e}f}z}g %{{{{}}}z}a %{a{b}c %{z}a}b) irb19> strings.each{|str| p str[re] } "%{z}" "%{a{b}z}" "%{a{b}c{d{e}f}z}" "%{{{{}}}z}" nil "%{z}" => ["%{z}a", "%{a{b}z}c", "%{a{b}c{d{e}f}z}g", "%{{{{}}}z}a", "%{a{b}c", "%{z}a}b"]
どの例も正しい範囲( %{ から z} まで)を切り取っているのがわかる。
/%[Qq]?(?<brace>\{(?:[^\{}]++|\g<brace>)*})/
若干速い。同じパターン( [^\{}] )の繰り返しも存在しない。http://fleur.hio.jp/perldoc/perl/5.10.0/pod/perl5100delta.mix.html#Regular_expressions を参考にした。
/%[Qq]?(?<brace>\{(?:[^\{}]+|\g<brace>)*})/
上のものの + が一つ落ちたもの。開き括弧が余分にある文字列を食わせると待てども待てども返ってこない。 http://mlog.euqset.org/archives/ruby-list/42232.html で既に書かれている。それに対する返答が http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/42233 。
最終更新: 2016-11-12T11:41+0900
テキストエディタは、メモ帳、TeraPadときて、現在は SakuraEditorを、もう五年以上使っている。xyzzy(正式な読み方はないらしい。ジッズィと読んでいる。saxyunの読みがサッキュンなのは詐欺だと思います)や Meadowに移る気は無し。
構文ハイライトには興味がなくて、どこかからダウンロードしてきた強調キーワードファイルや正規表現キーワードファイルを使っていた。間違いがあっても正規表現を直したりはせず、オフにするだけ。邪魔にならなければいい程度の扱いだった。
ところが最近 SHJSをいじってたこともあって中途半端なハイライトが許せなくなってしまった。
そのためには鬼車が必要。BREGEXP.dllでは %Q<a<b<c>d<e>f>g> のように入れ子になった括弧の対応を調べられないので。
キーワードファイルはこの日記の SHJS(with カスタマイズ版 sh_ruby.js)を使ったハイライトとコンパチ。ただし完全移植ではない。サクラエディタの正規表現キーワードは正規表現一発で、マッチした全体を特定の配色にするだけだけど、SHJSはパターン中のキャプチャグループごとに配色を分けることができる。サクラエディタの制限で、正規表現が行をまたいでマッチできないことも影響がある。正規表現マッチが行をまたげないのは SHJSも同じなのだが、SHJSは正規表現キーワードから利用できるスタックを用意していて、行を超えて色指定を継続できる。