# class Net::FTP

This class implements the `File` Transfer Protocol. If you have used a command-line `FTP` program, and are familiar with the commands, you will be able to use this class easily. Some extra features are included to take advantage of Ruby's style and strengths.

## Example¶ ↑

    require 'net/ftp'

### Example 1¶ ↑

    ftp = Net::FTP.new('example.com')
    ftp.login
    files = ftp.chdir('pub/lang/ruby/contrib')
    files = ftp.list('n*')
    ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
    ftp.close

### Example 2¶ ↑

    Net::FTP.open('example.com') do |ftp|
      ftp.login
      files = ftp.chdir('pub/lang/ruby/contrib')
      files = ftp.list('n*')
      ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
    end

## Major Methods¶ ↑

The following are the methods most likely to be useful to users:

- `FTP.open`

- `getbinaryfile`

- `gettextfile`

- `putbinaryfile`

- `puttextfile`

- `chdir`

- `nlst`

- `size`

- `rename`

- `delete`

### Constants

CASE_DEPENDENT_PARSER
CASE_INDEPENDENT_PARSER
DECIMAL_PARSER
FACT_PARSERS
OCTAL_PARSER
TIME_PARSER

### Attributes

binary[R]

When `true`, transfers are performed in binary mode. Default: `true`.

debug_mode[RW]

When `true`, all traffic to and from the server is written to +$stdout+. Default: `false`.

last_response[R]

The server's last response.

last_response_code[R]

The server's last response code.

lastresp[R]

The server's last response code.

open_timeout[RW]

Number of seconds to wait for the connection to open. Any number may be used, including Floats for fractional seconds. If the `FTP` object cannot open a connection in this many seconds, it raises a `Net::OpenTimeout` exception. The default value is `nil`.

passive[RW]

When `true`, the connection is in passive mode. Default: `true`.

read_timeout[R]

Number of seconds to wait for one block to be read (via one read(2) call). Any number may be used, including Floats for fractional seconds. If the `FTP` object cannot read data in this many seconds, it raises a `Timeout::Error` exception. The default value is 60 seconds.

resume[RW]

Sets or retrieves the `resume` status, which decides whether incomplete transfers are resumed or restarted. Default: `false`.

ssl_handshake_timeout[RW]

Number of seconds to wait for the TLS handshake. Any number may be used, including Floats for fractional seconds. If the `FTP` object cannot complete the TLS handshake in this many seconds, it raises a `Net::OpenTimeout` exception. The default value is `nil`. If `ssl_handshake_timeout` is `nil`, `open_timeout` is used instead.

welcome[R]

The server's welcome message.

### Public Class Methods

default_passive() click to toggle source

When `true`, connections are in passive mode per default. Default: `true`.

    # File lib/net/ftp.rb, line 151
    def self.default_passive
      @@default_passive
    end

default_passive=(value) click to toggle source

When `true`, connections are in passive mode per default. Default: `true`.

    # File lib/net/ftp.rb, line 145
    def self.default_passive=(value)
      @@default_passive = value
    end

Net::FTP.new(host = nil, options = {}) click to toggle source

Creates and returns a new `FTP` object. If a `host` is given, a connection is made.

`options` is an option hash, each key of which is a symbol.

The available options are:

port

  Port number (default value is 21)

ssl

  If options is true, then an attempt will be made to use SSL (now TLS) to connect to the server. For this to work `OpenSSL` [OSSL] and the Ruby `OpenSSL` [RSSL] extensions need to be installed. If options is a hash, it's passed to `OpenSSL::SSL::SSLContext#set_params` as parameters.

private_data_connection

  If true, TLS is used for data connections. Default: `true` when options is true.

username

  Username for login. If options is the string “anonymous” and the options is `nil`, “anonymous@” is used as a password.

password

  Password for login.

account

  Account information for ACCT.

passive

  When `true`, the connection is in passive mode. Default: `true`.

`open_timeout`

  Number of seconds to wait for the connection to open. See `Net::FTP#open_timeout` for details. Default: `nil`.

`read_timeout`

  Number of seconds to wait for one block to be read. See `Net::FTP#read_timeout` for details. Default: `60`.

