読者です 読者をやめる 読者になる 読者になる

CGI::unescapeの改良

Ruby cgi.rb

いずれ”るりま”かどこかへ反映させたいので、
メモのためにcgi.rbの改良のことを書いていきたいと思います。
 
id:h-sbtの人からクッキーがascii-8bitで
返ってくると言われまして、
そういやそうだったと思い出しました。
(放置していました。すみません。)
で、たどっていったところ、
unescapeがascii-8bitで返すというのがわかってきました。
考えてみると、escapeというのはus-asciiでは
表現できない文字列(バイト列)を後でまた元に戻すために
us-asciiに変換するためのものなので、
戻すときにencodingを指定するのが
ruby-1.9では自然なんだと思います。
というわけで、パッチを書いてみました。
optionでencodingを渡せるようにしています。
encodingがわたらなかった場合はクラス変数の@@accept_charsetで
encodingの変更を試みます。正しくなかったときは
ascii-8bitで返します。
@@accept_charsetのデフォルト値はUTF-8です。

Index: lib/cgi/util.rb
===================================================================
--- lib/cgi/util.rb	(revision 24163)
+++ lib/cgi/util.rb	(working copy)
@@ -12,11 +12,13 @@
   # URL-decode a string.
   #   string = CGI::unescape("%27Stop%21%27+said+Fred")
   #      # => "'Stop!' said Fred"
-  def CGI::unescape(string)
-    enc = string.encoding
-    string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
-      [$1.delete('%')].pack('H*').force_encoding(enc)
-    end
+  def CGI::unescape(string,encoding=@@accept_charset)
+    str=string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
+      [$1.delete('%')].pack('H*')
+    end.force_encoding(encoding)
+    str.valid_encoding? ? str : str.force_encoding(Encoding::ASCII_8BIT)
+    
+
   end
 
   TABLE_FOR_ESCAPE_HTML__ = {
Index: lib/cgi/cookie.rb

追記1

valid_encoding?にオプションを渡せるようにしたいなぁ。
提案してみよう。現状はforce_encodingしないとvalidチェックをできないので。

追記2

オプションを与えなかった場合はwarningを出すというのもありかなぁ。。。