青山です。

On Tue, 22 Feb 2000 03:15:47 +0900,
Tomoyuki Kosimizu <greentea / fa2.so-net.ne.jp> wrote:

> > # URIModule::URI.escape in uri.rbとCGI.escape in cgi.rb(bundled),
> > # さてどっちを使うべきか.
> 
> 私のほうを削りましょうか? もともとCGIに関係する機能に思えますし。ただ、
> cgi.rbでは' 'を'+'に置換してくれないみたいですけども。

再検討します。

RFC1866 section 8.2.1
>        1. The form field names and values are escaped: space
>        characters are replaced by `+', and then reserved characters
>        are escaped as per [URL]; that is, non-alphanumeric

つまり、' ' の '+' への置換は、CGI の form field においてのものであり、
URL escape の担当ではありません。

URL encode については RFC1738 section 2.2 にあり、それを元にした
URI::Escape::uri_escape() によると、対象の正規表現は次のようです。

/[\x00-\x20\"#%;<>?{}|\\^~`\[\]\x7F-\xFF]/
--> /[^0-9A-Za-z$\-_.+!*\'(),\/:=@&]/

RFC1738 section 2.2
>   Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
>   reserved characters used for their reserved purposes may be used
>   unencoded within a URL.
reserved charecters:  ";", "/", "?", ":", "@", "=" and "&"
(上の正規表現において ";", "?" が外されている理由については不明)

という事で、' ' は対象に含まれ、'%20' へと置換されます。

これらの事から、CGI の form field では '+' となり、それ以外では '%20'
となるわけですが、CGI 1.1 では unescape のさいに '+', '%20' どちらも
' ' にしろとあり、どうやら '%20' でも良さそうです。

また、CGI.pm, URI::URL::http::query_form() ともに '+' ではなく、'%20'
へ変換しています。

以上の事より、uri.rb, cgi.rb ともに、こんな感じでいかがでしょう。

def escape(string)
  string.gsub(/([\x00-\x20\"#%;<>?{}|\\^~`\[\]\x7F-\xFF])/n) do
    sprintf("%%%02X", $1.unpack("C")[0])
  end
end

' ' の扱いはおそらくこれで OK と思われますが、";", "?" がエスケープの
対象に含まれているのが気になりますね。URI::URL の reverved にはあるの
ですが。まあ、CGI.pm では /([^a-zA-Z0-9_.-])/ 程度ですし、あまり問題は
無さそうではありますが。


-- 
青山 和光 Wakou Aoyama <wakou / fsinet.or.jp>