digital-scurf wiki Colloquy 2Parser

Initial simple Colloquy 2 parser implementation

-------------------------------------------------------------------------------
-- Colloquy 2 -- Protocol Parser
--
-- Copyright (c) 2005 Rob Kendrick <rjek@rjek.com>
--                    Daniel Silverstone <dsilvers@digital-scurf.org>
--
-- This code handles the parsing of the C2 protocol, and dispatching commands
-- to their handler functions.
--
-- Modules can add hooks into the parser to add new commands, and remove them
-- as an when they feel they want to.
--
-- A handler function is passed four parameters.  These are:
--   connection: The connection object that the command should be executed as
--   tag: The client's chosen prefix tag for this command
--   command: The command's token/name (ie, 'SAY')
--   parameters: The rest of the data as-is.
-------------------------------------------------------------------------------

local handlers = { }

local setHandler = function(token, handler, permissions, comment)
  -- Sets a handler for a token to the parser.
  -- token: Token we're dealing with (ie, 'SAY' or 'QUIT')
  -- handler: Function to call to deal with this, or nil to remove it.
  -- permissions: A function to call to see if the current user has permission
  --              to execute this command.  It is passed the user's connection
  --              object, and the command's name, and its parameter data.
  -- comment: Normally just the name of the module providing this handler
  --
  -- Return value: nil on success, otherwise an error string.  This will
  --               almost certainly be 'Token already handled'

  if handler then
    handlers[token] = {
      handler = handler,
      permissions = permissions,
      comment = comment
    }
  else
    handlers[token] = nil
  end

  return nil

end

local doParse = function(connection, data)
  -- Parses and executes a command from a client
  -- connection: Connection of the client we're doing this as
  -- data: A single line of data that we've received from them.
  --
  -- Return value: Always nil

  local handler
  local null, null, tag, command, parameters =
    string.find(data, "(%S*) (%S*) ?(.*)")

  handler = handlers[command]

  if handler then
    if handler.permissions(connection, command, parameters) then
      pcall(handler, connection, tag, command, parameters)
    else
      connection:send(tag .. " ERROR Insufficient privilege")
    end
  else
    connection:send(tag .. " ERROR Unhandled command")
  end

  return nil
end

parser = {
  set = setHandler,
  parse = doParse
}