Skip to content

Commit 41dcae7

Browse files
committed
(PUP-11046) Implement RFC2396 style escape/unescape
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
1 parent f165750 commit 41dcae7

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

lib/puppet/util.rb

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -466,17 +466,7 @@ def uri_encode(path, opts = { :allow_fragment => false })
466466
# URI::parse and URI::Generic.build don't like paths encoded with CGI.escape
467467
# URI.escape does not change / to %2F and : to %3A like CGI.escape
468468
#
469-
# URI.escape is obsolete in Ruby 2.7. Ignore this error until we're able to
470-
# switch to a different escape mechanism. If this is JRuby, we can't mask
471-
# the error message, because this isn't thread safe. JRuby shouldn't be
472-
# using Ruby 2.7 or raising the warning anyway.
473-
orig_verbose = $VERBOSE
474-
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
475-
begin
476-
encoded += URI.escape(parts[:path]) unless parts[:path].nil?
477-
ensure
478-
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
479-
end
469+
encoded += rfc2396_escape(parts[:path]) unless parts[:path].nil?
480470

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

498-
def uri_unescape(path)
499-
orig_verbose = $VERBOSE
500-
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
501-
return URI.unescape(path)
502-
ensure
503-
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
488+
# From https://github.com/ruby/ruby/blob/v2_7_3/lib/uri/rfc2396_parser.rb#L24-L46
489+
ALPHA = "a-zA-Z".freeze
490+
ALNUM = "#{ALPHA}\\d".freeze
491+
UNRESERVED = "\\-_.!~*'()#{ALNUM}".freeze
492+
RESERVED = ";/?:@&=+$,\\[\\]".freeze
493+
UNSAFE = Regexp.new("[^#{UNRESERVED}#{RESERVED}]").freeze
494+
495+
HEX = "a-fA-F\\d".freeze
496+
ESCAPED = Regexp.new("%[#{HEX}]{2}").freeze
497+
498+
def rfc2396_escape(str)
499+
str.gsub(UNSAFE) do |match|
500+
tmp = ''
501+
match.each_byte do |uc|
502+
tmp << sprintf('%%%02X', uc)
503+
end
504+
tmp
505+
end.force_encoding(Encoding::US_ASCII)
506+
end
507+
module_function :rfc2396_escape
508+
509+
def uri_unescape(str)
510+
enc = str.encoding
511+
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
512+
str.gsub(ESCAPED) { [$&[1, 2]].pack('H2').force_encoding(enc) }
504513
end
505514
module_function :uri_unescape
506515

0 commit comments

Comments
 (0)