artonです。 Ruby 1.8.7-p22で、2点あります。 1つは、tempfile.rbで、$SAFE >= 2の場合にTempfile.newがRuntimeErrorで失敗 するのが意図的かどうかの確認です。 C:\home\arton\>ruby -rtempfile -e '$SAFE=2;Tempfile.new("test")' c:/home/ruby/lib/ruby/1.8/tempfile.rb:52:in `initialize': cannot generate tempfi le `' (RuntimeError) from -e:1:in `new' from -e:1 もし意図的でなければ、$SAFEが2の場合にはTempfile.newは成功して欲しいです。 Fileクラスは与えられたファイル名がtaintでなければ、$SAFEが4より小さけれ ばファイルの作成を許していますが、Tempfileのファイル名は安全なはずなので、 同様であってほしいと思います。具体的にやりたいことは、open-uriを使った Webサイトからのコンテンツ読み込みです。 なお、RuntimeErrorとなる原因は、ファイル名生成のときに呼び出すmake_tmpname で、$$を利用してpid($SAFE=2でSecurityError)を取得しようとしているため、 get_pidが、$SAFE>=2でSecurityErrorとしているからです。このためファイル名 が生成されていない状態でファイルを作成しようとして、RuntimeErrorとなりま す。 2点目は、Windows Vista以降のWindows固有の現象ですが、$SAFE>0の場合の tmpdir.rbのDir::tmpdirの挙動というか設定があまりうまくありません。 具体的には、$SAFE>0のため、環境変数を参照せずに安全なテンポラリディレク トリを得ようという意図だとは思いますが、@@systmpdirを利用しています。 で、@@systemdirとして、Win32 APIで取得したWindowsディレクトリ内のTempディ レクトリを設定していますが、このディレクトリは、Windows Vistaでは管理者権限のみ アクセス可能で、一般のユーザーは読み書きできません。 C:\home\arton>ruby -rtmpdir -e 'p Dir::tmpdir' "C:/Users/arton/AppData/Local/Temp" C:\home\arton>ruby -rtmpdir -e '$SAFE=1; p Dir::tmpdir' "C:/Windows/Temp" Windows側の意図と、元のtmpdirの意図を、尊重するならば、ユーザー固有のテ ンポラリディレクトリを、Win32 APIで取得するのがあるべき姿ではないでしょ うか。 というわけで、以下にtmpdir.rbのパッチを添付します。 SHGetFolderPath APIで現在のユーザーの専用ディレクトリを得るようにしてい ます。SHGetFolderPath APIが取れない場合(古いWindows)については、従来の動 作となるようにしています。 diff -u tmpdir.rb.org tmpdir.rb --- tmpdir.rb.org Sun Jun 29 02:20:44 2008 +++ tmpdir.rb Sun Jun 29 02:47:54 2008 @@ -9,18 +9,25 @@ class Dir @@systmpdir = '/tmp' - + CSIDL_LOCAL_APPDATA = 0x001c + begin require 'Win32API' max_pathlen = 260 windir = ' '*(max_pathlen+1) begin - getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L') + getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L') + raise RuntimeError if getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir) != 0 + windir = File.expand_path(windir.rstrip) rescue RuntimeError - getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L') + begin + getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L') + rescue RuntimeError + getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L') + end + len = getdir.call(windir, windir.size) + windir = File.expand_path(windir[0, len]) end - len = getdir.call(windir, windir.size) - windir = File.expand_path(windir[0, len]) temp = File.join(windir, 'temp') @@systmpdir = temp if File.directory?(temp) and File.writable?(temp) rescue LoadError パッチ後は、$SAFE=0の従来の値と同じものになりますが、TMP環境変数の設定に は影響されないことで確認できます。 C:\home\arton\test>set TMP=c:\home\arton\test C:\home\arton\test>ruby -rtmpdir -e '$SAFE=1;p Dir::tmpdir' "C:/Users/arton/AppData/Local/Temp" もっとも、Ruby-1.9.0-01だと、Tempfile.newもDir::tmpdirも、$SAFE>0では、 いずれもFile.expand_pathに引っかかってSecurityErrorになります。 できれば、こちらも動いて欲しいです。 -- arton <artonx / yahoo.co.jp> -------------------------------------- Power up the Internet with Yahoo! Toolbar. http://pr.mail.yahoo.co.jp/toolbar/