2004-03-16 07:42:53 +01:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Unified SMTP/FTP subsystem
|
|
|
|
-- LuaSocket toolkit.
|
|
|
|
-- Author: Diego Nehab
|
|
|
|
-- Conforming to: RFC 2616, LTN7
|
|
|
|
-- RCS ID: $Id$
|
|
|
|
-----------------------------------------------------------------------------
|
2004-05-30 23:36:22 +02:00
|
|
|
|
2004-06-04 17:15:45 +02:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Load other required modules
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
local socket = require("socket")
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Setup namespace
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
tp = {}
|
|
|
|
setmetatable(tp, { __index = _G })
|
|
|
|
setfenv(1, tp)
|
2004-03-16 07:42:53 +01:00
|
|
|
|
|
|
|
TIMEOUT = 60
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
-- gets server reply (works for SMTP and FTP)
|
|
|
|
local function get_reply(control)
|
2004-05-28 08:16:43 +02:00
|
|
|
local code, current, sep
|
2004-05-25 07:27:44 +02:00
|
|
|
local line, err = control:receive()
|
2004-03-16 07:42:53 +01:00
|
|
|
local reply = line
|
2004-03-18 08:01:14 +01:00
|
|
|
if err then return nil, err end
|
2004-05-28 08:16:43 +02:00
|
|
|
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
2004-03-16 07:42:53 +01:00
|
|
|
if not code then return nil, "invalid server reply" end
|
2004-05-28 08:16:43 +02:00
|
|
|
if sep == "-" then -- reply is multiline
|
2004-03-16 07:42:53 +01:00
|
|
|
repeat
|
2004-05-25 07:27:44 +02:00
|
|
|
line, err = control:receive()
|
2004-03-18 08:01:14 +01:00
|
|
|
if err then return nil, err end
|
2004-05-28 08:16:43 +02:00
|
|
|
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
2004-03-16 07:42:53 +01:00
|
|
|
reply = reply .. "\n" .. line
|
|
|
|
-- reply ends with same code
|
2004-05-28 08:16:43 +02:00
|
|
|
until code == current and sep == " "
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
2004-05-30 23:36:22 +02:00
|
|
|
print(reply)
|
2004-03-16 07:42:53 +01:00
|
|
|
return code, reply
|
|
|
|
end
|
|
|
|
|
|
|
|
-- metatable for sock object
|
2004-05-25 07:27:44 +02:00
|
|
|
local metat = { __index = {} }
|
2004-03-16 07:42:53 +01:00
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:check(ok)
|
|
|
|
local code, reply = get_reply(self.control)
|
2004-03-16 07:42:53 +01:00
|
|
|
if not code then return nil, reply end
|
|
|
|
if type(ok) ~= "function" then
|
2004-03-18 08:01:14 +01:00
|
|
|
if type(ok) == "table" then
|
|
|
|
for i, v in ipairs(ok) do
|
2004-05-25 07:27:44 +02:00
|
|
|
if string.find(code, v) then return tonumber(code), reply end
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
return nil, reply
|
|
|
|
else
|
2004-05-25 07:27:44 +02:00
|
|
|
if string.find(code, ok) then return tonumber(code), reply
|
2004-03-18 08:01:14 +01:00
|
|
|
else return nil, reply end
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
2004-05-25 07:27:44 +02:00
|
|
|
else return ok(tonumber(code), reply) end
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:command(cmd, arg)
|
2004-05-30 23:36:22 +02:00
|
|
|
print(cmd, arg)
|
2004-05-25 07:27:44 +02:00
|
|
|
if arg then return self.control:send(cmd .. " " .. arg.. "\r\n")
|
|
|
|
else return self.control:send(cmd .. "\r\n") end
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:sink(snk, pat)
|
|
|
|
local chunk, err = control:receive(pat)
|
2004-03-16 07:42:53 +01:00
|
|
|
return snk(chunk, err)
|
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:send(data)
|
|
|
|
return self.control:send(data)
|
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:receive(pat)
|
|
|
|
return self.control:receive(pat)
|
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:getfd()
|
|
|
|
return self.control:getfd()
|
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:dirty()
|
|
|
|
return self.control:dirty()
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:getcontrol()
|
|
|
|
return self.control
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
|
2004-05-26 06:58:32 +02:00
|
|
|
function metat.__index:source(source, step)
|
|
|
|
local sink = socket.sink("keep-open", self.control)
|
|
|
|
return ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
-- closes the underlying control
|
|
|
|
function metat.__index:close()
|
|
|
|
self.control:close()
|
|
|
|
return 1
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
-- connect with server and return control object
|
2004-03-16 07:42:53 +01:00
|
|
|
function connect(host, port)
|
2004-05-25 07:27:44 +02:00
|
|
|
local control, err = socket.connect(host, port)
|
|
|
|
if not control then return nil, err end
|
|
|
|
control:settimeout(TIMEOUT)
|
|
|
|
return setmetatable({control = control}, metat)
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
2004-06-04 17:15:45 +02:00
|
|
|
|
|
|
|
return tp
|