From: Akinori MUSHA Date: 2009-08-28T21:09:07+09:00 Subject: [ruby-dev:39184] URI.escape_component --pgp-sign-Multipart_Fri_Aug_28_21:08:40_2009-1 Content-Type: text/plain; charset=ISO-2022-JP  JavaScript の escapeURIComponent() 相当の関数ってありましたっけ? もしなければURIモジュールに追加するのはどうですか。  ドキュメントの修正も混ざっていますが、以下がパッチです。 Index: lib/uri/common.rb =================================================================== --- lib/uri/common.rb (revision 24684) +++ lib/uri/common.rb (working copy) @@ -70,6 +70,7 @@ module URI # # * :ESCAPED (URI::PATTERN::ESCAPED in default) # * :UNRESERVED (URI::PATTERN::UNRESERVED in default) + # * :RESERVED (URI::PATTERN::RESERVED in default) # * :DOMLABEL (URI::PATTERN::DOMLABEL in default) # * :TOPLABEL (URI::PATTERN::TOPLABEL in default) # * :HOSTNAME (URI::PATTERN::HOSTNAME in default) @@ -226,6 +227,10 @@ module URI end.force_encoding(Encoding::US_ASCII) end + def escape_component(str, unsafe = @regexp[:NON_UNRESERVED]) + escape(str, unsafe) + end + def unescape(str, escaped = @regexp[:ESCAPED]) str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(str.encoding) end @@ -408,6 +413,7 @@ module URI # for URI::escape/unescape ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED]) ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]") + ret[:NON_UNRESERVED] = Regexp.new("[^#{pattern[:UNRESERVED]}]") # for Generic#initialize ret[:SCHEME] = Regexp.new("^#{pattern[:SCHEME]}$") @@ -476,10 +482,10 @@ module URI # == Args # # +str+:: - # String to replaces in. + # String to escape. # +unsafe+:: # Regexp that matches all symbols that must be replaced with codes. - # By default uses REGEXP::UNSAFE. + # By default uses URI::UNSAFE. # When this argument is a String, it represents a character set. # # == Description @@ -529,6 +535,36 @@ module URI DEFAULT_PARSER.unescape(*arg) end alias decode unescape + # + # == Synopsis + # + # URI.escape_component(str) + # + # == Args + # + # +str+:: + # String to escape. + # +unsafe+:: + # Regexp that matches all symbols that must be replaced with codes. + # By default uses URI::NON_UNRESERVED. + # When this argument is a String, it represents a character set. + # + # == Description + # + # This function is a version of escape() to escape a string for use + # in URI query components. + # + # == Usage + # + # require 'uri' + # + # uri = URI.parse("http://example.com/plot?q=" + URI.escape_component("y=2x")) + # p uri + # # => "http://example.com/plot?q=y%3D2x" + # + def escape_component(*arg) + DEFAULT_PARSER.escape_component(*arg) + end end extend Escape Index: test/uri/test_common.rb =================================================================== --- test/uri/test_common.rb (revision 24684) +++ test/uri/test_common.rb (working copy) @@ -49,6 +49,40 @@ class TestCommon < Test::Unit::TestCase assert_equal(expected, Kernel::URI("http://www.ruby-lang.org/")) assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") } end + + RESERVED = /\A[;\/\?:@&=\+\$,\[\]]\z/ + UNRESERVED = /\A[\-_\.!~\*'\(\)A-Za-z0-9]\z/ + + def test_escape + unescaped = '' + escaped = '' + escaped_component = '' + + (0x00..0x7f).map { |c| + ch = c.chr + esc = '%%%02X' % c + + unescaped << ch + + case ch + when UNRESERVED + escaped << ch + escaped_component << ch + when RESERVED + escaped << ch + escaped_component << esc + else + escaped << esc + escaped_component << esc + end + } + + assert_equal(escaped, URI.escape(unescaped)) + assert_equal(escaped_component, URI.escape_component(unescaped)) + + assert_equal(unescaped, URI.unescape(escaped)) + assert_equal(unescaped, URI.unescape(escaped_component)) + end end -- Akinori MUSHA / http://akinori.org/ --pgp-sign-Multipart_Fri_Aug_28_21:08:40_2009-1 Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEABECAAYFAkqXyMgACgkQkgvvx5/Z4e5ttQCePcHZBu45MbvbGkM2GnzpsUIJ e1YAoKqbXcCsjtYzsIZPEcVgqfY/z5X+ =JzKv -----END PGP SIGNATURE----- --pgp-sign-Multipart_Fri_Aug_28_21:08:40_2009-1--