* lib/open-uri.rb (OpenURI.open_loop, URI::HTTP#proxy_open): use

catch/throw for redirection instead of exception.
  (OpenURI.open_loop, OpenURI.redirectable?): restrict redirection.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5015 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2003-11-24 14:36:18 +00:00
parent 087a8db4d2
commit 6eaa5f2b05
2 changed files with 37 additions and 23 deletions

View File

@ -1,3 +1,9 @@
Mon Nov 24 23:32:06 2003 Tanaka Akira <akr@m17n.org>
* lib/open-uri.rb (OpenURI.open_loop, URI::HTTP#proxy_open): use
catch/throw for redirection instead of exception.
(OpenURI.open_loop, OpenURI.redirectable?): restrict redirection.
Mon Nov 24 19:59:48 2003 Tanaka Akira <akr@m17n.org> Mon Nov 24 19:59:48 2003 Tanaka Akira <akr@m17n.org>
* lib/open-uri.rb (URI::Generic#find_proxy): use CGI_HTTP_PROXY * lib/open-uri.rb (URI::Generic#find_proxy): use CGI_HTTP_PROXY

View File

@ -159,36 +159,44 @@ module OpenURI
end end
uri_set = {} uri_set = {}
begin buf = nil
while true
redirect = catch(:open_uri_redirect) {
buf = Buffer.new buf = Buffer.new
if proxy_uri = find_proxy.call(uri) if proxy_uri = find_proxy.call(uri)
proxy_uri.proxy_open(buf, uri, options) proxy_uri.proxy_open(buf, uri, options)
else else
uri.direct_open(buf, options) uri.direct_open(buf, options)
end end
rescue Redirect nil
loc = $!.uri }
if loc.relative? if redirect
# Although it violates RFC 2616, Location: field may have relative URI. if redirect.relative?
# It is converted to absolute URI using uri. # Although it violates RFC 2616, Location: field may have relative
loc = uri + loc # URI. It is converted to absolute URI using uri.
redirect = uri + redirect
end end
uri = loc unless OpenURI.redirectable?(uri, redirect)
raise "redirection forbidden: #{uri} -> #{redirect}"
end
uri = redirect
raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
uri_set[uri.to_s] = true uri_set[uri.to_s] = true
retry else
break
end
end end
io = buf.io io = buf.io
io.base_uri = uri io.base_uri = uri
io io
end end
class Redirect < StandardError # :nodoc: def OpenURI.redirectable?(uri1, uri2) # :nodoc:
def initialize(uri) # This test is intended to forbid a redirection from http://... to
super("redirection to #{uri.to_s}") # file:///etc/passwd.
@uri = uri # However this is ad hoc. It should be extensible/configurable.
end uri1.scheme.downcase == uri2.scheme.downcase ||
attr_reader :uri (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
end end
class HTTPError < StandardError class HTTPError < StandardError
@ -502,7 +510,7 @@ module URI
Net::HTTPFound, # 302 Net::HTTPFound, # 302
Net::HTTPSeeOther, # 303 Net::HTTPSeeOther, # 303
Net::HTTPTemporaryRedirect # 307 Net::HTTPTemporaryRedirect # 307
raise OpenURI::Redirect.new(URI.parse(resp['location'])) throw :open_uri_redirect, URI.parse(resp['location'])
else else
raise OpenURI::HTTPError.new(io.status.join(' '), io) raise OpenURI::HTTPError.new(io.status.join(' '), io)
end end