diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-02-19 15:53:43 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-02-19 15:53:43 +0000 |
commit | 9846b5b67f05a2ed5d4a65c7612dc68fa29d0550 (patch) | |
tree | 418586caf57c3855126b150e7e3e29f846aa5340 /lib/open-uri.rb | |
parent | cadfea8999e723b672c69facf8d8c5a7886e3760 (diff) |
* lib/open-uri.rb (URI::FTP#buffer_open): access mechanism
re-implemented according to RFC 1738.
reported by Guillaume Marcais. [ruby-talk:131650]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@8003 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/open-uri.rb')
-rw-r--r-- | lib/open-uri.rb | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/lib/open-uri.rb b/lib/open-uri.rb index db35a5c158..f33dc38900 100644 --- a/lib/open-uri.rb +++ b/lib/open-uri.rb @@ -634,17 +634,46 @@ module URI return end require 'net/ftp' + + directories = self.path.split(%r{/}, -1) + directories.shift if directories[0] == '' # strip a field before leading slash + directories.each {|d| + d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") } + } + unless filename = directories.pop + raise ArgumentError, "no filename: #{self.inspect}" + end + directories.each {|d| + if /[\r\n]/ =~ d + raise ArgumentError, "invalid directory: #{d.inspect}" + end + } + if /[\r\n]/ =~ filename + raise ArgumentError, "invalid filename: #{filename.inspect}" + end + typecode = self.typecode + if typecode && /\A[aid]\z/ !~ typecode + raise ArgumentError, "invalid typecode: #{typecode.inspect}" + end + + # The access sequence is defined by RFC 1738 + ftp = Net::FTP.open(self.host) # todo: extract user/passwd from .netrc. user = 'anonymous' passwd = nil user, passwd = self.userinfo.split(/:/) if self.userinfo - - ftp = Net::FTP.open(self.host) ftp.login(user, passwd) + directories.each {|cwd| + ftp.voidcmd("CWD #{cwd}") + } + if typecode + # xxx: typecode D is not handled. + ftp.voidcmd("TYPE #{typecode.upcase}") + end if options[:content_length_proc] - options[:content_length_proc].call(ftp.size(self.path)) + options[:content_length_proc].call(ftp.size(filename)) end - ftp.getbinaryfile(self.path, '/dev/null', Net::FTP::DEFAULT_BLOCKSIZE) {|str| + ftp.retrbinary("RETR #{filename}", 4096) { |str| buf << str options[:progress_proc].call(buf.size) if options[:progress_proc] } |