def resolve(uri, referer = current_page)
referer_uri = referer && referer.uri
if uri.is_a?(URI)
uri = uri.dup
elsif uri.nil?
if referer_uri
return referer_uri
end
raise ArgumentError, "absolute URL needed (not nil)"
else
url = uri.to_s.strip
if url.empty?
if referer_uri
return referer_uri.dup.tap { |u| u.fragment = nil }
end
raise ArgumentError, "absolute URL needed (not #{uri.inspect})"
end
url.gsub!(/[^#{0.chr}-#{126.chr}]/o) { |match|
if RUBY_VERSION >= "1.9.0"
Mechanize::Util.uri_escape(match)
else
sprintf('%%%X', match.unpack($KCODE == 'UTF8' ? 'U' : 'C')[0])
end
}
escaped_url = Mechanize::Util.html_unescape(
url.split(/((?:%[0-9A-Fa-f]{2})+|#)/).each_slice(2).map { |x, y|
"#{WEBrick::HTTPUtils.escape(x)}#{y}"
}.join('')
)
begin
uri = URI.parse(escaped_url)
rescue
uri = URI.parse(WEBrick::HTTPUtils.escape(escaped_url))
end
end
scheme = uri.relative? ? 'relative' : uri.scheme.downcase
uri = @scheme_handlers[scheme].call(uri, referer)
if referer_uri
if uri.path.length == 0 && uri.relative?
uri.path = referer_uri.path
end
end
uri.path = '/' if uri.path.length == 0
if uri.relative?
raise ArgumentError, "absolute URL needed (not #{uri})" unless
referer_uri
if referer.respond_to?(:bases) && referer.parser &&
(lbase = referer.bases.last) && lbase.uri && lbase.uri.absolute?
base = lbase
else
base = nil
end
uri = referer_uri + (base ? base.uri : referer_uri) + uri
uri.path.sub!(/^(\/\.\.)+(?=\/)/, '')
end
unless ['http', 'https', 'file'].include?(uri.scheme.downcase)
raise ArgumentError, "unsupported scheme: #{uri.scheme}"
end
uri
end