# frozen_string_literal: true module Bundler::URI class RFC3986_Parser # :nodoc: # Bundler::URI defined in RFC3986 HOST = %r[ (?\[(?: (? (?:\h{1,4}:){6} (?\h{1,4}:\h{1,4} | (?(?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d) \.\g\.\g\.\g) ) | ::(?:\h{1,4}:){5}\g | \h{1,4}?::(?:\h{1,4}:){4}\g | (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g | (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g | (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g | (?:(?:\h{1,4}:){,4}\h{1,4})?::\g | (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4} | (?:(?:\h{1,4}:){,6}\h{1,4})?:: ) | (?v\h++\.[!$&-.0-9:;=A-Z_a-z~]++) )\]) | \g | (?(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+) ]x USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/ SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source RFC3986_URI = %r[\A (?#{SEG}){0} (? (?#{SCHEME}): (?// (? (?:(?#{USERINFO.source})@)? (?#{HOST.source.delete(" \n")}) (?::(?\d*+))? ) (?(?:/\g*+)?) | (?/((?!/)\g++)?) | (?(?!/)\g++) | (?) ) (?:\?(?[^\#]*+))? (?:\#(?#{FRAGMENT}))? )\z]x RFC3986_relative_ref = %r[\A (?#{SEG}){0} (? (?// (? (?:(?#{USERINFO.source})@)? (?#{HOST.source.delete(" \n")}(?\d*+))? ) (?(?:/\g*+)?) | (?/\g*+) | (?#{SEG_NC}++(?:/\g*+)?) | (?) ) (?:\?(?[^#]*+))? (?:\#(?#{FRAGMENT}))? )\z]x attr_reader :regexp def initialize @regexp = default_regexp.each_value(&:freeze).freeze end def split(uri) #:nodoc: begin uri = uri.to_str rescue NoMethodError raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri.inspect}" end uri.ascii_only? or raise InvalidURIError, "Bundler::URI must be ascii only #{uri.dump}" if m = RFC3986_URI.match(uri) query = m["query"] scheme = m["scheme"] opaque = m["path-rootless"] if opaque opaque << "?#{query}" if query [ scheme, nil, # userinfo nil, # host nil, # port nil, # registry nil, # path opaque, nil, # query m["fragment"] ] else # normal [ scheme, m["userinfo"], m["host"], m["port"], nil, # registry (m["path-abempty"] || m["path-absolute"] || m["path-empty"]), nil, # opaque query, m["fragment"] ] end elsif m = RFC3986_relative_ref.match(uri) [ nil, # scheme m["userinfo"], m["host"], m["port"], nil, # registry, (m["path-abempty"] || m["path-absolute"] || m["path-noscheme"] || m["path-empty"]), nil, # opaque m["query"], m["fragment"] ] else raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri.inspect}" end end def parse(uri) # :nodoc: Bundler::URI.for(*self.split(uri), self) end def join(*uris) # :nodoc: uris[0] = convert_to_uri(uris[0]) uris.inject :merge end @@to_s = Kernel.instance_method(:to_s) if @@to_s.respond_to?(:bind_call) def inspect @@to_s.bind_call(self) end else def inspect @@to_s.bind(self).call end end private def default_regexp # :nodoc: { SCHEME: %r[\A#{SCHEME}\z]o, USERINFO: %r[\A#{USERINFO}\z]o, HOST: %r[\A#{HOST}\z]o, ABS_PATH: %r[\A/#{SEG}*+\z]o, REL_PATH: %r[\A(?!/)#{SEG}++\z]o, QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z], FRAGMENT: %r[\A#{FRAGMENT}\z]o, OPAQUE: %r[\A(?:[^/].*)?\z], PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/, } end def convert_to_uri(uri) if uri.is_a?(Bundler::URI::Generic) uri elsif uri = String.try_convert(uri) parse(uri) else raise ArgumentError, "bad argument (expected Bundler::URI object or Bundler::URI string)" end end end # class Parser end # module Bundler::URI