/ 最近 .rdf 追記 設定 本棚

log[tDiary: 2009-02-23]



20090223()

[Ruby][tDiary]ruby-1.9.1不思議で困ったことが起こった

問題のコ(再掲)はこれあるハッシュのキーについて繰り返しているのにッシュにそのキーが存在しない(すべてのキーが見つからないわけではないが見つからないキーはいつでも見つからな)

categorized.keys.each do |c|
	PStore.new(cache_file(c)).transaction do |db|
		categorized.fetch(c) #=> key not found (KeyError)
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

fetchをブロックの最初に持って行くとそこではエラーにならない

categorized.keys.each do |c|
		categorized.fetch(c) #=> O.K.
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

cache_file(c)の呼び出しが原因その中でも includeしてある ERB::Utilu()メソドが核心

categorized.keys.each do |c|
		::ERB::Util.u(c)
		categorized.fetch(c) #=> key not found (KeyError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

引数にした文字列のエンコングが変わってしまっている

categorized.keys.each do |c|
		enc1 = c.encoding;
		::ERB::Util.u(c)
		enc2 = c.encoding
		categorized.fetch(c) { raise "#{enc1} #{enc2} #{::ERB.version}" } #=> UTF-8 ASCII-8BIT erb.rb [2.1.0 2009-01-11] (RuntimeError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

ERB::Util.url_encodeの定義を見ると引数の文字列を dupした後にエンコングを変更しているにも関わらず呼び出し元に影響を与えてしまっている

    def url_encode(s)
      s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
        sprintf("%%%02X", $&.unpack("C")[0])
      }
    end
    alias u url_encode

そんなわけだから呼び出し側(category.rb)

u( c.dup )

なんてやっても効果はなく

u( ""+c )

あるいは

u( "#{c}" )

とやって初めて今回の現象を回避することができた

これは、文字列の複製を遅らせた結果期せずしておこった現象にみえる

バグのはずなんだけどirbで再現しようと思ってもできないんだこれ


 追記@2009-08-13: 見る人が見れば修正はあっという間でした

http://redmine.ruby-lang.org/issues/show/1929

(ここに見るべき場所を見つけることもできなかった人間がひと)

* 正しくは ruby-1.9.2dev(2009-02-03)


20090215() 本文中の URL自動リンクがセミコロンで切れていたので/shjs/lang/sh_ruby.js/shjs/lang/sh_javascript.jsを修正したそこで使っていた正規表現『詳説 正規表現 第3大抵の場合うまくいくと紹介されていたものでした(CGIパラメータを ; で区切るのはいまだに異端でした)

[Ruby][tDiary] ruby-1.9.1*不思議で困ったことが起こった

この断片で理解してもらえるだろう

categorized.keys.each do |c|
	PStore.new(cache_file(c)).transaction do |db|
		categorized.fetch(c) #=> key not found (KeyError)
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

あるハッシュのキーについて繰り返しているのにッシュにはそのキーが存在しないというこの不思議

このときc

"\xE6\x9C\xAC\xE6\x97\xA5\xE3\x81\xAE\xE8\xB3\xBC\xE5\x85\xA5" ASCII-8BIT

ッシュのキーリトとそのエンコングは

"\xE6\x9C\xAC\xE6\x97\xA5\xE3\x81\xAE\xE8\xB3\xBC\xE5\x85\xA5" ASCII-8BIT
"本" UTF-8
"マンガ" UTF-8
"雑誌" UTF-8

存在しているだろうに……

 追記@2009-02-20: 同じ目に遭っている人がいた

さくらインターネト上で tDiaryruby1.9.1-p0 で動かす - まちゅダイアリ(2009-02-19)(14:57現在日別表示が不可能な状態最新表示は可)

* 正しくは ruby-1.9.2dev(2009-02-03)


20090212() ruby-1.8.7も最近 p0から p72にしましたそれ以上のはコンパイルできませんでしたおとなしくリリースを待ちます。

[tDiary] tDiary2.3.0.20080302から 2.3.1.20090129へアップデ

手動で migrate.rbを実行して UTF-8化してあったのに再度 90migrate.rbが走ってしまってータが壊れた慌てず ZIPァイルを解凍して元通り

