diff --git a/.document b/.document new file mode 100644 index 0000000..1d07bdf --- /dev/null +++ b/.document @@ -0,0 +1,5 @@ +BSDL +COPYING +README.md +docs/ +lib/ diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index e15d54b..9eb2e2a 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 with: egress-policy: audit @@ -36,7 +36,7 @@ jobs: ruby-version: ruby - name: Publish to RubyGems - uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1 + uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1 - name: Create GitHub release run: | diff --git a/.rdoc_options b/.rdoc_options new file mode 100644 index 0000000..b1f9cda --- /dev/null +++ b/.rdoc_options @@ -0,0 +1,4 @@ +main_page: README.md +op_dir: _site +warn_missing_rdoc_ref: true +title: URI Documentation diff --git a/README.md b/README.md index 3775f3b..5c7c0dd 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![CI](https://github.com/ruby/uri/actions/workflows/test.yml/badge.svg)](https://github.com/ruby/uri/actions/workflows/test.yml) [![Yard Docs](https://img.shields.io/badge/docs-exist-blue.svg)](https://ruby.github.io/uri/) -URI is a module providing classes to handle Uniform Resource Identifiers [RFC2396](http://tools.ietf.org/html/rfc2396). +URI is a module providing classes to handle Uniform Resource Identifiers [RFC3986](http://tools.ietf.org/html/rfc3986). ## Features diff --git a/docs/kernel.rb b/docs/kernel.rb new file mode 100644 index 0000000..68ed335 --- /dev/null +++ b/docs/kernel.rb @@ -0,0 +1,2 @@ +# :stopdoc: +module Kernel end diff --git a/lib/uri/common.rb b/lib/uri/common.rb index c3fe0b4..bf28dea 100644 --- a/lib/uri/common.rb +++ b/lib/uri/common.rb @@ -13,15 +13,19 @@ require_relative "rfc3986_parser" module URI + # The default parser instance for RFC 2396. RFC2396_PARSER = RFC2396_Parser.new Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor) + # The default parser instance for RFC 3986. RFC3986_PARSER = RFC3986_Parser.new Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor) + # The default parser instance. DEFAULT_PARSER = RFC3986_PARSER Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor) + # Set the default parser instance. def self.parser=(parser = RFC3986_PARSER) remove_const(:Parser) if defined?(::URI::Parser) const_set("Parser", parser.class) @@ -40,7 +44,7 @@ def self.parser=(parser = RFC3986_PARSER) end self.parser = RFC3986_PARSER - def self.const_missing(const) + def self.const_missing(const) # :nodoc: if const == :REGEXP warn "URI::REGEXP is obsolete. Use URI::RFC2396_REGEXP explicitly.", uplevel: 1 if $VERBOSE URI::RFC2396_REGEXP @@ -87,7 +91,7 @@ def make_components_hash(klass, array_hash) module_function :make_components_hash end - module Schemes + module Schemes # :nodoc: end private_constant :Schemes @@ -305,7 +309,7 @@ def self.regexp(schemes = nil)# :nodoc: 256.times do |i| TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i) end - TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze + TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze # :nodoc: TBLENCWWWCOMP_[' '] = '+' TBLENCWWWCOMP_.freeze TBLDECWWWCOMP_ = {} # :nodoc: diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index d4bfa3b..b574104 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -737,12 +737,12 @@ def check_registry(v) # :nodoc: end private :check_registry - def set_registry(v) #:nodoc: + def set_registry(v) # :nodoc: raise InvalidURIError, "cannot set registry" end protected :set_registry - def registry=(v) + def registry=(v) # :nodoc: raise InvalidURIError, "cannot set registry" end @@ -1133,17 +1133,16 @@ def merge(oth) base.fragment=(nil) # RFC2396, Section 5.2, 4) - if !authority - base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path - else - # RFC2396, Section 5.2, 4) - base.set_path(rel.path) if rel.path + if authority + base.set_userinfo(rel.userinfo) + base.set_host(rel.host) + base.set_port(rel.port || base.default_port) + base.set_path(rel.path) + elsif base.path && rel.path + base.set_path(merge_path(base.path, rel.path)) end # RFC2396, Section 5.2, 7) - base.set_userinfo(rel.userinfo) if rel.userinfo - base.set_host(rel.host) if rel.host - base.set_port(rel.port) if rel.port base.query = rel.query if rel.query base.fragment=(rel.fragment) if rel.fragment @@ -1392,10 +1391,12 @@ def ==(oth) end end + # Returns the hash value. def hash self.component_ary.hash end + # Compares with _oth_ for Hash. def eql?(oth) self.class == oth.class && parser == oth.parser && @@ -1438,7 +1439,7 @@ def select(*components) end end - def inspect + def inspect # :nodoc: "#<#{self.class} #{self}>" end diff --git a/lib/uri/rfc2396_parser.rb b/lib/uri/rfc2396_parser.rb index 0336366..75a2d2d 100644 --- a/lib/uri/rfc2396_parser.rb +++ b/lib/uri/rfc2396_parser.rb @@ -321,14 +321,14 @@ def unescape(str, escaped = @regexp[:ESCAPED]) str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) } end - @@to_s = Kernel.instance_method(:to_s) - if @@to_s.respond_to?(:bind_call) - def inspect - @@to_s.bind_call(self) + TO_S = Kernel.instance_method(:to_s) # :nodoc: + if TO_S.respond_to?(:bind_call) + def inspect # :nodoc: + TO_S.bind_call(self) end else - def inspect - @@to_s.bind(self).call + def inspect # :nodoc: + TO_S.bind(self).call end end diff --git a/lib/uri/version.rb b/lib/uri/version.rb index 59f1c82..b6a8ce1 100644 --- a/lib/uri/version.rb +++ b/lib/uri/version.rb @@ -1,6 +1,6 @@ module URI # :stopdoc: - VERSION_CODE = '010002'.freeze + VERSION_CODE = '010003'.freeze VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze # :startdoc: end diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb index e96f819..6326aec 100644 --- a/test/uri/test_common.rb +++ b/test/uri/test_common.rb @@ -10,23 +10,23 @@ def setup def teardown end - class Foo - include URI::REGEXP::PATTERN + EnvUtil.suppress_warning do + class Foo + # Intentionally use `URI::REGEXP`, which is for the compatibility + include URI::REGEXP::PATTERN + end end def test_fallback_constants - orig_verbose = $VERBOSE - $VERBOSE = nil - - assert_raise(NameError) { URI::FOO } + EnvUtil.suppress_warning do + assert_raise(NameError) { URI::FOO } - assert_equal URI::ABS_URI, URI::RFC2396_PARSER.regexp[:ABS_URI] - assert_equal URI::PATTERN, URI::RFC2396_Parser::PATTERN - assert_equal URI::REGEXP, URI::RFC2396_REGEXP - assert_equal URI::REGEXP::PATTERN, URI::RFC2396_REGEXP::PATTERN - assert_equal Foo::IPV4ADDR, URI::RFC2396_REGEXP::PATTERN::IPV4ADDR - ensure - $VERBOSE = orig_verbose + assert_equal URI::ABS_URI, URI::RFC2396_PARSER.regexp[:ABS_URI] + assert_equal URI::PATTERN, URI::RFC2396_Parser::PATTERN + assert_equal URI::REGEXP, URI::RFC2396_REGEXP + assert_equal URI::REGEXP::PATTERN, URI::RFC2396_REGEXP::PATTERN + assert_equal Foo::IPV4ADDR, URI::RFC2396_REGEXP::PATTERN::IPV4ADDR + end end def test_parser_switch diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb index 8209363..1d5fbc7 100644 --- a/test/uri/test_generic.rb +++ b/test/uri/test_generic.rb @@ -175,6 +175,17 @@ def test_parse # must be empty string to identify as path-abempty, not path-absolute assert_equal('', url.host) assert_equal('http:////example.com', url.to_s) + + # sec-2957667 + url = URI.parse('http://user:pass@example.com').merge('//example.net') + assert_equal('http://example.net', url.to_s) + assert_nil(url.userinfo) + url = URI.join('http://user:pass@example.com', '//example.net') + assert_equal('http://example.net', url.to_s) + assert_nil(url.userinfo) + url = URI.parse('http://user:pass@example.com') + '//example.net' + assert_equal('http://example.net', url.to_s) + assert_nil(url.userinfo) end def test_parse_scheme_with_symbols @@ -267,6 +278,13 @@ def test_merge assert_equal(u0, u1) end + def test_merge_authority + u = URI.parse('http://user:pass@example.com:8080') + u0 = URI.parse('http://new.example.org/path') + u1 = u.merge('//new.example.org/path') + assert_equal(u0, u1) + end + def test_route url = URI.parse('http://hoge/a.html').route_to('http://hoge/b.html') assert_equal('b.html', url.to_s)