diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb index 34f43ce20..a70dcf64d 100644 --- a/lib/rack/utils.rb +++ b/lib/rack/utils.rb @@ -13,7 +13,7 @@ module Utils # version since it's faster. (Stolen from Camping). def escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { - '%'+$1.unpack('H2'*$1.size).join('%').upcase + '%'+$1.unpack('H2'*bytesize($1)).join('%').upcase }.tr(' ', '+') end module_function :escape diff --git a/test/spec_rack_utils.rb b/test/spec_rack_utils.rb index 20abff53b..c39742997 100644 --- a/test/spec_rack_utils.rb +++ b/test/spec_rack_utils.rb @@ -12,6 +12,15 @@ should.equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C" end + specify "should escape correctly for multibyte characters" do + matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto + matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding + Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8' + matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto + matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding + Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8' + end + specify "should unescape correctly" do Rack::Utils.unescape("fo%3Co%3Ebar").should.equal "fobar" Rack::Utils.unescape("a+space").should.equal "a space"