# 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.

use_pasv_ip[RW]

When `true`, use the IP address in PASV responses. Otherwise, it uses the same IP address for the control connection. Default: `false`.

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 155
    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 149
    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`.

`use_pasv_ip`

  When `true`, use the IP address in PASV responses. Otherwise, it uses the same IP address for the control connection. Default: `false`.

`debug_mode`

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

Calls superclass method `MonitorMixin::new`

    # File lib/net/ftp.rb, line 218
    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
      @use_pasv_ip = options[:use_pasv_ip] || false
      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 165
    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 1234
    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 887
    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 286
    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 1155
    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 1312
    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 1328
    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 374
    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 1141
    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
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 816
    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 755
    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 790
    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 1276
    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 911
    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 606
    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 1266
    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 1199
    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 1115
    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 1093
    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 1192
    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 895
    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 1296
    def noop
      voidcmd("NOOP")
    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 872
    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 830
    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 859
    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 1214
    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 1287
    def quit
      voidcmd("QUIT")
    end

read_timeout=(sec) click to toggle source

Setter for the `read_timeout` attribute.

    # File lib/net/ftp.rb, line 132
    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 1130
    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 637
    def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
      synchronize do
        with_binary(true) do
          begin
            conn = transfercmd(cmd, rest_offset)
            loop do
              data = conn.read(blocksize)
              break if data == nil
              yield(data)
            end
            conn.shutdown(Socket::SHUT_WR)
            conn.read_timeout = 1
            conn.read
          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 664
    def retrlines(cmd) # :yield: line
      synchronize do
        with_binary(false) do
          begin
            conn = transfercmd(cmd)
            loop do
              line = conn.gets
              break if line == nil
              yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?)
            end
            conn.shutdown(Socket::SHUT_WR)
            conn.read_timeout = 1
            conn.read
          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 1207
    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 499
    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 404
    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 1303
    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 1178
    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 alot faster and over the same tcp session.

    # File lib/net/ftp.rb, line 1250
    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 691
    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
          conn = transfercmd(cmd)
          loop do
            buf = file.read(blocksize)
            break if buf == nil
            conn.write(buf)
            yield(buf) if block_given?
          end
          conn.close
          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 723
    def storlines(cmd, file) # :yield: line
      synchronize do
        with_binary(false) do
          conn = transfercmd(cmd)
          loop do
            buf = file.gets
            break if buf == nil
            if buf[-2, 2] != CRLF
              buf = buf.chomp + CRLF
            end
            conn.write(buf)
            yield(buf) if block_given?
          end
          conn.close
          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 1223
    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 509
    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 1073
    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 1371
    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 1376
    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 1383
    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 351
    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