From: Tomoyuki Kosimizu Date: 2000-04-02T06:14:31+09:00 Subject: [ruby-list:21727] Re: Where is http-access.rb? 越水です。 PerlのURI::Escape.pm (v3.13)では: # Default unsafe characters. (RFC 2396 ^uric) $text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/$escapes{$1}/g; となっています。コメントにあるuricというのは: uric = reserved | unreserved | escaped reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," unreserved = alphanum | mark mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" escaped = "%" hex hex となっています。コードを見たのですが、実際にはescapedをさらにエスケー プするようです。これはこれで実用上は構わないのでしょう。 ところで、IPv6のURLを定めているRFC 2732では、`['と`]'をreservedに移し ています。それを考慮して、上のEscape.pmのコードを直すと: $text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()\[\]])/$escapes{$1}/g; になります。これをRubyにすると: def escape(string) string.gsub(/([^;\/?:@&=+$,A-Za-z0-9\-_.!~*'()\[\]])/n) do sprintf("%%%02X", $1.unpack("C")[0]) end end となるでしょうか。正規表現の[^]を展開すると私の理解を越えてしまうので、 そのままにしておきました。 ただ、なひさんのおっしゃることにも一理あって、何をエスケープするかは、 ライブラリの実装者が決めかねるところでもあります。Escape.pmでは、それ に対応するために: uri_escape($string, [$unsafe]) として、どの文字をエスケープの対象にするか、ユーザが決められるようになっ ています。それを真似て: def escape(string, unsafe=nil) ## raise ArgumentError unless unsafe.nil? or unsafe.is_a? String if not unsafe string.gsub(/[^;\/?:@&=+$,A-Za-z0-9\-_.!~*'()\[\]]/n) do |match| sprintf("%%%02X", match.unpack("C")[0]) end else string.gsub(/[#{unsafe}]/n) do |match| sprintf("%%%02X", match.unpack("C")[0]) end end end p escape('http://foo/bar?a=b c=d') p escape('http://foo/bar?a=b c=d', ' ') としたほうがいいかも知れません。 ` 'を`+'に変換する処理は、もともとURIの範疇ではありませんし、削ること に異論はありません。ただ、考えてみれば、エスケープする機能は、正しい URI文字列を作るためには必要ですね。 越水 greentea@fa2.so-net.ne.jp