grepと同じ程度に簡単にータファイルや tdiary.confのバージョンナンバーをすべて書き換える方法(sed?)が思いつかなかったのでtdiary/lang/ja.rbmigrate_to_utf8を無効化して済ませた

def migrate_to_utf8( str )
	return str
	to_native( str, 'EUC-JP' )
end

素通しとはいえ migrationは実行されるので数十から百ちかい数のファイルを開いて書き込んで閉じてといった負荷をレンタルサーバーにかけたーカルでは一分以上かかった

 2.3.1になってカテゴリが大文字小文字の区別なくソトされる*

のが嬉しい気になっていてっぽど自分でやってやろうかと思っていたので

 古い tdiary.confを引き継ぐと

@accesskey_enabledの設定が存在しない(=>nil => falseと判断される)ためにアクセスキーがなくなってしまって戸惑ったここはデフトを過去と互換にして欲しかった(設定名を @disable_accesskeyにするとか)いまさらだけど

 category.rbnilにアクセスして NoMethodErrorを出すと思ったら

NaviUserCGIが木偶だからだった原因は category.rbにはなくできの悪い CGIのモックを渡した navi_user.rbにある

 エラーを出した category.rbのコ
class Info
	include ERB::Util

	def initialize(cgi, years, conf, args = {})
		@cgi = cgi
		@years = years
		@conf = conf
		@category = args[:category] || @cgi.params['category']
		@year = args[:year] || @cgi.params['year'][0] #=> NoMethodError: undefined method `[]' for nil:NilClass
 NaviUserCGIの定義
class NaviUserCGI
	attr_reader :params, :referer, :user_agent
	def initialize(datestr)
		@params = {'date' => [datestr]} # <<<注目!
		@referer = nil
		@user_agent = nil
	end

	def request_method
		'GET'
	end
end

オリジナルの CGI#paramsは単一のデフト値( [].freeze )を持った Hashなんだよね……

navi_user.rbrecent_list.rbと同じように書き換えてやろう

* 一か所大文字も小文字も存在しない配列のソトを普通のソトに戻しました


20090209() すでに世の中一般人も RSSです……よ?

[tDiary]ーマ自作 > badboy2007.css

screenshot (theme: badboy2007)

自分好みの見た目に拘るようになるにつれ既存のテーマから得られる部分が減り打ち消す手間が目立ってきたそろそろ一から積み上げる方が楽だと感じたので

公開されるテーマは汎用性を求められるぶん個人的には冗長だったりかゆいところに手が届かなくて CSSを追加したりする必要があったりするが公開を前提としない自作なら十分かつ必要最小限なものになる(この現状を十分とは口が裂けても言えないけれ)

以下備忘録としてスタイルを決めた際のポイトを(すごく雑)

  • タイヤの下には地面
  • 「ツッコミを入れるリンクの目的は移動ではなくアクションなのでボタンっぽく
  • 「ツッコミを入れる前後の [角かっこ]skel/diary.rhtmlから削除(ナビゲーションリンクの &laquo;, &raquo;も削除しています。なんでラベルに含めないんだろ今なら CSScontentも広く使えるのに文字のハドコングは不便)
  • IE8RC1のデフトスタイルシトは<pre>の文字を小さくするので抵抗した
  • 引用文は自分の書いた文章ではないので異物感
  • 引用の中のPREはそれとわからないように(実験)
  • 色の決定には色名に対する好みが多分に入っている(好き > navy, crimson)

ッダとフッタに関してもポイトを(未来の自分が思い出せるよう)

  • 日記著者向けのリンク(追記など)目立たないように閲覧者向けのナビゲーションリンクと混ぜないように(ージ最下部でも良)
  • 目次はスクロールの必要なく一画面に収まるように(ージンとヘッダの内容と表示日数を削)
  • ップに前後方向のナビゲーションはいらない(目次の下とページ最下部に置いてみまし)
  • フラトなカレンダーを先頭に置くと Tabーによるフーカス移動が大変(カレンダーはページ最下部にとりあえず放り込みまし)

古い日記はレイアトが崩れてるかも過去の日記の凍結(ッダッタプラグインの出力を日記執筆時点のものに固定)という名の HTML書き出し機能が欲しい

