class Net::FTP - net-ftp: Ruby Standard Library Documentation

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

## Mainframe User Support¶ ↑

- `literal`

- `quote`

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

debug_output[RW]

Sets or retrieves the output stream for debugging. Output stream will be used only when `debug_mode` is set to true. The default value is +$stdout+.

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 net-ftp-0.3.8/lib/net/ftp.rb, line 165
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 159
    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`[:ssl] 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`[:ssl] 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`[:ssl] is true.

implicit_ftps

  If true, TLS is established on initial connection. Default: `false`

username

  Username for login. If `options`[:username] is the string “anonymous” and the `options`[:password] 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

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 230
    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

        # jruby-openssl does not support session caching
        unless RUBY_ENGINE == "jruby"
          @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 }
        end

        @ssl_session = nil
        if options[:private_data_connection].nil?
          @private_data_connection = true
        else
          @private_data_connection = options[:private_data_connection]
        end
        if options[:implicit_ftps].nil?
          @implicit_ftps = false
        else
          @implicit_ftps = options[:implicit_ftps]
        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
        if options[:implicit_ftps]
          raise ArgumentError,
                "implicit_ftps can be set to true only when ssl is enabled"
        end
        @implicit_ftps = 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
      @debug_output = $stdout
      @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 net-ftp-0.3.8/lib/net/ftp.rb, line 175
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1283
    def abort
      line = "ABOR" + CRLF
      debug_print "put: ABOR"
      @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 net-ftp-0.3.8/lib/net/ftp.rb, line 925
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 314
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1194
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1397
    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` if and only if the connection is closed.

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1413
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 402
    def connect(host, port = FTP_PORT)
      debug_print "connect: #{host}:#{port}"
      synchronize do
        @host = host
        @bare_sock = open_socket(host, port)
        if @ssl_context
          begin
            unless @implicit_ftps
              set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
              voidcmd("AUTH TLS")
            end
            set_socket(BufferedSSLSocket.new(start_tls_session(@bare_sock), read_timeout: @read_timeout), @implicit_ftps)
            if @private_data_connection
              voidcmd("PBSZ 0")
              voidcmd("PROT P")
            end
          rescue OpenSSL::SSL::SSLError, OpenTimeout
            @sock.close
            raise
          end
        else
          set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
        end
      end
    end

debug_print(msg) click to toggle source

Writes debug message to the debug output stream

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1488
    def debug_print(msg)
      @debug_output << msg + "\n" if @debug_mode && @debug_output
    end

delete(filename) click to toggle source

Deletes a file on the server.

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1180
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1363
    def features
      resp = sendcmd("FEAT")
      if !resp.start_with?("211")
        raise FTPReplyError, resp
      end

      feats = []
      resp.each_line 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 net-ftp-0.3.8/lib/net/ftp.rb, line 849
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 788
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 823
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1326
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 949
    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
literal(arguments)
Alias for: quote
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 net-ftp-0.3.8/lib/net/ftp.rb, line 635
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1316
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1238
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1154
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1132
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1231
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 933
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1346
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1386
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 910
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 863
    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.

Returns the response which will contain a job number if the user was communicating with a mainframe in ASCII mode after issuing ‘quote site filetype=jes’

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

pwd() click to toggle source

Returns the current remote directory.

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

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

Exits the `FTP` session.

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

quote(arguments) click to toggle source

The “quote” subcommand sends arguments verbatim to the remote ftp server. The “literal” subcommand is an alias for “quote”. @param arguments Array to be sent verbatim to the remote ftp server

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1248
    def quote(arguments)
      sendcmd(arguments)
    end

Also aliased as: literal
read_timeout=(sec) click to toggle source

Setter for the `read_timeout` attribute.

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 142
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1169
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 666
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 691
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1256
    def rmdir(dirname)
      voidcmd("RMD #{dirname}")
    end

sendcmd(cmd) click to toggle source

Sends a command and returns the response.

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 523
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 432
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1353
    def site(arg)
      cmd = "SITE " + arg
      voidcmd(cmd)
    end

size(filename) click to toggle source

Returns the size of the given (remote) filename.

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1217
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1300
    def status(pathname = nil)
      line = pathname ? "STAT #{pathname}" : "STAT"
      if /[\r\n]/ =~ line
        raise ArgumentError, "A line must not contain CR or LF"
      end
      debug_print "put: #{line}"
      @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 net-ftp-0.3.8/lib/net/ftp.rb, line 716
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 752
    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
          getresp # The response might be important when connected to a mainframe
        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 net-ftp-0.3.8/lib/net/ftp.rb, line 1272
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 533
    def voidcmd(cmd)
      synchronize do
        putline(cmd)
        voidresp
      end
    end

### Private Instance Methods

parse_mlsx_entry(entry) click to toggle source

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1112
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1438
    def parse_pasv_ipv4_host(s)
      return s.tr(",", ".")
    end

parse_pasv_ipv6_host(s) click to toggle source

    # File net-ftp-0.3.8/lib/net/ftp.rb, line 1443
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 1450
    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 net-ftp-0.3.8/lib/net/ftp.rb, line 379
    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