`ssl_handshake_timeout`

  Number of seconds to wait for the TLS handshake. See `Net::FTP#ssl_handshake_timeout` for details. Default: `nil`.

`debug_mode`

  When `true`, all traffic to and from the server is written to +$stdout+. Default: `false`.

Calls superclass method

    # File lib/net/ftp.rb, line 211
    def initialize(host = nil, user_or_options = {}, passwd = nil, acct = nil)
      super()
      begin
        options = user_or_options.to_hash
      rescue NoMethodError
        # for backward compatibility
        options = {}
        options[:username] = user_or_options
        options[:password] = passwd
        options[:account] = acct
      end
      @host = nil
      if options[:ssl]
        unless defined?(OpenSSL::SSL)
          raise "SSL extension not installed"
        end
        ssl_params = options[:ssl] == true ? {} : options[:ssl]
        @ssl_context = SSLContext.new
        @ssl_context.set_params(ssl_params)
        if defined?(VerifyCallbackProc)
          @ssl_context.verify_callback = VerifyCallbackProc
        end
        @ssl_context.session_cache_mode =
          OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
          OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
        @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
        @ssl_session = nil
        if options[:private_data_connection].nil?
          @private_data_connection = true
        else
          @private_data_connection = options[:private_data_connection]
        end
      else
        @ssl_context = nil
        if options[:private_data_connection]
          raise ArgumentError,
            "private_data_connection can be set to true only when ssl is enabled"
        end
        @private_data_connection = false
      end
      @binary = true
      if options[:passive].nil?
        @passive = @@default_passive
      else
        @passive = options[:passive]
      end
      if options[:debug_mode].nil?
        @debug_mode = false
      else
        @debug_mode = options[:debug_mode]
      end
      @resume = false
      @bare_sock = @sock = NullSocket.new
      @logged_in = false
      @open_timeout = options[:open_timeout]
      @ssl_handshake_timeout = options[:ssl_handshake_timeout]
      @read_timeout = options[:read_timeout] || 60
      if host
        connect(host, options[:port] || FTP_PORT)
        if options[:username]
          login(options[:username], options[:password], options[:account])
        end
      end
    end

open(host, *args) { |ftp| ... } click to toggle source

A synonym for `FTP.new`, but with a mandatory host parameter.

If a block is given, it is passed the `FTP` object, which will be closed when the block finishes, or when an exception is raised.

    # File lib/net/ftp.rb, line 161
    def FTP.open(host, *args)
      if block_given?
        ftp = new(host, *args)
        begin
          yield ftp
        ensure
          ftp.close
        end
      else
        new(host, *args)
      end
    end

### Public Instance Methods

abort() click to toggle source

Aborts the previous command (ABOR command).

    # File lib/net/ftp.rb, line 1230
    def abort
      line = "ABOR" + CRLF
      print "put: ABOR\n" if @debug_mode
      @sock.send(line, Socket::MSG_OOB)
      resp = getmultiline
      unless ["426", "226", "225"].include?(resp[0, 3])
        raise FTPProtoError, resp
      end
      return resp
    end

acct(account) click to toggle source

Sends the ACCT command.

This is a less common `FTP` command, to send account information if the destination host requires it.

    # File lib/net/ftp.rb, line 883
    def acct(account)
      cmd = "ACCT " + account
      voidcmd(cmd)
    end

binary=(newmode) click to toggle source

A setter to toggle transfers in binary mode. `newmode` is either `true` or `false`

    # File lib/net/ftp.rb, line 278
    def binary=(newmode)
      if newmode != @binary
        @binary = newmode
        send_type_command if @logged_in
      end
    end

chdir(dirname) click to toggle source

Changes the (remote) directory.

    # File lib/net/ftp.rb, line 1151
    def chdir(dirname)
      if dirname == ".."
        begin
          voidcmd("CDUP")
          return
        rescue FTPPermError => e
          if e.message[0, 3] != "500"
            raise e
          end
        end
      end
      cmd = "CWD #{dirname}"
      voidcmd(cmd)
    end

close() click to toggle source