実は squeeze.rbを少し変更してヘッダッタを含む HTMLを書き出しmod_rewriteを使ってその HTMLァイルが存在するときはそちらを参照するように .htaccessで設定したりしていた

RewriteEngine on
RewriteBase /ds14050/diary

# Rewrite rule1
#  shows static html, if exists.
RewriteCond /home/vvvvvv/www/cgi_file/ds14050/diary/snap/$1.html -f
RewriteCond %{REQUEST_METHOD} =GET [OR]
RewriteCond %{REQUEST_METHOD} =HEAD
RewriteCond %{HTTP:Cache-Control} !=no-cache [nocase]
RewriteRule ^([0-9]{8})\.html$ /cgi_file/ds14050/diary/snap/$1.html [L]

でも静的 HTMLをブラウザが直接参照するので tDiaryが起動せずリファラの記録が行われなくなるし多分ツッコミ(トラックバック)が入るだけで HTMLが新しく生成されてしまう翌日の日記へのナビゲーションリンクも基本的に出ないッコミの読み込みとリファラの記録を静的 HTMLに埋め込んだ JavaScriptで行うことで内容を最新に保ちつつ HTMLの生成を抑制できるが実際にやってみるほどのメリトを見いだせず。スクリトを実行しないブラウザ対応もパッと思いつかない(使える道具って<script><noscript>だけなのだろうコメト部を別 HTMLァイルとして保存して SSIで埋め込むとか……ーむ)


20090202() [Vista] リソース モニタのキーボドインターフェイ: P(CPU項目を展開)D(スク項目を展開)N(トワーク項目を展開)M(メモリ項目を展開)L(全て展開)Shift+P,D,N,M,L(それぞれの項目を展開折り畳み切り替)

[Ruby][tDiary] tDiary1.9系の Rubyでは 1.9.2から動くようになるの

やっぱり nobuさんがやってくれました。

requireの処理の中でーフレベルを一時的に 0 に下げる部分があってこの範囲を広げることでSecurityErrorが出ないようになっていた(3)

画像はtDiaryamazon.rbリポトリから持ってきただけの素の Ruby-1.9.2dev(2009-02-03)上で動いているところ

既に正式版がリリースされて*しまって*いる Ruby-1.9.1との違いを、先月の日記に書いた例で見ていくと

 $SAFE=1カレトリのスクリトを requireしたとき

irb192> RUBY_DESCRIPTION
=> "ruby 1.9.2dev (2009-02-03) [i386-mswin32_90]"
irb192> $SAFE=1
=> 1
irb192> require "a"
SecurityError: cannot load from insecure path - Y:/.../Desktop/a.rb
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192> require "a.rb"
SecurityError: cannot load from insecure path - Y:/.../Desktop/a.rb
        from (irb):4:in `require'
        from (irb):4
        from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192>

2009-02-03版の ruby-1.9.2devでは$SAFE=1のときカレトリのスクリトを requireできないこれは $:($LOAD_PATH)に汚染されていない "." が含まれていようとrequire の引数の文字列が汚染されていなかろうとrequireできない見つけた抜け道は絶対パスで requireするか$:($LOAD_PATH)にカレトリを絶対パスで追加すること("."が含まれる場合はそれより前に追加する必要もある)

ruby-1.9.1の結果は Release Candidateのときと変わらず

irb191> RUBY_DESCRIPTION
=> "ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32]"
irb191> $SAFE=1
=> 1
irb191> require "a"
SecurityError: Insecure operation - require
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> require "a.rb"
a.rb required.
=> true
irb191>

ruby-1.9.1では拡張子を付けてやるとカレトリのスクリトも requireできる拡張子を付けないときに requireできないのは ruby-1.9.2devも同じだが ruby-1.9.1には ruby-1.9.2devにない爆弾がある$SAFE=1のときの拡張子を付けない require添付ライブラリの requireであっても失敗したりする

irb191> $SAFE=1
=> 1
irb191> require "stringio"
SecurityError: Insecure operation - require
        from (irb):2:in `require'
        from (irb):2
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> require "stringio.so"
=> true
irb191>

