123456789_123456789_123456789_123456789_123456789_

Class: URI::FTP

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: lib/open-uri.rb

Instance Method Summary

::OpenURI::OpenRead - Included

#open

open provides ‘open’ for HTTP and FTP.

#read

OpenURI::OpenRead#read([ options ]) reads a content referenced by self and returns the content as string.

Instance Method Details

#buffer_open(buf, proxy, options)

[ GitHub ]

  
# File 'lib/open-uri.rb', line 777

def buffer_open(buf, proxy, options) # :nodoc:
  if proxy
    OpenURI.open_http(buf, self, proxy, options)
    return
  end

  begin
    require 'net/ftp'
  rescue LoadError
    abort "net/ftp is not found. You may need to `gem install net-ftp` to install net/ftp."
  end

  path = self.path
  path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it.
  directories = path.split(%r{/}, -1)
  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.new
  ftp.connect(self.hostname, self.port)
  ftp.passive = !options[:ftp_active_mode]
  # todo: extract user/passwd from .netrc.
  user = 'anonymous'
  passwd = nil
  user, passwd = self.userinfo.split(/:/) if self.userinfo
  ftp.(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(filename))
  end
  ftp.retrbinary("RETR #{filename}", 4096) { |str|
    buf << str
    options[:progress_proc].call(buf.size) if options[:progress_proc]
  }
  ftp.close
  buf.io.rewind
end