lib/ruby_ftp/client.rb
def write_data_command(cmd)
      result = ''

      response = write_command('PASV')
      success_regex = /227 Entering Passive Mode \((?<ip1>\d+),(?<ip2>\d+),(?<ip3>\d+),(?<ip4>\d+),(?<port1>\d+),(?<port2>\d+)\)\.\r\n/
      if (match = success_regex.match(response))
        # Doesn't work with Docker + Mac, cheating for now
        # data_ip = "#{match[:ip1]}.#{match[:ip2]}.#{match[:ip3]}.#{match[:ip4]}"
        data_ip = '127.0.0.1'
        data_port = (match[:port1].to_i << 8) + match[:port2].to_i

        @data_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
        # Connect non-blocking - the error means it's successful?
        begin
          @data_socket.connect_nonblock Socket.pack_sockaddr_in(data_port, data_ip)
        rescue IO::WaitWritable
          # This exception means it was successful

          res = write_command(cmd)
          puts res

          # Block waiting for an async read
          IO.select(nil, [@data_socket])

          result = ''
          while (line = @data_socket.gets)
            result += line
          end

          close_socket(@data_socket)

          command_response = read_command_response(command_socket)
          puts command_response
        end
      end

      result
    end
# Opens a new connection to the data socket after entering PASV mode
# Then we send the required command, block reading from the data channel,
Opens a new connection to the data socket after entering PASV mode
Then we send the required command, block reading from the data channel.
Opens a new connection to the data socket after entering PASV mode Then we send the required command block reading from the data channel .
def write_data_command(cmd)
      result = ''
      response = write_command('PASV')
      success_regex = /227 Entering Passive Mode \((?<ip1>\d+),(?<ip2>\d+),(?<ip3>\d+),(?<ip4>\d+),(?<port1>\d+),(?<port2>\d+)\)\.\r\n/
      if (match = success_regex.match(response))
        data_ip = '127.0.0.1'
        data_port = (match[:port1].to_i << 8) + match[:port2].to_i
        @data_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
        begin
          @data_socket.connect_nonblock Socket.pack_sockaddr_in(data_port, data_ip)
        rescue IO::WaitWritable
          res = write_command(cmd)
          puts res
          IO.select(nil, [@data_socket])
          result = ''
          while (line = @data_socket.gets)
            result += line
          end
          close_socket(@data_socket)
          command_response = read_command_response(command_socket)
          puts command_response
        end
      end
      result
    end
def write_data_command ( cmd ) result = '' response = write_command ( 'PASV' ) success_regex = / 227 Entering Passive Mode  \( (?<ip1> \d +),(?<ip2> \d +),(?<ip3> \d +),(?<ip4> \d +),(?<port1> \d +),(?<port2> \d +) \) \. \r \n / if ( match = success_regex . match ( response ) ) data_ip = '127.0.0.1' data_port = ( match [ :port1 ] . to_i << 8 ) + match [ :port2 ] . to_i @data_socket = Socket . new ( Socket :: AF_INET , Socket :: SOCK_STREAM , 0 ) begin @data_socket . connect_nonblock Socket . pack_sockaddr_in ( data_port , data_ip ) rescue IO :: WaitWritable res = write_command ( cmd ) puts res IO . select ( nil , [ @data_socket ] ) result = '' while ( line = @data_socket . gets ) result += line end close_socket ( @data_socket ) command_response = read_command_response ( command_socket ) puts command_response end end result end
Opens a new connection to the data socket after entering PASV mode
Then we send the required command, block reading from the data channel,
Opens a new connection to the data socket after entering PASV mode Then we send the required command block reading from the data channel
# Doesn't work with Docker + Mac, cheating for now # data_ip = "#{match[:ip1]}.#{match[:ip2]}.#{match[:ip3]}.#{match[:ip4]}" # Connect non-blocking - the error means it's successful? # This exception means it was successful # Block waiting for an async read
cmd