Skip to content

Commit

Permalink
(PUP-11046) Implement RFC2396 style escape/unescape
Browse files Browse the repository at this point in the history
URI.escape/unescape was removed in Ruby 3, because it implements RFC 2396
escape/unescape with updates for RFCs 2732 and 2373, and those have been
superseded by RFC 3986.

To maintain 100% compatibility while supporting Ruby 3, implement the
escape/unescape methods in puppet[1]. In the future we can look at using
Addressable or using the newer URI parser in ruby.

[1] https://github.com/ruby/ruby/blob/v2_7_3/lib/uri/rfc2396_parser.rb#L24-L46
  • Loading branch information
joshcooper committed Apr 29, 2021
1 parent f165750 commit 41dcae7
Showing 1 changed file with 26 additions and 17 deletions.
43 changes: 26 additions & 17 deletions lib/puppet/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -466,17 +466,7 @@ def uri_encode(path, opts = { :allow_fragment => false })
# URI::parse and URI::Generic.build don't like paths encoded with CGI.escape
# URI.escape does not change / to %2F and : to %3A like CGI.escape
#
# URI.escape is obsolete in Ruby 2.7. Ignore this error until we're able to
# switch to a different escape mechanism. If this is JRuby, we can't mask
# the error message, because this isn't thread safe. JRuby shouldn't be
# using Ruby 2.7 or raising the warning anyway.
orig_verbose = $VERBOSE
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
begin
encoded += URI.escape(parts[:path]) unless parts[:path].nil?
ensure
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
end
encoded += rfc2396_escape(parts[:path]) unless parts[:path].nil?

# each query parameter
if !parts[:query].nil?
Expand All @@ -495,12 +485,31 @@ def uri_encode(path, opts = { :allow_fragment => false })
end
module_function :uri_encode

def uri_unescape(path)
orig_verbose = $VERBOSE
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
return URI.unescape(path)
ensure
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
# From https://github.com/ruby/ruby/blob/v2_7_3/lib/uri/rfc2396_parser.rb#L24-L46
ALPHA = "a-zA-Z".freeze
ALNUM = "#{ALPHA}\\d".freeze
UNRESERVED = "\\-_.!~*'()#{ALNUM}".freeze
RESERVED = ";/?:@&=+$,\\[\\]".freeze
UNSAFE = Regexp.new("[^#{UNRESERVED}#{RESERVED}]").freeze

HEX = "a-fA-F\\d".freeze
ESCAPED = Regexp.new("%[#{HEX}]{2}").freeze

def rfc2396_escape(str)
str.gsub(UNSAFE) do |match|
tmp = ''
match.each_byte do |uc|
tmp << sprintf('%%%02X', uc)
end
tmp
end.force_encoding(Encoding::US_ASCII)
end
module_function :rfc2396_escape

def uri_unescape(str)
enc = str.encoding
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
str.gsub(ESCAPED) { [$&[1, 2]].pack('H2').force_encoding(enc) }
end
module_function :uri_unescape

Expand Down

0 comments on commit 41dcae7

Please sign in to comment.