aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2005-11-22 08:33:29 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2005-11-22 08:33:29 +0000
commitd55a5826e81136a9ecf65c4cd407152a56684dc2 (patch)
tree109ad44c75cee890ad5e98583e12b15b5e65a18e /src
parenta2b780bf7a78c66d54a248fa99b5fc862c12a127 (diff)
downloadluasocket-d55a5826e81136a9ecf65c4cd407152a56684dc2.tar.gz
luasocket-d55a5826e81136a9ecf65c4cd407152a56684dc2.tar.bz2
luasocket-d55a5826e81136a9ecf65c4cd407152a56684dc2.zip
Few tweaks in installation, some missing files, etc.
Diffstat (limited to 'src')
-rw-r--r--src/ftp.lua26
-rw-r--r--src/http.lua32
-rw-r--r--src/ltn12.lua30
-rw-r--r--src/mbox.lua2
-rw-r--r--src/mime.lua14
-rw-r--r--src/smtp.lua42
-rw-r--r--src/socket.lua16
-rw-r--r--src/tp.lua20
-rw-r--r--src/url.lua50
-rw-r--r--src/usocket.c3
10 files changed, 118 insertions, 117 deletions
diff --git a/src/ftp.lua b/src/ftp.lua
index c83c1cb..5e1b685 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -40,7 +40,7 @@ function open(server, port, create)
40 local f = base.setmetatable({ tp = tp }, metat) 40 local f = base.setmetatable({ tp = tp }, metat)
41 -- make sure everything gets closed in an exception 41 -- make sure everything gets closed in an exception
42 f.try = socket.newtry(function() f:close() end) 42 f.try = socket.newtry(function() f:close() end)
43 return f 43 return f
44end 44end
45 45
46function metat.__index:portconnect() 46function metat.__index:portconnect()
@@ -71,20 +71,20 @@ function metat.__index:pasv()
71 local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" 71 local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
72 local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) 72 local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
73 self.try(a and b and c and d and p1 and p2, reply) 73 self.try(a and b and c and d and p1 and p2, reply)
74 self.pasvt = { 74 self.pasvt = {
75 ip = string.format("%d.%d.%d.%d", a, b, c, d), 75 ip = string.format("%d.%d.%d.%d", a, b, c, d),
76 port = p1*256 + p2 76 port = p1*256 + p2
77 } 77 }
78 if self.server then 78 if self.server then
79 self.server:close() 79 self.server:close()
80 self.server = nil 80 self.server = nil
81 end 81 end
82 return self.pasvt.ip, self.pasvt.port 82 return self.pasvt.ip, self.pasvt.port
83end 83end
84 84
85function metat.__index:port(ip, port) 85function metat.__index:port(ip, port)
86 self.pasvt = nil 86 self.pasvt = nil
87 if not ip then 87 if not ip then
88 ip, port = self.try(self.tp:getcontrol():getsockname()) 88 ip, port = self.try(self.tp:getcontrol():getsockname())
89 self.server = self.try(socket.bind(ip, 0)) 89 self.server = self.try(socket.bind(ip, 0))
90 ip, port = self.try(self.server:getsockname()) 90 ip, port = self.try(self.server:getsockname())
@@ -100,11 +100,11 @@ end
100 100
101function metat.__index:send(sendt) 101function metat.__index:send(sendt)
102 self.try(self.pasvt or self.server, "need port or pasv first") 102 self.try(self.pasvt or self.server, "need port or pasv first")
103 -- if there is a pasvt table, we already sent a PASV command 103 -- if there is a pasvt table, we already sent a PASV command
104 -- we just get the data connection into self.data 104 -- we just get the data connection into self.data
105 if self.pasvt then self:pasvconnect() end 105 if self.pasvt then self:pasvconnect() end
106 -- get the transfer argument and command 106 -- get the transfer argument and command
107 local argument = sendt.argument or 107 local argument = sendt.argument or
108 url.unescape(string.gsub(sendt.path or "", "^[/\\]", "")) 108 url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
109 if argument == "" then argument = nil end 109 if argument == "" then argument = nil end
110 local command = sendt.command or "stor" 110 local command = sendt.command or "stor"
@@ -137,7 +137,7 @@ end
137function metat.__index:receive(recvt) 137function metat.__index:receive(recvt)
138 self.try(self.pasvt or self.server, "need port or pasv first") 138 self.try(self.pasvt or self.server, "need port or pasv first")
139 if self.pasvt then self:pasvconnect() end 139 if self.pasvt then self:pasvconnect() end
140 local argument = recvt.argument or 140 local argument = recvt.argument or
141 url.unescape(string.gsub(recvt.path or "", "^[/\\]", "")) 141 url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
142 if argument == "" then argument = nil end 142 if argument == "" then argument = nil end
143 local command = recvt.command or "retr" 143 local command = recvt.command or "retr"
@@ -220,7 +220,7 @@ local function parse(u)
220 socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") 220 socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
221 socket.try(t.host, "missing hostname") 221 socket.try(t.host, "missing hostname")
222 local pat = "^type=(.)$" 222 local pat = "^type=(.)$"
223 if t.params then 223 if t.params then
224 t.type = socket.skip(2, string.find(t.params, pat)) 224 t.type = socket.skip(2, string.find(t.params, pat))
225 socket.try(t.type == "a" or t.type == "i", 225 socket.try(t.type == "a" or t.type == "i",
226 "invalid type '" .. t.type .. "'") 226 "invalid type '" .. t.type .. "'")
@@ -229,7 +229,7 @@ local function parse(u)
229end 229end
230 230
231local function sput(u, body) 231local function sput(u, body)
232 local putt = parse(u) 232 local putt = parse(u)
233 putt.source = ltn12.source.string(body) 233 putt.source = ltn12.source.string(body)
234 return tput(putt) 234 return tput(putt)
235end 235end
@@ -253,7 +253,7 @@ local function tget(gett)
253end 253end
254 254
255local function sget(u) 255local function sget(u)
256 local gett = parse(u) 256 local gett = parse(u)
257 local t = {} 257 local t = {}
258 gett.sink = ltn12.sink.table(t) 258 gett.sink = ltn12.sink.table(t)
259 tget(gett) 259 tget(gett)
diff --git a/src/http.lua b/src/http.lua
index f08da07..1834061 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -21,7 +21,7 @@ module("socket.http")
21-- Program constants 21-- Program constants
22----------------------------------------------------------------------------- 22-----------------------------------------------------------------------------
23-- connection timeout in seconds 23-- connection timeout in seconds
24TIMEOUT = 60 24TIMEOUT = 60
25-- default port for document retrieval 25-- default port for document retrieval
26PORT = 80 26PORT = 80
27-- user agent field sent in request 27-- user agent field sent in request
@@ -65,18 +65,18 @@ socket.sourcet["http-chunked"] = function(sock, headers)
65 return base.setmetatable({ 65 return base.setmetatable({
66 getfd = function() return sock:getfd() end, 66 getfd = function() return sock:getfd() end,
67 dirty = function() return sock:dirty() end 67 dirty = function() return sock:dirty() end
68 }, { 68 }, {
69 __call = function() 69 __call = function()
70 -- get chunk size, skip extention 70 -- get chunk size, skip extention
71 local line, err = sock:receive() 71 local line, err = sock:receive()
72 if err then return nil, err end 72 if err then return nil, err end
73 local size = base.tonumber(string.gsub(line, ";.*", ""), 16) 73 local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
74 if not size then return nil, "invalid chunk size" end 74 if not size then return nil, "invalid chunk size" end
75 -- was it the last chunk? 75 -- was it the last chunk?
76 if size > 0 then 76 if size > 0 then
77 -- if not, get chunk and skip terminating CRLF 77 -- if not, get chunk and skip terminating CRLF
78 local chunk, err, part = sock:receive(size) 78 local chunk, err, part = sock:receive(size)
79 if chunk then sock:receive() end 79 if chunk then sock:receive() end
80 return chunk, err 80 return chunk, err
81 else 81 else
82 -- if it was, read trailers into headers table 82 -- if it was, read trailers into headers table
@@ -91,7 +91,7 @@ socket.sinkt["http-chunked"] = function(sock)
91 return base.setmetatable({ 91 return base.setmetatable({
92 getfd = function() return sock:getfd() end, 92 getfd = function() return sock:getfd() end,
93 dirty = function() return sock:dirty() end 93 dirty = function() return sock:dirty() end
94 }, { 94 }, {
95 __call = function(self, chunk, err) 95 __call = function(self, chunk, err)
96 if not chunk then return sock:send("0\r\n\r\n") end 96 if not chunk then return sock:send("0\r\n\r\n") end
97 local size = string.format("%X\r\n", string.len(chunk)) 97 local size = string.format("%X\r\n", string.len(chunk))
@@ -115,11 +115,11 @@ function open(host, port, create)
115 h.try(c:settimeout(TIMEOUT)) 115 h.try(c:settimeout(TIMEOUT))
116 h.try(c:connect(host, port or PORT)) 116 h.try(c:connect(host, port or PORT))
117 -- here everything worked 117 -- here everything worked
118 return h 118 return h
119end 119end
120 120
121function metat.__index:sendrequestline(method, uri) 121function metat.__index:sendrequestline(method, uri)
122 local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) 122 local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
123 return self.try(self.c:send(reqline)) 123 return self.try(self.c:send(reqline))
124end 124end
125 125
@@ -133,7 +133,7 @@ function metat.__index:sendheaders(headers)
133end 133end
134 134
135function metat.__index:sendbody(headers, source, step) 135function metat.__index:sendbody(headers, source, step)
136 source = source or ltn12.source.empty() 136 source = source or ltn12.source.empty()
137 step = step or ltn12.pump.step 137 step = step or ltn12.pump.step
138 -- if we don't know the size in advance, send chunked and hope for the best 138 -- if we don't know the size in advance, send chunked and hope for the best
139 local mode = "http-chunked" 139 local mode = "http-chunked"
@@ -159,7 +159,7 @@ function metat.__index:receivebody(headers, sink, step)
159 local mode = "default" -- connection close 159 local mode = "default" -- connection close
160 if t and t ~= "identity" then mode = "http-chunked" 160 if t and t ~= "identity" then mode = "http-chunked"
161 elseif base.tonumber(headers["content-length"]) then mode = "by-length" end 161 elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
162 return self.try(ltn12.pump.all(socket.source(mode, self.c, length), 162 return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
163 sink, step)) 163 sink, step))
164end 164end
165 165
@@ -185,7 +185,7 @@ local function adjusturi(reqt)
185end 185end
186 186
187local function adjustproxy(reqt) 187local function adjustproxy(reqt)
188 local proxy = reqt.proxy or PROXY 188 local proxy = reqt.proxy or PROXY
189 if proxy then 189 if proxy then
190 proxy = url.parse(proxy) 190 proxy = url.parse(proxy)
191 return proxy.host, proxy.port or 3128 191 return proxy.host, proxy.port or 3128
@@ -292,10 +292,10 @@ function trequest(reqt)
292 local code, headers, status 292 local code, headers, status
293 code, status = h:receivestatusline() 293 code, status = h:receivestatusline()
294 headers = h:receiveheaders() 294 headers = h:receiveheaders()
295 if shouldredirect(reqt, code, headers) then 295 if shouldredirect(reqt, code, headers) then
296 h:close() 296 h:close()
297 return tredirect(reqt, headers.location) 297 return tredirect(reqt, headers.location)
298 elseif shouldauthorize(reqt, code) then 298 elseif shouldauthorize(reqt, code) then
299 h:close() 299 h:close()
300 return tauthorize(reqt) 300 return tauthorize(reqt)
301 elseif shouldreceivebody(reqt, code) then 301 elseif shouldreceivebody(reqt, code) then
@@ -307,12 +307,12 @@ end
307 307
308local function srequest(u, body) 308local function srequest(u, body)
309 local t = {} 309 local t = {}
310 local reqt = { 310 local reqt = {
311 url = u, 311 url = u,
312 sink = ltn12.sink.table(t) 312 sink = ltn12.sink.table(t)
313 } 313 }
314 if body then 314 if body then
315 reqt.source = ltn12.source.string(body) 315 reqt.source = ltn12.source.string(body)
316 reqt.headers = { ["content-length"] = string.len(body) } 316 reqt.headers = { ["content-length"] = string.len(body) }
317 reqt.method = "POST" 317 reqt.method = "POST"
318 end 318 end
diff --git a/src/ltn12.lua b/src/ltn12.lua
index 2c16253..c49d130 100644
--- a/src/ltn12.lua
+++ b/src/ltn12.lua
@@ -36,19 +36,19 @@ end
36 36
37-- chains a bunch of filters together 37-- chains a bunch of filters together
38-- (thanks to Wim Couwenberg) 38-- (thanks to Wim Couwenberg)
39function filter.chain(...) 39function filter.chain(...)
40 local n = table.getn(arg) 40 local n = table.getn(arg)
41 local top, index = 1, 1 41 local top, index = 1, 1
42 local retry = "" 42 local retry = ""
43 return function(chunk) 43 return function(chunk)
44 retry = chunk and retry 44 retry = chunk and retry
45 while true do 45 while true do
46 if index == top then 46 if index == top then
47 chunk = arg[index](chunk) 47 chunk = arg[index](chunk)
48 if chunk == "" or top == n then return chunk 48 if chunk == "" or top == n then return chunk
49 elseif chunk then index = index + 1 49 elseif chunk then index = index + 1
50 else 50 else
51 top = top+1 51 top = top+1
52 index = top 52 index = top
53 end 53 end
54 else 54 else
@@ -148,9 +148,9 @@ function source.chain(src, f)
148 last_in, err = src() 148 last_in, err = src()
149 if err then return nil, err end 149 if err then return nil, err end
150 last_out = f(last_in) 150 last_out = f(last_in)
151 if not last_out then 151 if not last_out then
152 if last_in then 152 if last_in then
153 base.error('filter returned inappropriate nil') 153 base.error('filter returned inappropriate nil')
154 else 154 else
155 return nil 155 return nil
156 end 156 end
@@ -159,17 +159,17 @@ function source.chain(src, f)
159 if last_in then last_in = "" end 159 if last_in then last_in = "" end
160 return last_out 160 return last_out
161 end 161 end
162 else 162 else
163 last_out = f(last_in) 163 last_out = f(last_in)
164 if last_out == "" then 164 if last_out == "" then
165 if last_in == "" then 165 if last_in == "" then
166 state = "feeding" 166 state = "feeding"
167 else 167 else
168 base.error('filter returned ""') 168 base.error('filter returned ""')
169 end 169 end
170 elseif not last_out then 170 elseif not last_out then
171 if last_in then 171 if last_in then
172 base.error('filter returned inappropriate nil') 172 base.error('filter returned inappropriate nil')
173 else 173 else
174 return nil 174 return nil
175 end 175 end
@@ -224,7 +224,7 @@ end
224function sink.file(handle, io_err) 224function sink.file(handle, io_err)
225 if handle then 225 if handle then
226 return function(chunk, err) 226 return function(chunk, err)
227 if not chunk then 227 if not chunk then
228 handle:close() 228 handle:close()
229 return 1 229 return 1
230 else return handle:write(chunk) end 230 else return handle:write(chunk) end
@@ -248,7 +248,7 @@ function sink.error(err)
248 end 248 end
249end 249end
250 250
251-- chains a sink with a filter 251-- chains a sink with a filter
252function sink.chain(f, snk) 252function sink.chain(f, snk)
253 base.assert(f and snk) 253 base.assert(f and snk)
254 return function(chunk, err) 254 return function(chunk, err)
@@ -282,7 +282,7 @@ function pump.all(src, snk, step)
282 step = step or pump.step 282 step = step or pump.step
283 while true do 283 while true do
284 local ret, err = step(src, snk) 284 local ret, err = step(src, snk)
285 if not ret then 285 if not ret then
286 if err then return nil, err 286 if err then return nil, err
287 else return 1 end 287 else return 1 end
288 end 288 end
diff --git a/src/mbox.lua b/src/mbox.lua
index f52719b..ce6537c 100644
--- a/src/mbox.lua
+++ b/src/mbox.lua
@@ -10,7 +10,7 @@ function Public.split_message(message_s)
10 if not message.body then 10 if not message.body then
11 string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) 11 string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
12 end 12 end
13 if not message.headers and not message.body then 13 if not message.headers and not message.body then
14 message.headers = message_s 14 message.headers = message_s
15 end 15 end
16 return message.headers or "", message.body or "" 16 return message.headers or "", message.body or ""
diff --git a/src/mime.lua b/src/mime.lua
index f6a9333..3182545 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -20,10 +20,10 @@ encodet = {}
20decodet = {} 20decodet = {}
21wrapt = {} 21wrapt = {}
22 22
23-- creates a function that chooses a filter by name from a given table 23-- creates a function that chooses a filter by name from a given table
24local function choose(table) 24local function choose(table)
25 return function(name, opt1, opt2) 25 return function(name, opt1, opt2)
26 if base.type(name) ~= "string" then 26 if base.type(name) ~= "string" then
27 name, opt1, opt2 = "default", name, opt1 27 name, opt1, opt2 = "default", name, opt1
28 end 28 end
29 local f = table[name or "nil"] 29 local f = table[name or "nil"]
@@ -38,7 +38,7 @@ encodet['base64'] = function()
38end 38end
39 39
40encodet['quoted-printable'] = function(mode) 40encodet['quoted-printable'] = function(mode)
41 return ltn12.filter.cycle(qp, "", 41 return ltn12.filter.cycle(qp, "",
42 (mode == "binary") and "=0D=0A" or "\r\n") 42 (mode == "binary") and "=0D=0A" or "\r\n")
43end 43end
44 44
@@ -56,22 +56,22 @@ local function format(chunk)
56 if chunk == "" then return "''" 56 if chunk == "" then return "''"
57 else return string.len(chunk) end 57 else return string.len(chunk) end
58 else return "nil" end 58 else return "nil" end
59end 59end
60 60
61-- define the line-wrap filters 61-- define the line-wrap filters
62wrapt['text'] = function(length) 62wrapt['text'] = function(length)
63 length = length or 76 63 length = length or 76
64 return ltn12.filter.cycle(wrp, length, length) 64 return ltn12.filter.cycle(wrp, length, length)
65end 65end
66wrapt['base64'] = wrapt['text'] 66wrapt['base64'] = wrapt['text']
67wrapt['default'] = wrapt['text'] 67wrapt['default'] = wrapt['text']
68 68
69wrapt['quoted-printable'] = function() 69wrapt['quoted-printable'] = function()
70 return ltn12.filter.cycle(qpwrp, 76, 76) 70 return ltn12.filter.cycle(qpwrp, 76, 76)
71end 71end
72 72
73-- function that choose the encoding, decoding or wrap algorithm 73-- function that choose the encoding, decoding or wrap algorithm
74encode = choose(encodet) 74encode = choose(encodet)
75decode = choose(decodet) 75decode = choose(decodet)
76wrap = choose(wrapt) 76wrap = choose(wrapt)
77 77
diff --git a/src/smtp.lua b/src/smtp.lua
index 03b9e9b..72c4234 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -27,8 +27,8 @@ TIMEOUT = 60
27-- default server used to send e-mails 27-- default server used to send e-mails
28SERVER = "localhost" 28SERVER = "localhost"
29-- default port 29-- default port
30PORT = 25 30PORT = 25
31-- domain used in HELO command and default sendmail 31-- domain used in HELO command and default sendmail
32-- If we are under a CGI, try to get from environment 32-- If we are under a CGI, try to get from environment
33DOMAIN = os.getenv("SERVER_NAME") or "localhost" 33DOMAIN = os.getenv("SERVER_NAME") or "localhost"
34-- default time zone (means we don't know) 34-- default time zone (means we don't know)
@@ -43,12 +43,12 @@ function metat.__index:greet(domain)
43 self.try(self.tp:check("2..")) 43 self.try(self.tp:check("2.."))
44 self.try(self.tp:command("EHLO", domain or DOMAIN)) 44 self.try(self.tp:command("EHLO", domain or DOMAIN))
45 return socket.skip(1, self.try(self.tp:check("2.."))) 45 return socket.skip(1, self.try(self.tp:check("2..")))
46end 46end
47 47
48function metat.__index:mail(from) 48function metat.__index:mail(from)
49 self.try(self.tp:command("MAIL", "FROM:" .. from)) 49 self.try(self.tp:command("MAIL", "FROM:" .. from))
50 return self.try(self.tp:check("2..")) 50 return self.try(self.tp:check("2.."))
51end 51end
52 52
53function metat.__index:rcpt(to) 53function metat.__index:rcpt(to)
54 self.try(self.tp:command("RCPT", "TO:" .. to)) 54 self.try(self.tp:command("RCPT", "TO:" .. to))
@@ -99,7 +99,7 @@ function metat.__index:auth(user, password, ext)
99end 99end
100 100
101-- send message or throw an exception 101-- send message or throw an exception
102function metat.__index:send(mailt) 102function metat.__index:send(mailt)
103 self:mail(mailt.from) 103 self:mail(mailt.from)
104 if base.type(mailt.rcpt) == "table" then 104 if base.type(mailt.rcpt) == "table" then
105 for i,v in base.ipairs(mailt.rcpt) do 105 for i,v in base.ipairs(mailt.rcpt) do
@@ -112,14 +112,14 @@ function metat.__index:send(mailt)
112end 112end
113 113
114function open(server, port, create) 114function open(server, port, create)
115 local tp = socket.try(tp.connect(server or SERVER, port or PORT, 115 local tp = socket.try(tp.connect(server or SERVER, port or PORT,
116 create, TIMEOUT)) 116 create, TIMEOUT))
117 local s = base.setmetatable({tp = tp}, metat) 117 local s = base.setmetatable({tp = tp}, metat)
118 -- make sure tp is closed if we get an exception 118 -- make sure tp is closed if we get an exception
119 s.try = socket.newtry(function() 119 s.try = socket.newtry(function()
120 s:close() 120 s:close()
121 end) 121 end)
122 return s 122 return s
123end 123end
124 124
125--------------------------------------------------------------------------- 125---------------------------------------------------------------------------
@@ -142,7 +142,7 @@ local function send_headers(headers)
142 for i,v in base.pairs(headers) do 142 for i,v in base.pairs(headers) do
143 h = i .. ': ' .. v .. "\r\n" .. h 143 h = i .. ': ' .. v .. "\r\n" .. h
144 end 144 end
145 coroutine.yield(h) 145 coroutine.yield(h)
146end 146end
147 147
148-- yield multipart message body from a multipart message table 148-- yield multipart message body from a multipart message table
@@ -151,25 +151,25 @@ local function send_multipart(mesgt)
151 local bd = newboundary() 151 local bd = newboundary()
152 local headers = mesgt.headers or {} 152 local headers = mesgt.headers or {}
153 headers['content-type'] = headers['content-type'] or 'multipart/mixed' 153 headers['content-type'] = headers['content-type'] or 'multipart/mixed'
154 headers['content-type'] = headers['content-type'] .. 154 headers['content-type'] = headers['content-type'] ..
155 '; boundary="' .. bd .. '"' 155 '; boundary="' .. bd .. '"'
156 send_headers(headers) 156 send_headers(headers)
157 -- send preamble 157 -- send preamble
158 if mesgt.body.preamble then 158 if mesgt.body.preamble then
159 coroutine.yield(mesgt.body.preamble) 159 coroutine.yield(mesgt.body.preamble)
160 coroutine.yield("\r\n") 160 coroutine.yield("\r\n")
161 end 161 end
162 -- send each part separated by a boundary 162 -- send each part separated by a boundary
163 for i, m in base.ipairs(mesgt.body) do 163 for i, m in base.ipairs(mesgt.body) do
164 coroutine.yield("\r\n--" .. bd .. "\r\n") 164 coroutine.yield("\r\n--" .. bd .. "\r\n")
165 send_message(m) 165 send_message(m)
166 end 166 end
167 -- send last boundary 167 -- send last boundary
168 coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") 168 coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
169 -- send epilogue 169 -- send epilogue
170 if mesgt.body.epilogue then 170 if mesgt.body.epilogue then
171 coroutine.yield(mesgt.body.epilogue) 171 coroutine.yield(mesgt.body.epilogue)
172 coroutine.yield("\r\n") 172 coroutine.yield("\r\n")
173 end 173 end
174end 174end
175 175
@@ -181,7 +181,7 @@ local function send_source(mesgt)
181 'text/plain; charset="iso-8859-1"' 181 'text/plain; charset="iso-8859-1"'
182 send_headers(headers) 182 send_headers(headers)
183 -- send body from source 183 -- send body from source
184 while true do 184 while true do
185 local chunk, err = mesgt.body() 185 local chunk, err = mesgt.body()
186 if err then coroutine.yield(nil, err) 186 if err then coroutine.yield(nil, err)
187 elseif chunk then coroutine.yield(chunk) 187 elseif chunk then coroutine.yield(chunk)
@@ -213,11 +213,11 @@ local function adjust_headers(mesgt)
213 for i,v in base.pairs(mesgt.headers or lower) do 213 for i,v in base.pairs(mesgt.headers or lower) do
214 lower[string.lower(i)] = v 214 lower[string.lower(i)] = v
215 end 215 end
216 lower["date"] = lower["date"] or 216 lower["date"] = lower["date"] or
217 os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE) 217 os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
218 lower["x-mailer"] = lower["x-mailer"] or socket._VERSION 218 lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
219 -- this can't be overriden 219 -- this can't be overriden
220 lower["mime-version"] = "1.0" 220 lower["mime-version"] = "1.0"
221 mesgt.headers = lower 221 mesgt.headers = lower
222end 222end
223 223
@@ -225,7 +225,7 @@ function message(mesgt)
225 adjust_headers(mesgt) 225 adjust_headers(mesgt)
226 -- create and return message source 226 -- create and return message source
227 local co = coroutine.create(function() send_message(mesgt) end) 227 local co = coroutine.create(function() send_message(mesgt) end)
228 return function() 228 return function()
229 local ret, a, b = coroutine.resume(co) 229 local ret, a, b = coroutine.resume(co)
230 if ret then return a, b 230 if ret then return a, b
231 else return nil, a end 231 else return nil, a end
diff --git a/src/socket.lua b/src/socket.lua
index 6eb3159..458418e 100644
--- a/src/socket.lua
+++ b/src/socket.lua
@@ -19,7 +19,7 @@ module("socket")
19function connect(address, port, laddress, lport) 19function connect(address, port, laddress, lport)
20 local sock, err = socket.tcp() 20 local sock, err = socket.tcp()
21 if not sock then return nil, err end 21 if not sock then return nil, err end
22 if laddress then 22 if laddress then
23 local res, err = sock:bind(laddress, lport, -1) 23 local res, err = sock:bind(laddress, lport, -1)
24 if not res then return nil, err end 24 if not res then return nil, err end
25 end 25 end
@@ -65,9 +65,9 @@ sinkt["close-when-done"] = function(sock)
65 return base.setmetatable({ 65 return base.setmetatable({
66 getfd = function() return sock:getfd() end, 66 getfd = function() return sock:getfd() end,
67 dirty = function() return sock:dirty() end 67 dirty = function() return sock:dirty() end
68 }, { 68 }, {
69 __call = function(self, chunk, err) 69 __call = function(self, chunk, err)
70 if not chunk then 70 if not chunk then
71 sock:close() 71 sock:close()
72 return 1 72 return 1
73 else return sock:send(chunk) end 73 else return sock:send(chunk) end
@@ -79,7 +79,7 @@ sinkt["keep-open"] = function(sock)
79 return base.setmetatable({ 79 return base.setmetatable({
80 getfd = function() return sock:getfd() end, 80 getfd = function() return sock:getfd() end,
81 dirty = function() return sock:dirty() end 81 dirty = function() return sock:dirty() end
82 }, { 82 }, {
83 __call = function(self, chunk, err) 83 __call = function(self, chunk, err)
84 if chunk then return sock:send(chunk) 84 if chunk then return sock:send(chunk)
85 else return 1 end 85 else return 1 end
@@ -95,7 +95,7 @@ sourcet["by-length"] = function(sock, length)
95 return base.setmetatable({ 95 return base.setmetatable({
96 getfd = function() return sock:getfd() end, 96 getfd = function() return sock:getfd() end,
97 dirty = function() return sock:dirty() end 97 dirty = function() return sock:dirty() end
98 }, { 98 }, {
99 __call = function() 99 __call = function()
100 if length <= 0 then return nil end 100 if length <= 0 then return nil end
101 local size = math.min(socket.BLOCKSIZE, length) 101 local size = math.min(socket.BLOCKSIZE, length)
@@ -112,16 +112,16 @@ sourcet["until-closed"] = function(sock)
112 return base.setmetatable({ 112 return base.setmetatable({
113 getfd = function() return sock:getfd() end, 113 getfd = function() return sock:getfd() end,
114 dirty = function() return sock:dirty() end 114 dirty = function() return sock:dirty() end
115 }, { 115 }, {
116 __call = function() 116 __call = function()
117 if done then return nil end 117 if done then return nil end
118 local chunk, err, partial = sock:receive(socket.BLOCKSIZE) 118 local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
119 if not err then return chunk 119 if not err then return chunk
120 elseif err == "closed" then 120 elseif err == "closed" then
121 sock:close() 121 sock:close()
122 done = 1 122 done = 1
123 return partial 123 return partial
124 else return nil, err end 124 else return nil, err end
125 end 125 end
126 }) 126 })
127end 127end
diff --git a/src/tp.lua b/src/tp.lua
index 984bd67..c6d60c8 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -37,7 +37,7 @@ local function get_reply(c)
37 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) 37 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
38 reply = reply .. "\n" .. line 38 reply = reply .. "\n" .. line
39 -- reply ends with same code 39 -- reply ends with same code
40 until code == current and sep == " " 40 until code == current and sep == " "
41 end 41 end
42 return code, reply 42 return code, reply
43end 43end
@@ -49,25 +49,25 @@ function metat.__index:check(ok)
49 local code, reply = get_reply(self.c) 49 local code, reply = get_reply(self.c)
50 if not code then return nil, reply end 50 if not code then return nil, reply end
51 if base.type(ok) ~= "function" then 51 if base.type(ok) ~= "function" then
52 if base.type(ok) == "table" then 52 if base.type(ok) == "table" then
53 for i, v in base.ipairs(ok) do 53 for i, v in base.ipairs(ok) do
54 if string.find(code, v) then 54 if string.find(code, v) then
55 return base.tonumber(code), reply 55 return base.tonumber(code), reply
56 end 56 end
57 end 57 end
58 return nil, reply 58 return nil, reply
59 else 59 else
60 if string.find(code, ok) then return base.tonumber(code), reply 60 if string.find(code, ok) then return base.tonumber(code), reply
61 else return nil, reply end 61 else return nil, reply end
62 end 62 end
63 else return ok(base.tonumber(code), reply) end 63 else return ok(base.tonumber(code), reply) end
64end 64end
65 65
66function metat.__index:command(cmd, arg) 66function metat.__index:command(cmd, arg)
67 if arg then 67 if arg then
68 return self.c:send(cmd .. " " .. arg.. "\r\n") 68 return self.c:send(cmd .. " " .. arg.. "\r\n")
69 else 69 else
70 return self.c:send(cmd .. "\r\n") 70 return self.c:send(cmd .. "\r\n")
71 end 71 end
72end 72end
73 73
@@ -114,8 +114,8 @@ function connect(host, port, create, timeout)
114 if not c then return nil, e end 114 if not c then return nil, e end
115 c:settimeout(timeout or TIMEOUT) 115 c:settimeout(timeout or TIMEOUT)
116 local r, e = c:connect(host, port) 116 local r, e = c:connect(host, port)
117 if not r then 117 if not r then
118 c:close() 118 c:close()
119 return nil, e 119 return nil, e
120 end 120 end
121 return base.setmetatable({c = c}, metat) 121 return base.setmetatable({c = c}, metat)
diff --git a/src/url.lua b/src/url.lua
index 135d723..c700f90 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -20,7 +20,7 @@ _VERSION = "URL 1.0"
20 20
21----------------------------------------------------------------------------- 21-----------------------------------------------------------------------------
22-- Encodes a string into its escaped hexadecimal representation 22-- Encodes a string into its escaped hexadecimal representation
23-- Input 23-- Input
24-- s: binary string to be encoded 24-- s: binary string to be encoded
25-- Returns 25-- Returns
26-- escaped representation of string binary 26-- escaped representation of string binary
@@ -33,8 +33,8 @@ end
33 33
34----------------------------------------------------------------------------- 34-----------------------------------------------------------------------------
35-- Protects a path segment, to prevent it from interfering with the 35-- Protects a path segment, to prevent it from interfering with the
36-- url parsing. 36-- url parsing.
37-- Input 37-- Input
38-- s: binary string to be encoded 38-- s: binary string to be encoded
39-- Returns 39-- Returns
40-- escaped representation of string binary 40-- escaped representation of string binary
@@ -50,12 +50,12 @@ end
50-- these are allowed withing a path segment, along with alphanum 50-- these are allowed withing a path segment, along with alphanum
51-- other characters must be escaped 51-- other characters must be escaped
52local segment_set = make_set { 52local segment_set = make_set {
53 "-", "_", ".", "!", "~", "*", "'", "(", 53 "-", "_", ".", "!", "~", "*", "'", "(",
54 ")", ":", "@", "&", "=", "+", "$", ",", 54 ")", ":", "@", "&", "=", "+", "$", ",",
55} 55}
56 56
57local function protect_segment(s) 57local function protect_segment(s)
58 return string.gsub(s, "([^A-Za-z0-9_])", function (c) 58 return string.gsub(s, "([^A-Za-z0-9_])", function (c)
59 if segment_set[c] then return c 59 if segment_set[c] then return c
60 else return string.format("%%%02x", string.byte(c)) end 60 else return string.format("%%%02x", string.byte(c)) end
61 end) 61 end)
@@ -63,7 +63,7 @@ end
63 63
64----------------------------------------------------------------------------- 64-----------------------------------------------------------------------------
65-- Encodes a string into its escaped hexadecimal representation 65-- Encodes a string into its escaped hexadecimal representation
66-- Input 66-- Input
67-- s: binary string to be encoded 67-- s: binary string to be encoded
68-- Returns 68-- Returns
69-- escaped representation of string binary 69-- escaped representation of string binary
@@ -86,11 +86,11 @@ local function absolute_path(base_path, relative_path)
86 if string.sub(relative_path, 1, 1) == "/" then return relative_path end 86 if string.sub(relative_path, 1, 1) == "/" then return relative_path end
87 local path = string.gsub(base_path, "[^/]*$", "") 87 local path = string.gsub(base_path, "[^/]*$", "")
88 path = path .. relative_path 88 path = path .. relative_path
89 path = string.gsub(path, "([^/]*%./)", function (s) 89 path = string.gsub(path, "([^/]*%./)", function (s)
90 if s ~= "./" then return s else return "" end 90 if s ~= "./" then return s else return "" end
91 end) 91 end)
92 path = string.gsub(path, "/%.$", "/") 92 path = string.gsub(path, "/%.$", "/")
93 local reduced 93 local reduced
94 while reduced ~= path do 94 while reduced ~= path do
95 reduced = path 95 reduced = path
96 path = string.gsub(reduced, "([^/]*/%.%./)", function (s) 96 path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
@@ -116,7 +116,7 @@ end
116-- Returns 116-- Returns
117-- table with the following fields, where RFC naming conventions have 117-- table with the following fields, where RFC naming conventions have
118-- been preserved: 118-- been preserved:
119-- scheme, authority, userinfo, user, password, host, port, 119-- scheme, authority, userinfo, user, password, host, port,
120-- path, params, query, fragment 120-- path, params, query, fragment
121-- Obs: 121-- Obs:
122-- the leading '/' in {/<path>} is considered part of <path> 122-- the leading '/' in {/<path>} is considered part of <path>
@@ -130,26 +130,26 @@ function parse(url, default)
130 -- remove whitespace 130 -- remove whitespace
131 -- url = string.gsub(url, "%s", "") 131 -- url = string.gsub(url, "%s", "")
132 -- get fragment 132 -- get fragment
133 url = string.gsub(url, "#(.*)$", function(f) 133 url = string.gsub(url, "#(.*)$", function(f)
134 parsed.fragment = f 134 parsed.fragment = f
135 return "" 135 return ""
136 end) 136 end)
137 -- get scheme 137 -- get scheme
138 url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", 138 url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
139 function(s) parsed.scheme = s; return "" end) 139 function(s) parsed.scheme = s; return "" end)
140 -- get authority 140 -- get authority
141 url = string.gsub(url, "^//([^/]*)", function(n) 141 url = string.gsub(url, "^//([^/]*)", function(n)
142 parsed.authority = n 142 parsed.authority = n
143 return "" 143 return ""
144 end) 144 end)
145 -- get query stringing 145 -- get query stringing
146 url = string.gsub(url, "%?(.*)", function(q) 146 url = string.gsub(url, "%?(.*)", function(q)
147 parsed.query = q 147 parsed.query = q
148 return "" 148 return ""
149 end) 149 end)
150 -- get params 150 -- get params
151 url = string.gsub(url, "%;(.*)", function(p) 151 url = string.gsub(url, "%;(.*)", function(p)
152 parsed.params = p 152 parsed.params = p
153 return "" 153 return ""
154 end) 154 end)
155 -- path is whatever was left 155 -- path is whatever was left
@@ -158,14 +158,14 @@ function parse(url, default)
158 if not authority then return parsed end 158 if not authority then return parsed end
159 authority = string.gsub(authority,"^([^@]*)@", 159 authority = string.gsub(authority,"^([^@]*)@",
160 function(u) parsed.userinfo = u; return "" end) 160 function(u) parsed.userinfo = u; return "" end)
161 authority = string.gsub(authority, ":([^:]*)$", 161 authority = string.gsub(authority, ":([^:]*)$",
162 function(p) parsed.port = p; return "" end) 162 function(p) parsed.port = p; return "" end)
163 if authority ~= "" then parsed.host = authority end 163 if authority ~= "" then parsed.host = authority end
164 local userinfo = parsed.userinfo 164 local userinfo = parsed.userinfo
165 if not userinfo then return parsed end 165 if not userinfo then return parsed end
166 userinfo = string.gsub(userinfo, ":([^:]*)$", 166 userinfo = string.gsub(userinfo, ":([^:]*)$",
167 function(p) parsed.password = p; return "" end) 167 function(p) parsed.password = p; return "" end)
168 parsed.user = userinfo 168 parsed.user = userinfo
169 return parsed 169 return parsed
170end 170end
171 171
@@ -189,8 +189,8 @@ function build(parsed)
189 local userinfo = parsed.userinfo 189 local userinfo = parsed.userinfo
190 if parsed.user then 190 if parsed.user then
191 userinfo = parsed.user 191 userinfo = parsed.user
192 if parsed.password then 192 if parsed.password then
193 userinfo = userinfo .. ":" .. parsed.password 193 userinfo = userinfo .. ":" .. parsed.password
194 end 194 end
195 end 195 end
196 if userinfo then authority = userinfo .. "@" .. authority end 196 if userinfo then authority = userinfo .. "@" .. authority end
@@ -233,8 +233,8 @@ function absolute(base_url, relative_url)
233 relative_parsed.query = base_parsed.query 233 relative_parsed.query = base_parsed.query
234 end 234 end
235 end 235 end
236 else 236 else
237 relative_parsed.path = absolute_path(base_parsed.path or "", 237 relative_parsed.path = absolute_path(base_parsed.path or "",
238 relative_parsed.path) 238 relative_parsed.path)
239 end 239 end
240 end 240 end
diff --git a/src/usocket.c b/src/usocket.c
index 6a0b178..e70806a 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -110,7 +110,8 @@ int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
110 double t = timeout_getretry(tm); 110 double t = timeout_getretry(tm);
111 tv.tv_sec = (int) t; 111 tv.tv_sec = (int) t;
112 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); 112 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
113 ret = select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL); 113 /* timeout = 0 means no wait */
114 ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL);
114 } while (ret < 0 && errno == EINTR); 115 } while (ret < 0 && errno == EINTR);
115 return ret; 116 return ret;
116} 117}