2004-03-16 07:42:53 +01:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Unified SMTP/FTP subsystem
|
|
|
|
-- LuaSocket toolkit.
|
|
|
|
-- Author: Diego Nehab
|
|
|
|
-----------------------------------------------------------------------------
|
2004-05-30 23:36:22 +02:00
|
|
|
|
2004-06-04 17:15:45 +02:00
|
|
|
-----------------------------------------------------------------------------
|
2004-09-27 06:01:18 +02:00
|
|
|
-- Declare module and import dependencies
|
2004-06-04 17:15:45 +02:00
|
|
|
-----------------------------------------------------------------------------
|
2005-06-14 06:29:23 +02:00
|
|
|
local base = _G
|
2004-11-27 08:58:04 +01:00
|
|
|
local string = require("string")
|
2004-06-04 17:15:45 +02:00
|
|
|
local socket = require("socket")
|
2004-06-15 08:24:00 +02:00
|
|
|
local ltn12 = require("ltn12")
|
2013-05-27 10:45:09 +02:00
|
|
|
|
|
|
|
socket.tp = {}
|
|
|
|
local _M = socket.tp
|
2004-09-27 06:01:18 +02:00
|
|
|
|
2004-06-15 08:24:00 +02:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Program constants
|
|
|
|
-----------------------------------------------------------------------------
|
2013-05-27 10:45:09 +02:00
|
|
|
_M.TIMEOUT = 60
|
2004-03-16 07:42:53 +01:00
|
|
|
|
2004-06-15 08:24:00 +02:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Implementation
|
|
|
|
-----------------------------------------------------------------------------
|
2004-05-25 07:27:44 +02:00
|
|
|
-- gets server reply (works for SMTP and FTP)
|
2004-06-18 23:41:44 +02:00
|
|
|
local function get_reply(c)
|
2004-05-28 08:16:43 +02:00
|
|
|
local code, current, sep
|
2004-06-18 23:41:44 +02:00
|
|
|
local line, err = c: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-06-18 23:41:44 +02:00
|
|
|
line, err = c: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
|
2005-11-22 09:33:29 +01:00
|
|
|
until code == current and sep == " "
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
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)
|
2004-06-18 23:41:44 +02:00
|
|
|
local code, reply = get_reply(self.c)
|
2004-03-16 07:42:53 +01:00
|
|
|
if not code then return nil, reply end
|
2004-11-27 08:58:04 +01:00
|
|
|
if base.type(ok) ~= "function" then
|
2005-11-22 09:33:29 +01:00
|
|
|
if base.type(ok) == "table" then
|
2004-11-27 08:58:04 +01:00
|
|
|
for i, v in base.ipairs(ok) do
|
2005-11-22 09:33:29 +01:00
|
|
|
if string.find(code, v) then
|
|
|
|
return base.tonumber(code), reply
|
2004-11-27 08:58:04 +01:00
|
|
|
end
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
return nil, reply
|
|
|
|
else
|
2005-11-22 09:33:29 +01:00
|
|
|
if string.find(code, ok) then return base.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-11-27 08:58:04 +01:00
|
|
|
else return ok(base.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)
|
2009-05-27 11:31:38 +02:00
|
|
|
cmd = string.upper(cmd)
|
2005-11-22 09:33:29 +01:00
|
|
|
if arg then
|
2004-11-27 08:58:04 +01:00
|
|
|
return self.c:send(cmd .. " " .. arg.. "\r\n")
|
2005-11-22 09:33:29 +01:00
|
|
|
else
|
|
|
|
return self.c:send(cmd .. "\r\n")
|
2004-11-27 08:58:04 +01:00
|
|
|
end
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:sink(snk, pat)
|
2004-06-18 23:41:44 +02:00
|
|
|
local chunk, err = c: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)
|
2004-06-18 23:41:44 +02:00
|
|
|
return self.c:send(data)
|
2004-05-25 07:27:44 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:receive(pat)
|
2004-06-18 23:41:44 +02:00
|
|
|
return self.c:receive(pat)
|
2004-05-25 07:27:44 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:getfd()
|
2004-06-18 23:41:44 +02:00
|
|
|
return self.c:getfd()
|
2004-05-25 07:27:44 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function metat.__index:dirty()
|
2004-06-18 23:41:44 +02:00
|
|
|
return self.c:dirty()
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:getcontrol()
|
2004-06-18 23:41:44 +02:00
|
|
|
return self.c
|
2004-03-18 08:01:14 +01:00
|
|
|
end
|
|
|
|
|
2004-05-26 06:58:32 +02:00
|
|
|
function metat.__index:source(source, step)
|
2004-06-18 23:41:44 +02:00
|
|
|
local sink = socket.sink("keep-open", self.c)
|
2005-08-12 07:56:32 +02:00
|
|
|
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
|
|
|
return ret, err
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-06-18 23:41:44 +02:00
|
|
|
-- closes the underlying c
|
2004-05-25 07:27:44 +02:00
|
|
|
function metat.__index:close()
|
2004-06-18 23:41:44 +02:00
|
|
|
self.c:close()
|
2011-05-25 22:57:22 +02:00
|
|
|
return 1
|
2004-03-16 07:42:53 +01:00
|
|
|
end
|
|
|
|
|
2004-06-18 23:41:44 +02:00
|
|
|
-- connect with server and return c object
|
2013-05-27 10:45:09 +02:00
|
|
|
function _M.connect(host, port, timeout, create)
|
2006-03-14 10:04:15 +01:00
|
|
|
local c, e = (create or socket.tcp)()
|
2004-06-18 23:41:44 +02:00
|
|
|
if not c then return nil, e end
|
2013-05-27 10:45:09 +02:00
|
|
|
c:settimeout(timeout or _M.TIMEOUT)
|
2004-06-18 23:41:44 +02:00
|
|
|
local r, e = c:connect(host, port)
|
2005-11-22 09:33:29 +01:00
|
|
|
if not r then
|
|
|
|
c:close()
|
2004-06-18 23:41:44 +02:00
|
|
|
return nil, e
|
|
|
|
end
|
2004-11-27 08:58:04 +01:00
|
|
|
return base.setmetatable({c = c}, metat)
|
2004-06-18 23:41:44 +02:00
|
|
|
end
|
2004-11-27 08:58:04 +01:00
|
|
|
|
2013-05-27 10:45:09 +02:00
|
|
|
return _M
|