Closes the connection. Further operations are impossible until you open a new connection with `connect`.

    # File lib/net/ftp.rb, line 1344
    def close
      if @sock and not @sock.closed?
        begin
          @sock.shutdown(Socket::SHUT_WR) rescue nil
          orig, self.read_timeout = self.read_timeout, 3
          @sock.read rescue nil
        ensure
          @sock.close
          self.read_timeout = orig
        end
      end
    end

closed?() click to toggle source

Returns `true` iff the connection is closed.

    # File lib/net/ftp.rb, line 1360
    def closed?
      @sock == nil or @sock.closed?
    end

connect(host, port = FTP_PORT) click to toggle source

Establishes an `FTP` connection to host, optionally overriding the default port. If the environment variable `SOCKS_SERVER` is set, sets up the connection through a SOCKS proxy. Raises an exception (typically `Errno::ECONNREFUSED`) if the connection cannot be established.

    # File lib/net/ftp.rb, line 366
    def connect(host, port = FTP_PORT)
      if @debug_mode
        print "connect: ", host, ", ", port, "\n"
      end
      synchronize do
        @host = host
        @bare_sock = open_socket(host, port)
        @sock = BufferedSocket.new(@bare_sock, read_timeout: @read_timeout)
        voidresp
        if @ssl_context
          begin
            voidcmd("AUTH TLS")
            ssl_sock = start_tls_session(@bare_sock)
            @sock = BufferedSSLSocket.new(ssl_sock, read_timeout: @read_timeout)
            if @private_data_connection
              voidcmd("PBSZ 0")
              voidcmd("PROT P")
            end
          rescue OpenSSL::SSL::SSLError, OpenTimeout
            @sock.close
            raise
          end
        end
      end
    end

delete(filename) click to toggle source

Deletes a file on the server.

    # File lib/net/ftp.rb, line 1137
    def delete(filename)
      resp = sendcmd("DELE #{filename}")
      if resp.start_with?("250")
        return
      elsif resp.start_with?("5")
        raise FTPPermError, resp
      else
        raise FTPReplyError, resp
      end
    end

dir(*args)
Alias for: list
features() click to toggle source

Issues a FEAT command

Returns an array of supported optional features

    # File lib/net/ftp.rb, line 1310
    def features
      resp = sendcmd("FEAT")
      if !resp.start_with?("211")
        raise FTPReplyError, resp
      end

      feats = []
      resp.split("\n").each do |line|
        next if !line.start_with?(' ') # skip status lines

        feats << line.strip
      end

      return feats
    end

get(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } click to toggle source

