summaryrefslogtreecommitdiff
path: root/lib/open-uri.rb
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-02-19 15:53:43 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-02-19 15:53:43 +0000
commit9846b5b67f05a2ed5d4a65c7612dc68fa29d0550 (patch)
tree418586caf57c3855126b150e7e3e29f846aa5340 /lib/open-uri.rb
parentcadfea8999e723b672c69facf8d8c5a7886e3760 (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.rb37
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]
}