Force encoding of US-ASCII to UTF-8 in unescape_uri.

Because URI paths may contain non US-ASCII characters we need to force
the encoding of any unescaped URIs to UTF-8 if they are US-ASCII.
This essentially replicates the functionality of the monkey patch to
URI.parser.unescape in active_support/core_ext/uri.rb.

Fixes #16104.
This commit is contained in:
Karl Entwistle 2014-07-10 09:58:46 +01:00
parent b9ffae8feb
commit 8a29713134
3 changed files with 21 additions and 5 deletions

View File

@ -1,3 +1,12 @@
* Because URI paths may contain non US-ASCII characters we need to force
the encoding of any unescaped URIs to UTF-8 if they are US-ASCII.
This essentially replicates the functionality of the monkey patch to
URI.parser.unescape in active_support/core_ext/uri.rb.
Fixes #16104.
*Karl Entwistle*
* Generate shallow paths for all children of shallow resources.
Fixes #15783.

View File

@ -25,9 +25,10 @@ module ActionDispatch
# http://tools.ietf.org/html/rfc3986
class UriEncoder # :nodoc:
ENCODE = "%%%02X".freeze
ENCODING = Encoding::US_ASCII
EMPTY = "".force_encoding(ENCODING).freeze
DEC2HEX = (0..255).to_a.map{ |i| ENCODE % i }.map{ |s| s.force_encoding(ENCODING) }
US_ASCII = Encoding::US_ASCII
UTF_8 = Encoding::UTF_8
EMPTY = "".force_encoding(US_ASCII).freeze
DEC2HEX = (0..255).to_a.map{ |i| ENCODE % i }.map{ |s| s.force_encoding(US_ASCII) }
ALPHA = "a-zA-Z".freeze
DIGIT = "0-9".freeze
@ -53,12 +54,13 @@ module ActionDispatch
end
def unescape_uri(uri)
uri.gsub(ESCAPED) { [$&[1, 2].hex].pack('C') }.force_encoding(uri.encoding)
encoding = uri.encoding == US_ASCII ? UTF_8 : uri.encoding
uri.gsub(ESCAPED) { [$&[1, 2].hex].pack('C') }.force_encoding(encoding)
end
protected
def escape(component, pattern)
component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(ENCODING)
component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
end
def percent_encode(unsafe)

View File

@ -1,3 +1,4 @@
# coding: utf-8
require 'abstract_unit'
module ActionDispatch
@ -20,6 +21,10 @@ module ActionDispatch
assert_equal "a/b c+d", Utils.unescape_uri("a%2Fb%20c+d")
end
def test_uri_unescape_with_utf8_string
assert_equal "Šašinková", Utils.unescape_uri("%C5%A0a%C5%A1inkov%C3%A1".force_encoding(Encoding::US_ASCII))
end
def test_normalize_path_not_greedy
assert_equal "/foo%20bar%20baz", Utils.normalize_path("/foo%20bar%20baz")
end