Retrieves `remotefile` in whatever mode the session is set (text or binary). See `gettextfile` and `getbinaryfile`.

    # File lib/net/ftp.rb, line 812
    def get(remotefile, localfile = File.basename(remotefile),
            blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
      if @binary
        getbinaryfile(remotefile, localfile, blocksize, &block)
      else
        gettextfile(remotefile, localfile, &block)
      end
    end

getbinaryfile(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } click to toggle source

Retrieves `remotefile` in binary mode, storing the result in `localfile`. If `localfile` is nil, returns retrieved data. If a block is supplied, it is passed the retrieved data in `blocksize` chunks.

    # File lib/net/ftp.rb, line 751
    def getbinaryfile(remotefile, localfile = File.basename(remotefile),
                      blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
      f = nil
      result = nil
      if localfile
        if @resume
          rest_offset = File.size?(localfile)
          f = File.open(localfile, "a")
        else
          rest_offset = nil
          f = File.open(localfile, "w")
        end
      elsif !block_given?
        result = String.new
      end
      begin
        f&.binmode
        retrbinary("RETR #{remotefile}", blocksize, rest_offset) do |data|
          f&.write(data)
          block&.(data)
          result&.concat(data)
        end
        return result
      ensure
        f&.close
      end
    end

getdir()
Alias for: pwd
gettextfile(remotefile, localfile = File.basename(remotefile)) { |line| ... } click to toggle source

Retrieves `remotefile` in ASCII (text) mode, storing the result in `localfile`. If `localfile` is nil, returns retrieved data. If a block is supplied, it is passed the retrieved data one line at a time.

    # File lib/net/ftp.rb, line 786
    def gettextfile(remotefile, localfile = File.basename(remotefile),
                    &block) # :yield: line
      f = nil
      result = nil
      if localfile
        f = File.open(localfile, "w")
      elsif !block_given?
        result = String.new
      end
      begin
        retrlines("RETR #{remotefile}") do |line, newline|
          l = newline ? line + "\n" : line
          f&.print(l)
          block&.(line, newline)
          result&.concat(l)
        end
        return result
      ensure
        f&.close
      end
    end

help(arg = nil) click to toggle source

Issues the HELP command.

    # File lib/net/ftp.rb, line 1273
    def help(arg = nil)
      cmd = "HELP"
      if arg
        cmd = cmd + " " + arg
      end
      sendcmd(cmd)
    end

list(*args) { |line| ... } click to toggle source

Returns an array of file information in the directory (the output is like `ls -l`). If a block is given, it iterates through the listing.

    # File lib/net/ftp.rb, line 907
    def list(*args, &block) # :yield: line
      cmd = "LIST"
      args.each do |arg|
        cmd = "#{cmd} #{arg}"
      end
      lines = []
      retrlines(cmd) do |line|
        lines << line
      end
      if block
        lines.each(&block)
      end
      return lines
    end

Also aliased as: ls, dir
login(user = "anonymous", passwd = nil, acct = nil) click to toggle source

Logs in to the remote host. The session must have been previously connected. If `user` is the string “anonymous” and the `password` is `nil`, “anonymous@” is used as a password. If the `acct` parameter is not `nil`, an `FTP` ACCT command is sent following the successful login. Raises an exception on error (typically `Net::FTPPermError`).

    # File lib/net/ftp.rb, line 598
    def login(user = "anonymous", passwd = nil, acct = nil)
      if user == "anonymous" and passwd == nil
        passwd = "anonymous@"
      end

      resp = ""
      synchronize do
        resp = sendcmd('USER ' + user)
        if resp.start_with?("3")
          raise FTPReplyError, resp if passwd.nil?
          resp = sendcmd('PASS ' + passwd)
        end
        if resp.start_with?("3")
          raise FTPReplyError, resp if acct.nil?
          resp = sendcmd('ACCT ' + acct)
        end
      end
      if !resp.start_with?("2")
        raise FTPReplyError, resp
      end
      @welcome = resp
      send_type_command
      @logged_in = true
    end

ls(*args)
Alias for: list
mdtm(filename) click to toggle source

Returns the raw last modification time of the (remote) file in the format “YYYYMMDDhhmmss” (MDTM command).

Use `mtime` if you want a parsed `Time` instance.

    # File lib/net/ftp.rb, line 1263
    def mdtm(filename)
      resp = sendcmd("MDTM #{filename}")
      if resp.start_with?("213")
        return get_body(resp)
      end
    end

mkdir(dirname) click to toggle source

Creates a remote directory.

    # File lib/net/ftp.rb, line 1195
    def mkdir(dirname)
      resp = sendcmd("MKD #{dirname}")
      return parse257(resp)
    end

mlsd(pathname = nil) { |entry| ... } click to toggle source

Returns an array of the entries of the directory specified by `pathname`. Each entry has the facts (e.g., size, last modification time, etc.) and the pathname. If a block is given, it iterates through the listing. If `pathname` is omitted, the current directory is assumed.

    # File lib/net/ftp.rb, line 1111
    def mlsd(pathname = nil, &block) # :yield: entry
      cmd = pathname ? "MLSD #{pathname}" : "MLSD"
      entries = []
      retrlines(cmd) do |line|
        entries << parse_mlsx_entry(line)
      end
      if block
        entries.each(&block)
      end
      return entries
    end

mlst(pathname = nil) click to toggle source

Returns data (e.g., size, last modification time, entry type, etc.) about the file or directory specified by `pathname`. If `pathname` is omitted, the current directory is assumed.

    # File lib/net/ftp.rb, line 1089
    def mlst(pathname = nil)
      cmd = pathname ? "MLST #{pathname}" : "MLST"
      resp = sendcmd(cmd)
      if !resp.start_with?("250")
        raise FTPReplyError, resp
      end
      line = resp.lines[1]
      unless line
        raise FTPProtoError, resp
      end
      entry = line.sub(/\A(250-| *)/, "")
      return parse_mlsx_entry(entry)
    end

mtime(filename, local = false) click to toggle source

Returns the last modification time of the (remote) file. If `local` is `true`, it is returned as a local time, otherwise it's a UTC time.

    # File lib/net/ftp.rb, line 1188
    def mtime(filename, local = false)
      return TIME_PARSER.(mdtm(filename), local)
    end

nlst(dir = nil) click to toggle source

Returns an array of filenames in the remote directory.

    # File lib/net/ftp.rb, line 891
    def nlst(dir = nil)
      cmd = "NLST"
      if dir
        cmd = "#{cmd} #{dir}"
      end
      files = []
      retrlines(cmd) do |line|
        files.push(line)
      end
      return files
    end

noop() click to toggle source

Issues a NOOP command.

Does nothing except return a response.

    # File lib/net/ftp.rb, line 1293
    def noop
      voidcmd("NOOP")
    end

option(name, params = nil) click to toggle source

Issues an OPTS command

- name Should be the name of the option to set

- params is any optional parameters to supply with the option

example: option('UTF8', 'ON') => 'OPTS UTF8 ON'

    # File lib/net/ftp.rb, line 1333
    def option(name, params = nil)
      cmd = "OPTS #{name}"
      cmd += " #{params}" if params

      voidcmd(cmd)
    end

put(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE, &block) click to toggle source

Transfers `localfile` to the server in whatever mode the session is set (text or binary). See `puttextfile` and `putbinaryfile`.

    # File lib/net/ftp.rb, line 868
    def put(localfile, remotefile = File.basename(localfile),
            blocksize = DEFAULT_BLOCKSIZE, &block)
      if @binary
        putbinaryfile(localfile, remotefile, blocksize, &block)
      else
        puttextfile(localfile, remotefile, &block)
      end
    end

putbinaryfile(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } click to toggle source

Transfers `localfile` to the server in binary mode, storing the result in `remotefile`. If a block is supplied, calls it, passing in the transmitted data in `blocksize` chunks.

    # File lib/net/ftp.rb, line 826
    def putbinaryfile(localfile, remotefile = File.basename(localfile),
                      blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
      if @resume
        begin
          rest_offset = size(remotefile)
        rescue Net::FTPPermError
          rest_offset = nil
        end
      else
        rest_offset = nil
      end
      f = File.open(localfile)
      begin
        f.binmode
        if rest_offset
          storbinary("APPE #{remotefile}", f, blocksize, rest_offset, &block)
        else
          storbinary("STOR #{remotefile}", f, blocksize, rest_offset, &block)
        end
      ensure
        f.close
      end
    end

puttextfile(localfile, remotefile = File.basename(localfile)) { |line| ... } click to toggle source

Transfers `localfile` to the server in ASCII (text) mode, storing the result in `remotefile`. If callback or an associated block is supplied, calls it, passing in the transmitted data one line at a time.

    # File lib/net/ftp.rb, line 855
    def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
      f = File.open(localfile)
      begin
        storlines("STOR #{remotefile}", f, &block)
      ensure
        f.close
      end
    end

pwd() click to toggle source

Returns the current remote directory.

    # File lib/net/ftp.rb, line 1210
    def pwd
      resp = sendcmd("PWD")
      return parse257(resp)
    end

Also aliased as: getdir
quit() click to toggle source

Exits the `FTP` session.

    # File lib/net/ftp.rb, line 1284
    def quit
      voidcmd("QUIT")
    end

read_timeout=(sec) click to toggle source

Setter for the `read_timeout` attribute.

    # File lib/net/ftp.rb, line 128
    def read_timeout=(sec)
      @sock.read_timeout = sec
      @read_timeout = sec
    end

rename(fromname, toname) click to toggle source

Renames a file on the server.

    # File lib/net/ftp.rb, line 1126
    def rename(fromname, toname)
      resp = sendcmd("RNFR #{fromname}")
      if !resp.start_with?("3")
        raise FTPReplyError, resp
      end
      voidcmd("RNTO #{toname}")
    end

retrbinary(cmd, blocksize, rest_offset = nil) { |data| ... } click to toggle source

Puts the connection into binary (image) mode, issues the given command, and fetches the data returned, passing it to the associated block in chunks of `blocksize` characters. Note that `cmd` is a server command (such as “RETR myfile”).

    # File lib/net/ftp.rb, line 629
    def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
      synchronize do
        with_binary(true) do
          begin
            conn = transfercmd(cmd, rest_offset)
            while data = conn.read(blocksize)
              yield(data)
            end
            conn.shutdown(Socket::SHUT_WR) rescue nil
            conn.read_timeout = 1
            conn.read rescue nil
          ensure
            conn.close if conn
          end
          voidresp
        end
      end
    end

retrlines(cmd) { |line| ... } click to toggle source

Puts the connection into ASCII (text) mode, issues the given command, and passes the resulting data, one line at a time, to the associated block. If no block is given, prints the lines. Note that `cmd` is a server command (such as “RETR myfile”).

    # File lib/net/ftp.rb, line 654
    def retrlines(cmd) # :yield: line
      synchronize do
        with_binary(false) do
          begin
            conn = transfercmd(cmd)
            while line = conn.gets
              yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?)
            end
            conn.shutdown(Socket::SHUT_WR) rescue nil
            conn.read_timeout = 1
            conn.read rescue nil
          ensure
            conn.close if conn
          end
          voidresp
        end
      end
    end

rmdir(dirname) click to toggle source

Removes a remote directory.

    # File lib/net/ftp.rb, line 1203
    def rmdir(dirname)
      voidcmd("RMD #{dirname}")
    end

sendcmd(cmd) click to toggle source

Sends a command and returns the response.

    # File lib/net/ftp.rb, line 491
    def sendcmd(cmd)
      synchronize do
        putline(cmd)
        return getresp
      end
    end

set_socket(sock, get_greeting = true) click to toggle source

`Set` the socket used to connect to the `FTP` server.

May raise FTPReplyError if `get_greeting` is false.

    # File lib/net/ftp.rb, line 396
    def set_socket(sock, get_greeting = true)
      synchronize do
        @sock = sock
        if get_greeting
          voidresp
        end
      end
    end

site(arg) click to toggle source

Issues a SITE command.

    # File lib/net/ftp.rb, line 1300
    def site(arg)
      cmd = "SITE " + arg
      voidcmd(cmd)
    end

size(filename) click to toggle source

Returns the size of the given (remote) filename.

    # File lib/net/ftp.rb, line 1174
    def size(filename)
      with_binary(true) do
        resp = sendcmd("SIZE #{filename}")
        if !resp.start_with?("213")
          raise FTPReplyError, resp
        end
        return get_body(resp).to_i
      end
    end

status(pathname = nil) click to toggle source

Returns the status (STAT command).

pathname

  when stat is invoked with pathname as a parameter it acts like list but a lot faster and over the same tcp session.

    # File lib/net/ftp.rb, line 1247
    def status(pathname = nil)
      line = pathname ? "STAT #{pathname}" : "STAT"
      if /[\r\n]/ =~ line
        raise ArgumentError, "A line must not contain CR or LF"
      end
      print "put: #{line}\n" if @debug_mode
      @sock.send(line + CRLF, Socket::MSG_OOB)
      return getresp
    end

storbinary(cmd, file, blocksize, rest_offset = nil) { |data| ... } click to toggle source

Puts the connection into binary (image) mode, issues the given server-side command (such as “STOR myfile”), and sends the contents of the file named `file` to the server. If the optional block is given, it also passes it the data, in chunks of `blocksize` characters.

    # File lib/net/ftp.rb, line 679
    def storbinary(cmd, file, blocksize, rest_offset = nil) # :yield: data
      if rest_offset
        file.seek(rest_offset, IO::SEEK_SET)
      end
      synchronize do
        with_binary(true) do
          begin
            conn = transfercmd(cmd)
            while buf = file.read(blocksize)
              conn.write(buf)
              yield(buf) if block_given?
            end
            conn.shutdown(Socket::SHUT_WR) rescue nil
            conn.read_timeout = 1
            conn.read rescue nil
          ensure
            conn.close if conn
          end
          voidresp
        end
      end
    rescue Errno::EPIPE
      # EPIPE, in this case, means that the data connection was unexpectedly
      # terminated.  Rather than just raising EPIPE to the caller, check the
      # response on the control connection.  If getresp doesn't raise a more
      # appropriate exception, re-raise the original exception.
      getresp
      raise
    end

storlines(cmd, file) { |line| ... } click to toggle source

Puts the connection into ASCII (text) mode, issues the given server-side command (such as “STOR myfile”), and sends the contents of the file named `file` to the server, one line at a time. If the optional block is given, it also passes it the lines.

    # File lib/net/ftp.rb, line 715
    def storlines(cmd, file) # :yield: line
      synchronize do
        with_binary(false) do
          begin
            conn = transfercmd(cmd)
            while buf = file.gets
              if buf[-2, 2] != CRLF
                buf = buf.chomp + CRLF
              end
              conn.write(buf)
              yield(buf) if block_given?
            end
            conn.shutdown(Socket::SHUT_WR) rescue nil
            conn.read_timeout = 1
            conn.read rescue nil
          ensure
            conn.close if conn
          end
          voidresp
        end
      end
    rescue Errno::EPIPE
      # EPIPE, in this case, means that the data connection was unexpectedly
      # terminated.  Rather than just raising EPIPE to the caller, check the
      # response on the control connection.  If getresp doesn't raise a more
      # appropriate exception, re-raise the original exception.
      getresp
      raise
    end

system() click to toggle source

Returns system information.

    # File lib/net/ftp.rb, line 1219
    def system
      resp = sendcmd("SYST")
      if !resp.start_with?("215")
        raise FTPReplyError, resp
      end
      return get_body(resp)
    end

voidcmd(cmd) click to toggle source

Sends a command and expect a response beginning with '2'.

    # File lib/net/ftp.rb, line 501
    def voidcmd(cmd)
      synchronize do
        putline(cmd)
        voidresp
      end
    end

### Private Instance Methods

parse_mlsx_entry(entry) click to toggle source

    # File lib/net/ftp.rb, line 1069
    def parse_mlsx_entry(entry)
      facts, pathname = entry.chomp.split(/ /, 2)
      unless pathname
        raise FTPProtoError, entry
      end
      return MLSxEntry.new(
        facts.scan(/(.*?)=(.*?);/).each_with_object({}) {
          |(factname, value), h|
          name = factname.downcase
          h[name] = FACT_PARSERS[name].(value)
        },
        pathname)
    end

parse_pasv_ipv4_host(s) click to toggle source

    # File lib/net/ftp.rb, line 1398
    def parse_pasv_ipv4_host(s)
      return s.tr(",", ".")
    end

parse_pasv_ipv6_host(s) click to toggle source

    # File lib/net/ftp.rb, line 1403
    def parse_pasv_ipv6_host(s)
      return s.split(/,/).map { |i|
        "%02x" % i.to_i
      }.each_slice(2).map(&:join).join(":")
    end

parse_pasv_port(s) click to toggle source

    # File lib/net/ftp.rb, line 1410
    def parse_pasv_port(s)
      return s.split(/,/).map(&:to_i).inject { |x, y|
        (x << 8) + y
      }
    end

start_tls_session(sock) click to toggle source

    # File lib/net/ftp.rb, line 343
    def start_tls_session(sock)
      ssl_sock = SSLSocket.new(sock, @ssl_context)
      ssl_sock.sync_close = true
      ssl_sock.hostname = @host if ssl_sock.respond_to? :hostname=
      if @ssl_session &&
          Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
        # ProFTPD returns 425 for data connections if session is not reused.
        ssl_sock.session = @ssl_session
      end
      ssl_socket_connect(ssl_sock, @ssl_handshake_timeout || @open_timeout)
      if @ssl_context.verify_mode != VERIFY_NONE
        ssl_sock.post_connection_check(@host)
      end
      return ssl_sock
    end