summaryrefslogtreecommitdiff
path: root/lib/open-uri.rb
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-24 14:36:18 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-24 14:36:18 +0000
commit6eaa5f2b05c17cf05db5ced5e24f818e99a39828 (patch)
tree4bf715871561db61af3d968eafdfc8668326d9bc /lib/open-uri.rb
parent087a8db4d2bf4fb6807693b1da2caadffb33702c (diff)
* 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
Diffstat (limited to 'lib/open-uri.rb')
-rw-r--r--lib/open-uri.rb54
1 files changed, 31 insertions, 23 deletions
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 871b7b490e..5aaa5c4f9c 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -159,36 +159,44 @@ module OpenURI
end
uri_set = {}
- begin
- buf = Buffer.new
- if proxy_uri = find_proxy.call(uri)
- proxy_uri.proxy_open(buf, uri, options)
+ buf = nil
+ while true
+ redirect = catch(:open_uri_redirect) {
+ buf = Buffer.new
+ if proxy_uri = find_proxy.call(uri)
+ proxy_uri.proxy_open(buf, uri, options)
+ else
+ uri.direct_open(buf, options)
+ end
+ nil
+ }
+ if redirect
+ if redirect.relative?
+ # Although it violates RFC 2616, Location: field may have relative
+ # URI. It is converted to absolute URI using uri.
+ redirect = uri + redirect
+ end
+ 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
+ uri_set[uri.to_s] = true
else
- uri.direct_open(buf, options)
- end
- rescue Redirect
- loc = $!.uri
- if loc.relative?
- # Although it violates RFC 2616, Location: field may have relative URI.
- # It is converted to absolute URI using uri.
- loc = uri + loc
+ break
end
- uri = loc
- raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
- uri_set[uri.to_s] = true
- retry
end
io = buf.io
io.base_uri = uri
io
end
- class Redirect < StandardError # :nodoc:
- def initialize(uri)
- super("redirection to #{uri.to_s}")
- @uri = uri
- end
- attr_reader :uri
+ def OpenURI.redirectable?(uri1, uri2) # :nodoc:
+ # This test is intended to forbid a redirection from http://... to
+ # file:///etc/passwd.
+ # However this is ad hoc. It should be extensible/configurable.
+ uri1.scheme.downcase == uri2.scheme.downcase ||
+ (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
end
class HTTPError < StandardError
@@ -502,7 +510,7 @@ module URI
Net::HTTPFound, # 302
Net::HTTPSeeOther, # 303
Net::HTTPTemporaryRedirect # 307
- raise OpenURI::Redirect.new(URI.parse(resp['location']))
+ throw :open_uri_redirect, URI.parse(resp['location'])
else
raise OpenURI::HTTPError.new(io.status.join(' '), io)
end