Class: Raval::Handler

Inherits:
Object
  • Object
show all
Defined in:
lib/raval/handler.rb

Overview

implement the FTP wire protocol, deferring the users driver when interaction with the persistence layer is required. Nothing in this class is network aware, it should remain ignorant of where the FTP connection is from and assume the connection will handle it.

A new instance of this class is created for each active FTP connection, so it’s OK to store connection specific state in instance variables.

Constant Summary collapse

COMMANDS =
%w[quit type user retr stor eprt port cdup cwd dele rmd pwd
list size syst mkd pass xcup xpwd xcwd xrmd rest allo nlst
pasv epsv help noop mode rnfr rnto stru mdtm]
REQUIRE_AUTH =
%w[cdup xcup cwd xcwd eprt epsv mode nlst list mdtm pasv port
pwd xpwd retr size stor stru syst type]
REQUIRE_PARAM =
%w[cwd xcwd eprt mdtm mode pass port retr size stor stru
type user]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(driver) ⇒ Handler

Returns a new instance of Handler.



30
31
32
# File 'lib/raval/handler.rb', line 30

def initialize(driver)
  @driver = driver
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



28
29
30
# File 'lib/raval/handler.rb', line 28

def connection
  @connection
end

#name_prefixObject (readonly)

Returns the value of attribute name_prefix.



28
29
30
# File 'lib/raval/handler.rb', line 28

def name_prefix
  @name_prefix
end

Instance Method Details

#new_connection(connection) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/raval/handler.rb', line 34

def new_connection(connection)
  @mode   = :binary
  @user   = nil
  @name_prefix = "/"
  @connection = connection
  @connection.send_response(220, "FTP server (raval) ready")
end

#receive_line(line) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/raval/handler.rb', line 42

def receive_line(line)
  cmd, param = parse_request(line)

  # if the command is contained in the whitelist, and there is a method
  # to handle it, call it. Otherwise send an appropriate response to the
  # client
  if REQUIRE_AUTH.include?(cmd) && !logged_in?
    @connection.send_response(530, "Not logged in")
  elsif REQUIRE_PARAM.include?(cmd) && param.nil?
    @connection.send_response(553, "action aborted, required param missing")
  elsif COMMANDS.include?(cmd) && self.respond_to?("cmd_#{cmd}".to_sym, true)
    self.__send__("cmd_#{cmd}".to_sym, param)
  else
    @connection.send_response(500, "Sorry, I don't understand #{cmd.upcase}")
  end
end