1
-----------------------------------------------------------------------------
2
-- Unified SMTP/FTP subsystem
5
-- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $
6
-----------------------------------------------------------------------------
8
-----------------------------------------------------------------------------
9
-- Declare module and import dependencies
10
-----------------------------------------------------------------------------
12
local string = require("string")
13
local socket = require("socket")
14
local ltn12 = require("ltn12")
17
-----------------------------------------------------------------------------
19
-----------------------------------------------------------------------------
22
-----------------------------------------------------------------------------
24
-----------------------------------------------------------------------------
25
-- gets server reply (works for SMTP and FTP)
26
local function get_reply(c)
27
local code, current, sep
28
local line, err = c:receive()
30
if err then return nil, err end
31
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
32
if not code then return nil, "invalid server reply" end
33
if sep == "-" then -- reply is multiline
35
line, err = c:receive()
36
if err then return nil, err end
37
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
38
reply = reply .. "\n" .. line
39
-- reply ends with same code
40
until code == current and sep == " "
45
-- metatable for sock object
46
local metat = { __index = {} }
48
function metat.__index:check(ok)
49
local code, reply = get_reply(self.c)
50
if not code then return nil, reply end
51
if base.type(ok) ~= "function" then
52
if base.type(ok) == "table" then
53
for i, v in base.ipairs(ok) do
54
if string.find(code, v) then
55
return base.tonumber(code), reply
60
if string.find(code, ok) then return base.tonumber(code), reply
61
else return nil, reply end
63
else return ok(base.tonumber(code), reply) end
66
function metat.__index:command(cmd, arg)
68
return self.c:send(cmd .. " " .. arg.. "\r\n")
70
return self.c:send(cmd .. "\r\n")
74
function metat.__index:sink(snk, pat)
75
local chunk, err = c:receive(pat)
76
return snk(chunk, err)
79
function metat.__index:send(data)
80
return self.c:send(data)
83
function metat.__index:receive(pat)
84
return self.c:receive(pat)
87
function metat.__index:getfd()
91
function metat.__index:dirty()
95
function metat.__index:getcontrol()
99
function metat.__index:source(source, step)
100
local sink = socket.sink("keep-open", self.c)
101
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
105
-- closes the underlying c
106
function metat.__index:close()
111
-- connect with server and return c object
112
function connect(host, port, timeout, create)
113
local c, e = (create or socket.tcp)()
114
if not c then return nil, e end
115
c:settimeout(timeout or TIMEOUT)
116
local r, e = c:connect(host, port)
121
return base.setmetatable({c = c}, metat)