これが原因でtDiaryruby-1.9.1で動かすのは絶望的だと思っている*(ruby-1.9.1はリリースされちったしスクリトで対応できる範囲を超えているか)

この部分は SecurityErrorが出ない方向に修正されると思っていたからruby-1.9.2devで両方のパターンが SecurityErrorになったのは意外

 $SAFE=1汚染されたパスが $:($LOAD_PATH)に含まれるとき

ruby-1.9.2devでは汚染されたパスが $:($LOAD_PATH)のどの位置にあるかが重要

irb192> $SAFE=1
=> 1
irb192> $:.unshift "!tainted!".taint
=> ["!tainted!", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2/i386-mswin32_90", "."]
irb192> require "cgi"
SecurityError: cannot load from insecure path - Y:/.../Desktop/!tainted!/cgi.rb
       from (irb):3:in `require'
       from (irb):3
       from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192> $:.push $:.shift
=> ["C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2/i386-mswin32_90", ".", "!tainted!"]
irb192> require "cgi"
=> true
irb192>

ruby-1.9.2devでは$SAFE=1汚染された LOAD_PATHからスクリトを requireすることはできないが汚染されていない LOAD_PATHからスクリトを先に見つけた場合はrequireに成功するruby-1.9.1(ruby-1.8.7-p72)ではどうだったかというとより厳しくて

irb191> $SAFE=1
=> 1
irb191> $:.unshift "!tainted!".taint
=> ["!tainted!", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/i386-mswin32", "."]
irb191> require "cgi"
SecurityError: Insecure operation - require
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> $:.push $:.shift
=> ["C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/i386-mswin32", ".", "!tainted!"]
irb191> require "cgi"
SecurityError: Insecure operation - require
        from (irb):5:in `require'
        from (irb):5
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191>

ruby-1.9.1では汚染されたパスが一つでも $:($LOAD_PATH)に含まれると(相対パスで) requireはできない絶対パスならできるがそんな書き方はしないので $:($LOAD_PATH)に追加するパスは常に untaintしなければならない

 ruby-1.9.2dev(2009-02-03)は概ね期待通りの動作だが……

requireしたときのカレトリの扱いに不満が残る

多分従来の Rubyruby-1.9.1ruby-1.8.7$:($LOAD_PATH)の要素の汚染状況なんて気にしていなかった$:に含まれるか含まれないかだけが重要2005年から現在まで変わっていないリファレスマニュアルのこの記述がそれを物語っていない

Level 1以上では起動時に以下の違いがある

  • 環境変数 RUBYLIB$: に加えない
  • カレトリを $: に加えない
  • (以下)

その方針に異議を唱えるものではないけれどこの方式にはーフレベルによる分岐が起動時に限定されるという制限があるコマドラインオプション -T を指定したときにしか有効にならず$SAFEを使ってセーフレベルをコトロールするシナリオでは機能しない

ruby-1.9.2dev$:($LOAD_PATH) の要素の汚染状況に注目することで$SAFEを使ってセールレベルをコトロールする場合で「環境変数 RUBYLIB$: に加えない「カレトリを $: に加えないのと同等の制限を課せる可能性を持っているつまり「環境変数RUBYLIBとカレトリは常に $:($LOAD_PATH)に追加されるただし汚染された状態でということ

それなのに現在の ruby-1.9.2dev$SAFE=1の下での requireに対するカレトリの扱いはruby-1.8.7よりむしろ退化している

ruby-1.8.7では $:($LOAD_PATH)"." を追加したり取り除いたりすることでカレトリの扱いをーフレベルによらずスクリトがコトロールできた

拡張子の有無で結果が変わる動作に筋の通らない ruby-1.9.1requireは論外として

ruby-1.9.2devではカレトリのスクリトの require$:($LOAD_PATH)によらずSecurityErrorになるカレトリを絶対パスで $:($LOAD_PATH)に追加することでコトロール可能だが既に含まれているかもしれない "." が邪魔をするruby-1.9.2dev$:($LOAD_PATH)に含まれる "." の汚染状況(あるいは "."が $:に含まれないこと)によってのみカレトリの扱いを変えるべきでカレトリが特別に SecurityErrorになる現在の ruby-1.9.2devには同意できない

ールレベル1ではまだスクリトを信用しているのだから少なくとも ruby-1.8.7と同等のコトロールをスクリトに渡して欲しい

requireが利用する File.expand_pathの仕様によりカレトリからの相対パスが汚染されるのだろうがFile.expand_pathrequire$:($LOAD_PATH)に依拠していることを知らないのだから requireが何とかすべき

* その後の変更でruby-1.9.1らしき挙動の requireを検出したときはセーフレベルを 1から 0に下げてプラグインを実行することになっているーフレベル0なら今回のことは関係ないからーフレベルを下げるという発想は全く頭になかったなんかこう負けた気がするからだろうruby-1.9.0だとセキュアモ(ーフレベル4)で動かないという話もあったけどどうなったんだろう


20090122() Ruby-1.9.1-RC2出ました

[tDiary] tDiary on Ruby-1.9.1-rc2 -> Encoding::CompatibilityError

#<Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT>
(plugin/00default.rb):571:in `comment_form_text'
(plugin/00default.rb):616:in `comment_form'
(TDiary::Plugin#eval_src):79: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'

なにが ASCII-8BITったかというと Cookie

plugin/00default.rb:575: #{comment_name_label}:<input class="field" name="name" value="#{h( @conf.to_native(@cgi.cookies['tdiary'][0] || '' ))}">

ならばと UTF-8への変換を試みたならば

@cgi.cookies['tdiary'][1].encode("utf-8")
#=> #<Encoding::UndefinedConversionError: "\xE3" from ASCII-8BIT to UTF-8>

ッキーみたいに何が送られてくるかわからないものは慎重に慎重にエラーに備えて取り扱わないといけないということですね(面倒くさいな)

CGIパラメータなんかも取り扱い注意だよねcgi.rbの支援はないのかな?(他力本)


 補足エラーの原因の心当たり

Testing tDiary on Ruby1.9.1と題した日記にも関わらず少しの間っかり 1.8.7で動かしていたそのせいでキッシュが原因のエラーが出たしッシュを削除したら今度はクッキーが原因のエラーが出たという次第

ーバーの Ruby1.8.7から 1.9.1にアップデトしたタイミングでそのサーバーの日記を閲覧できなくなる人(過去3か月間にコメトした人限定)が続出ないだろう


 追記@2009-01-24: Ruby-1.9での cgi.rbとその代替(Rack)

cgi.rbも変わっていたのでした

どちらも日付が今日(2009-01-24)だ! Googleクローリング早い

tDiaryの文脈で Rackの名前を見かけてたんだけど名前から Rakeのようなものを想像していたWeb方面だったのね


20090119() Wassrという Webービスがあってそこに tDiaryというチャンネルがあってFirefoxにはライブブックマークとかいうものがあっていろいろなものを発見(コミトログの確認が svk sync + viewvcより簡単だ古い記事がちょこちょこ投稿されると思ったら delicious..から tDiaryタグの付いた URLを拾っているとほへ)

[Ruby][tDiary] require$SAFE=1と汚染された $LOAD_PATH

>irb
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 1.8.7 (2008-05-31 patchlevel 0) [i386-mswin32_90]"
irb(main):002:0> $SAFE=1
=> 1
irb(main):003:0> $:.unshift "hoge".taint
=> ["hoge", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8",..., "."]
irb(main):004:0> require 'cgi'
SecurityError: Insecure operation - require
        from (irb):4:in `require'
        from (irb):4
        from :0
irb(main):005:0>

1.8.7でもこうなのだから知らない俺が抜けているのだが$SAFE=1のときに汚染された文字列を $LOAD_PATHに追加する(pushでも unshiftでも)一切の requireができなくなる

期待したいのはhoge/cgi.rbhoge/cgi.soなどが存在するときにはこのパスは汚染されているので SecurityError存在しないときはファイルの探索を続けて C:/Program Files (x86)/ruby/lib/ruby/1.8/cgi.rb (このパスは汚染されていないはず)を読み込むという動作なのだけど……

実際はそうではないのだから tDiary

tdiary.rb:12: $:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' )

というのは __FILE__ が汚染されているときにわりと危険な操作ということになる問題が起きないのは SAKURAのレンタルサーバの Ruby1.8.6だからなのか__FILE__File.dirname(__FILE__) が汚染されていることが稀だからなの(汚染されていることが実際にあるのは、20090117p01で書いたようにuntaintすることで状況が改善したことから推測でき)


問題が起きないのは SAKURAのレンタルサーバの Ruby1.8.6だからなのか__FILE__File.dirname(__FILE__) が汚染されていることが稀だからなの

両方でした__FILE__が汚染されているのは Ruby-1.9.1RC1だから(多分)


$SAFE=1のときに汚染された文字列を $LOAD_PATHに追加する(pushでも unshiftでも)と、一切の requireができなくなる

書きながら誇張だとは気付いていたのだけど(一切のの部分が)そうでない例を自分で見つけたので追記(2009-02-02)

Windowsフルパスであるいは拡張子(.rb)なしのフルパスでなら requireできる

Y:\...\Desktop\a>irb
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 1.8.7 (2008-05-31 patchlevel 0) [i386-mswin32_90]"
irb(main):002:0> $SAFE=1
=> 1
irb(main):003:0> $:.push "".taint
=> ["C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby/1.8/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/1.8/i386-mswin32_90", ".", ""]
irb(main):004:0> require "a"
SecurityError: Insecure operation - require
        from (irb):4:in `require'
        from (irb):4
        from :0
irb(main):005:0> require "a.rb"
SecurityError: Insecure operation - require
        from (irb):5:in `require'
        from (irb):5
        from :0
irb(main):006:0> require "./a.rb"
SecurityError: Insecure operation - require
        from (irb):6:in `require'
        from (irb):6
        from :0
irb(main):007:0> require "Y:/.../Desktop/a/a"
=> true
irb(main):008:0> require "Y:/.../Desktop/a/a.rb"
=> false
irb(main):009:0> require "a"
SecurityError: Insecure operation - require
        from (irb):9:in `require'
        from (irb):9
        from :0
irb(main):010:0>

20090117()

[Ruby][tDiary] 昨日(「引き続き rexml/source.rb:16requireSecurityErrorになる原因を探る)の続き

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.1SecurityErrorを量産する 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.c501行目をコメトアトした 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' )

今回の一連の流れ(20090113p0120090114p0120090116p01)$SAFE=1SecurityErrorで使い物にならなくなる(>添付ライブラリの 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_pathSecurityErrorを出すのは正しいのかも(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_pathfile_expand_pathに仕事を丸投げする rb_file_expand_pathでセーフレベルに基づくチックを行うのが呼び出し側にとって便利だと思う

tDiaryのプラグインの recent_list.rbを書き換えたのは今思えば不要だったみたいだ(Rubyの方が変わるに違いないも)


20090116()

[Ruby][tDiary] Ruby1.9.1RC1Insecure Operation - require (SecurityError)が頻発する原因

20090113p0120090114p01で発生したエラーを起こす最小のスクリトとそれを回避する方法

>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_pathfile_expand_pathを呼びその結果を tmpにコピーしてくれている二度目を呼ぶ必要はないのでは? rb_file_expand_pathは適宜汚染されたStringオブジトを返しまた $SAFE>0のとき汚染された引数を SecurityErrorで拒絶するので複数回の (rb_)file_expand_path呼び出しは容易に SecurityErrorを引き起こす。これは Ruby1.9.1Ruby1.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-uriSecurityErrorはでなくなってる

>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:16requireSecurityErrorになる原因を探る(tDiaryを起動しないと再現させられないのが辛)


20090114() $SAFE=1だと添付ライブラリ(open-uri)SecurityErrorを出しまくるんだけど……260行目の require 'net/http' で出る375行目の StringIOに書き込むところでも出る破綻してる気がする

[tDiary][Ruby] 昨日のつづきrecent_listを実際に修正

方針は昨日書いたとおりプラグインが自由に日記データを取得できる手段を提供した

日記を一日書いたとたんにエラーということはなくなったみたい


$SAFE=1requireが失敗する(ァイル名の untaintもしているのに)のがそもそもおかしいopen-urirexmlで同様に requireSecurityErrorエラーが生じていることからも疑惑の目がウチの Rubyに向いてきた1.9.1RC1だからではな「ウチでコンパイルしたからあるいは(開発者に)利用者が少なそうな Windows(それも Vista)だからなのかもしれない


ASRをイールしてみたけどダメだった同じtDiaryをセキュアモドで動かしているわけではないので Rubyのセーフレベルは最高でも 1taintedな文字列を使った requireが失敗するならわかるでも rexml/source.rb16行目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'

20090113() [Vista] >clipboard 'clipboard'内部コマドまたは外部コマ操作可能なプログラムまたはバッチ ファイルとして認識されていません >clip: "CLIP /?" と入力すると使用法が表示されます。 >clip /? コマド ライン ツールの出力を Windows クリップボドにリダイレトします。(っぱりあるよね手コピしなくてすんでよかったなお XPには…)

最終更: 2015-07-09T23:54+0900

[tDiary][Ruby] Insecure operation - require (SecurityError)

tdiary/trunk (r3394)ruby 1.9.1 (2008-12-30 patchlevel-0 revision 21203) [i386-mswin32_90] で動かしてみた

dot.htaccesstdiary.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()するんでなくて読み込まれたときに必要なデータを準備しておけばいいんじゃないかとか思ったけどevalTDiaryMonthクラスにアクセサを追加したりしているあたり*反則泥縄の対応では気が済まないプラグインが日記データを要求できるようなインターフェイスが求められている(現在は TDiaryXXXX#initializeで読み込まれたもののみPlugin@diariesからアクセスできる)然るべき手段を用意したのちrecent_list.rbはそれを利用するべき

* 歴史的経緯>http://kitaj.no-ip.com/tdiary/20021106.html#p03


20081119()

[][tDiary] 洋書の書影を出すのは難しいな

映画でもハンバト ハンバトを演じたジェレミー アイアンズが朗読します。驚きの CD10枚組その収録時間や 11時間半トパフーマス高すぎです。

本当は子供向けの Audiobookを探していたのです。不思議の国のアリスとか赤毛のアンとか秘密の花園を狙っています。アリスは言い回しが難しそうなのでまずはこの Anne of Green Gables3枚組 4時間朗読ではなくBGMありトありドラマCDきかん気が強そうで口の減らなそうなアンの声が素敵

SearchIndexBooks決めうちではなく ForeignBooksとの二択にする必要があるのだけど978-4-*********Foreignか否かはどの国の Amazonを利用するつもりかで変わってくるとりあえず Amazon.co.jpの利用を前提とした変更を amazon.rbに施して書影の表示にこぎ着けた(さらにISBN-13の頭が 978だけしかない期間限定の対応だけ)

	url << "&SearchIndex=#{'Foreign' if /\A(978)?4/ !~ asin}Books" if id_type == 'ISBN'

20080718() 二重ブラケトの中でもマークアップが使えるところで |\ でエスケープできるんだけど \ が消費されない……

[tDiary][Hiki] 引用元の URLと説明を HikiDocで書けるように

こう書くと

""[[http://vvvvvv.sakura.ne.jp]]
""どこからの引用だかわかるでしょうか?
""
""すくなくとも Firefox3、Safari3.1、Opera9.50ではわかるはずですが、IE7では無理です。

こうなる

どこからの引用だかわかるでしょうか?

すくなくとも Firefox3Safari3.1Opera9.50ではわかるはずですがIE7では無理です。

http://vvvvvv.sakura.ne.jp/

HTMLはこんな感じになっている

<blockquote cite="http://vvvvvv.sakura.ne.jp">...</blockquote>

スタイルシトはこう残念な子 IE7contentをサポトしていないのが敗因

.section blockquote[cite]:after,
.section blockquote[title]:after {
  content: "引用元: "attr(title)" "attr(cite); /* ハイパーリンクにしたい。マークアップもしたい。 */
  display: block;
  text-align: right;
  font-style: oblique;
  background-color: #F3F9FF;
}

引用の最初の行が二重ブラケトリンクだけだった場合に限りその中身を <blockquote>cite/title属性として扱うこういうパターンがあり得る

 URLANDTITLE
URLANDTITLE
 TITLEONLY
TITLEONLY
 http://URLONLY
http://urlonly/

add_cite_and_title_to_blockquote3.diff