diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-03-22 04:15:03 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-03-22 04:15:03 +0000 |
commit | 1fa65d89ca5dc64756f7933d7cc3f524e4627dce (patch) | |
tree | df614c8b86b0f7c2f45c2afcacc993ab3c0dcf11 /src | |
parent | 4919a83d2271a9e43b83c7d488e3f94c850681e3 (diff) | |
download | luasocket-1fa65d89ca5dc64756f7933d7cc3f524e4627dce.tar.gz luasocket-1fa65d89ca5dc64756f7933d7cc3f524e4627dce.tar.bz2 luasocket-1fa65d89ca5dc64756f7933d7cc3f524e4627dce.zip |
Adjusted some details, got rid of old files, added some new.
Diffstat (limited to 'src')
-rw-r--r-- | src/http.lua | 41 | ||||
-rw-r--r-- | src/ltn12.lua | 13 | ||||
-rw-r--r-- | src/smtp.lua | 43 |
3 files changed, 58 insertions, 39 deletions
diff --git a/src/http.lua b/src/http.lua index a10cf50..ab166e3 100644 --- a/src/http.lua +++ b/src/http.lua | |||
@@ -2,7 +2,7 @@ | |||
2 | -- HTTP/1.1 client support for the Lua language. | 2 | -- HTTP/1.1 client support for the Lua language. |
3 | -- LuaSocket toolkit. | 3 | -- LuaSocket toolkit. |
4 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
5 | -- Conforming to: RFC 2616, LTN7 | 5 | -- Conforming to RFC 2616 |
6 | -- RCS ID: $Id$ | 6 | -- RCS ID: $Id$ |
7 | ----------------------------------------------------------------------------- | 7 | ----------------------------------------------------------------------------- |
8 | -- make sure LuaSocket is loaded | 8 | -- make sure LuaSocket is loaded |
@@ -39,21 +39,18 @@ local function third(a, b, c) | |||
39 | return c | 39 | return c |
40 | end | 40 | end |
41 | 41 | ||
42 | local function shift(a, b, c, d) | 42 | local function receive_headers(reqt, respt) |
43 | return c, d | 43 | local headers = {} |
44 | end | 44 | local sock = respt.tmp.sock |
45 | 45 | local line, name, value, _ | |
46 | -- resquest_p forward declaration | 46 | -- store results |
47 | local request_p | 47 | respt.headers = headers |
48 | |||
49 | local function receive_headers(sock, headers) | ||
50 | local line, name, value | ||
51 | -- get first line | 48 | -- get first line |
52 | line = socket.try(sock:receive()) | 49 | line = socket.try(sock:receive()) |
53 | -- headers go until a blank line is found | 50 | -- headers go until a blank line is found |
54 | while line ~= "" do | 51 | while line ~= "" do |
55 | -- get field-name and value | 52 | -- get field-name and value |
56 | name, value = shift(string.find(line, "^(.-):%s*(.*)")) | 53 | _, _, name, value = string.find(line, "^(.-):%s*(.*)") |
57 | assert(name and value, "malformed reponse headers") | 54 | assert(name and value, "malformed reponse headers") |
58 | name = string.lower(name) | 55 | name = string.lower(name) |
59 | -- get next line (value might be folded) | 56 | -- get next line (value might be folded) |
@@ -100,7 +97,10 @@ local function receive_body_bychunks(sock, sink) | |||
100 | -- let callback know we are done | 97 | -- let callback know we are done |
101 | hand(sink, nil) | 98 | hand(sink, nil) |
102 | -- servers shouldn't send trailer headers, but who trusts them? | 99 | -- servers shouldn't send trailer headers, but who trusts them? |
103 | receive_headers(sock, {}) | 100 | local line = socket.try(sock:receive()) |
101 | while line ~= "" do | ||
102 | line = socket.try(sock:receive()) | ||
103 | end | ||
104 | end | 104 | end |
105 | 105 | ||
106 | local function receive_body_bylength(sock, length, sink) | 106 | local function receive_body_bylength(sock, length, sink) |
@@ -245,7 +245,7 @@ local function open(reqt, respt) | |||
245 | socket.try(sock:connect(host, port)) | 245 | socket.try(sock:connect(host, port)) |
246 | end | 246 | end |
247 | 247 | ||
248 | function adjust_headers(reqt, respt) | 248 | local function adjust_headers(reqt, respt) |
249 | local lower = {} | 249 | local lower = {} |
250 | local headers = reqt.headers or {} | 250 | local headers = reqt.headers or {} |
251 | -- set default headers | 251 | -- set default headers |
@@ -261,7 +261,7 @@ function adjust_headers(reqt, respt) | |||
261 | respt.tmp.headers = lower | 261 | respt.tmp.headers = lower |
262 | end | 262 | end |
263 | 263 | ||
264 | function parse_url(reqt, respt) | 264 | local function parse_url(reqt, respt) |
265 | -- parse url with default fields | 265 | -- parse url with default fields |
266 | local parsed = socket.url.parse(reqt.url, { | 266 | local parsed = socket.url.parse(reqt.url, { |
267 | host = "", | 267 | host = "", |
@@ -280,11 +280,16 @@ function parse_url(reqt, respt) | |||
280 | respt.tmp.parsed = parsed | 280 | respt.tmp.parsed = parsed |
281 | end | 281 | end |
282 | 282 | ||
283 | -- forward declaration | ||
284 | local request_p | ||
285 | |||
283 | local function should_authorize(reqt, respt) | 286 | local function should_authorize(reqt, respt) |
284 | -- if there has been an authorization attempt, it must have failed | 287 | -- if there has been an authorization attempt, it must have failed |
285 | if reqt.headers and reqt.headers["authorization"] then return nil end | 288 | if reqt.headers and reqt.headers["authorization"] then return nil end |
286 | -- if we don't have authorization information, we can't retry | 289 | -- if last attempt didn't fail due to lack of authentication, |
287 | return respt.tmp.parsed.user and respt.tmp.parsed.password | 290 | -- or we don't have authorization information, we can't retry |
291 | return respt.code == 401 and | ||
292 | respt.tmp.parsed.user and respt.tmp.parsed.password | ||
288 | end | 293 | end |
289 | 294 | ||
290 | local function clone(headers) | 295 | local function clone(headers) |
@@ -338,14 +343,14 @@ local function redirect(reqt, respt) | |||
338 | if respt.headers then respt.headers.location = redirt.url end | 343 | if respt.headers then respt.headers.location = redirt.url end |
339 | end | 344 | end |
340 | 345 | ||
346 | -- execute a request of through an exception | ||
341 | function request_p(reqt, respt) | 347 | function request_p(reqt, respt) |
342 | parse_url(reqt, respt) | 348 | parse_url(reqt, respt) |
343 | adjust_headers(reqt, respt) | 349 | adjust_headers(reqt, respt) |
344 | open(reqt, respt) | 350 | open(reqt, respt) |
345 | send_request(reqt, respt) | 351 | send_request(reqt, respt) |
346 | receive_status(reqt, respt) | 352 | receive_status(reqt, respt) |
347 | respt.headers = {} | 353 | receive_headers(reqt, respt) |
348 | receive_headers(respt.tmp.sock, respt.headers) | ||
349 | if should_redirect(reqt, respt) then | 354 | if should_redirect(reqt, respt) then |
350 | respt.tmp.sock:close() | 355 | respt.tmp.sock:close() |
351 | redirect(reqt, respt) | 356 | redirect(reqt, respt) |
diff --git a/src/ltn12.lua b/src/ltn12.lua index dc49d80..ed3449b 100644 --- a/src/ltn12.lua +++ b/src/ltn12.lua | |||
@@ -22,6 +22,7 @@ end | |||
22 | 22 | ||
23 | -- returns a high level filter that cycles a cycles a low-level filter | 23 | -- returns a high level filter that cycles a cycles a low-level filter |
24 | function filter.cycle(low, ctx, extra) | 24 | function filter.cycle(low, ctx, extra) |
25 | if type(low) ~= 'function' then error('invalid low-level filter', 2) end | ||
25 | return function(chunk) | 26 | return function(chunk) |
26 | local ret | 27 | local ret |
27 | ret, ctx = low(ctx, chunk, extra) | 28 | ret, ctx = low(ctx, chunk, extra) |
@@ -31,6 +32,8 @@ end | |||
31 | 32 | ||
32 | -- chains two filters together | 33 | -- chains two filters together |
33 | local function chain2(f1, f2) | 34 | local function chain2(f1, f2) |
35 | if type(f1) ~= 'function' then error('invalid filter', 2) end | ||
36 | if type(f2) ~= 'function' then error('invalid filter', 2) end | ||
34 | return function(chunk) | 37 | return function(chunk) |
35 | return f2(f1(chunk)) | 38 | return f2(f1(chunk)) |
36 | end | 39 | end |
@@ -40,6 +43,7 @@ end | |||
40 | function filter.chain(...) | 43 | function filter.chain(...) |
41 | local f = arg[1] | 44 | local f = arg[1] |
42 | for i = 2, table.getn(arg) do | 45 | for i = 2, table.getn(arg) do |
46 | if type(arg[i]) ~= 'function' then error('invalid filter', 2) end | ||
43 | f = chain2(f, arg[i]) | 47 | f = chain2(f, arg[i]) |
44 | end | 48 | end |
45 | return f | 49 | return f |
@@ -74,6 +78,7 @@ end | |||
74 | 78 | ||
75 | -- turns a fancy source into a simple source | 79 | -- turns a fancy source into a simple source |
76 | function source.simplify(src) | 80 | function source.simplify(src) |
81 | if type(src) ~= 'function' then error('invalid source', 2) end | ||
77 | return function() | 82 | return function() |
78 | local chunk, err_or_new = src() | 83 | local chunk, err_or_new = src() |
79 | src = err_or_new or src | 84 | src = err_or_new or src |
@@ -97,6 +102,7 @@ end | |||
97 | 102 | ||
98 | -- creates rewindable source | 103 | -- creates rewindable source |
99 | function source.rewind(src) | 104 | function source.rewind(src) |
105 | if type(src) ~= 'function' then error('invalid source', 2) end | ||
100 | local t = {} | 106 | local t = {} |
101 | return function(chunk) | 107 | return function(chunk) |
102 | if not chunk then | 108 | if not chunk then |
@@ -111,6 +117,8 @@ end | |||
111 | 117 | ||
112 | -- chains a source with a filter | 118 | -- chains a source with a filter |
113 | function source.chain(src, f) | 119 | function source.chain(src, f) |
120 | if type(src) ~= 'function' then error('invalid source', 2) end | ||
121 | if type(f) ~= 'function' then error('invalid filter', 2) end | ||
114 | local co = coroutine.create(function() | 122 | local co = coroutine.create(function() |
115 | while true do | 123 | while true do |
116 | local chunk, err = src() | 124 | local chunk, err = src() |
@@ -157,6 +165,7 @@ end | |||
157 | 165 | ||
158 | -- turns a fancy sink into a simple sink | 166 | -- turns a fancy sink into a simple sink |
159 | function sink.simplify(snk) | 167 | function sink.simplify(snk) |
168 | if type(snk) ~= 'function' then error('invalid sink', 2) end | ||
160 | return function(chunk, err) | 169 | return function(chunk, err) |
161 | local ret, err_or_new = snk(chunk, err) | 170 | local ret, err_or_new = snk(chunk, err) |
162 | if not ret then return nil, err_or_new end | 171 | if not ret then return nil, err_or_new end |
@@ -195,6 +204,8 @@ end | |||
195 | 204 | ||
196 | -- chains a sink with a filter | 205 | -- chains a sink with a filter |
197 | function sink.chain(f, snk) | 206 | function sink.chain(f, snk) |
207 | if type(snk) ~= 'function' then error('invalid sink', 2) end | ||
208 | if type(f) ~= 'function' then error('invalid filter', 2) end | ||
198 | return function(chunk, err) | 209 | return function(chunk, err) |
199 | local filtered = f(chunk) | 210 | local filtered = f(chunk) |
200 | local done = chunk and "" | 211 | local done = chunk and "" |
@@ -209,6 +220,8 @@ end | |||
209 | 220 | ||
210 | -- pumps all data from a source to a sink | 221 | -- pumps all data from a source to a sink |
211 | function pump(src, snk) | 222 | function pump(src, snk) |
223 | if type(src) ~= 'function' then error('invalid source', 2) end | ||
224 | if type(snk) ~= 'function' then error('invalid sink', 2) end | ||
212 | while true do | 225 | while true do |
213 | local chunk, src_err = src() | 226 | local chunk, src_err = src() |
214 | local ret, snk_err = snk(chunk, src_err) | 227 | local ret, snk_err = snk(chunk, src_err) |
diff --git a/src/smtp.lua b/src/smtp.lua index c823c97..ed8bd15 100644 --- a/src/smtp.lua +++ b/src/smtp.lua | |||
@@ -20,16 +20,17 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost" | |||
20 | -- default time zone (means we don't know) | 20 | -- default time zone (means we don't know) |
21 | ZONE = "-0000" | 21 | ZONE = "-0000" |
22 | 22 | ||
23 | function stuff() | ||
24 | return ltn12.filter.cycle(dot, 2) | ||
25 | end | ||
26 | |||
27 | local function shift(a, b, c) | 23 | local function shift(a, b, c) |
28 | return b, c | 24 | return b, c |
29 | end | 25 | end |
30 | 26 | ||
27 | -- high level stuffing filter | ||
28 | function stuff() | ||
29 | return ltn12.filter.cycle(dot, 2) | ||
30 | end | ||
31 | |||
31 | -- send message or throw an exception | 32 | -- send message or throw an exception |
32 | function psend(control, mailt) | 33 | local function send_p(control, mailt) |
33 | socket.try(control:check("2..")) | 34 | socket.try(control:check("2..")) |
34 | socket.try(control:command("EHLO", mailt.domain or DOMAIN)) | 35 | socket.try(control:command("EHLO", mailt.domain or DOMAIN)) |
35 | socket.try(control:check("2..")) | 36 | socket.try(control:check("2..")) |
@@ -61,11 +62,11 @@ local function newboundary() | |||
61 | math.random(0, 99999), seqno) | 62 | math.random(0, 99999), seqno) |
62 | end | 63 | end |
63 | 64 | ||
64 | -- sendmessage forward declaration | 65 | -- send_message forward declaration |
65 | local sendmessage | 66 | local send_message |
66 | 67 | ||
67 | -- yield multipart message body from a multipart message table | 68 | -- yield multipart message body from a multipart message table |
68 | local function sendmultipart(mesgt) | 69 | local function send_multipart(mesgt) |
69 | local bd = newboundary() | 70 | local bd = newboundary() |
70 | -- define boundary and finish headers | 71 | -- define boundary and finish headers |
71 | coroutine.yield('content-type: multipart/mixed; boundary="' .. | 72 | coroutine.yield('content-type: multipart/mixed; boundary="' .. |
@@ -75,7 +76,7 @@ local function sendmultipart(mesgt) | |||
75 | -- send each part separated by a boundary | 76 | -- send each part separated by a boundary |
76 | for i, m in ipairs(mesgt.body) do | 77 | for i, m in ipairs(mesgt.body) do |
77 | coroutine.yield("\r\n--" .. bd .. "\r\n") | 78 | coroutine.yield("\r\n--" .. bd .. "\r\n") |
78 | sendmessage(m) | 79 | send_message(m) |
79 | end | 80 | end |
80 | -- send last boundary | 81 | -- send last boundary |
81 | coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") | 82 | coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") |
@@ -84,7 +85,7 @@ local function sendmultipart(mesgt) | |||
84 | end | 85 | end |
85 | 86 | ||
86 | -- yield message body from a source | 87 | -- yield message body from a source |
87 | local function sendsource(mesgt) | 88 | local function send_source(mesgt) |
88 | -- set content-type if user didn't override | 89 | -- set content-type if user didn't override |
89 | if not mesgt.headers or not mesgt.headers["content-type"] then | 90 | if not mesgt.headers or not mesgt.headers["content-type"] then |
90 | coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n') | 91 | coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n') |
@@ -101,7 +102,7 @@ local function sendsource(mesgt) | |||
101 | end | 102 | end |
102 | 103 | ||
103 | -- yield message body from a string | 104 | -- yield message body from a string |
104 | local function sendstring(mesgt) | 105 | local function send_string(mesgt) |
105 | -- set content-type if user didn't override | 106 | -- set content-type if user didn't override |
106 | if not mesgt.headers or not mesgt.headers["content-type"] then | 107 | if not mesgt.headers or not mesgt.headers["content-type"] then |
107 | coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n') | 108 | coroutine.yield('content-type: text/plain; charset="iso-8859-1"\r\n') |
@@ -114,7 +115,7 @@ local function sendstring(mesgt) | |||
114 | end | 115 | end |
115 | 116 | ||
116 | -- yield the headers one by one | 117 | -- yield the headers one by one |
117 | local function sendheaders(mesgt) | 118 | local function send_headers(mesgt) |
118 | if mesgt.headers then | 119 | if mesgt.headers then |
119 | for i,v in pairs(mesgt.headers) do | 120 | for i,v in pairs(mesgt.headers) do |
120 | coroutine.yield(i .. ':' .. v .. "\r\n") | 121 | coroutine.yield(i .. ':' .. v .. "\r\n") |
@@ -123,15 +124,15 @@ local function sendheaders(mesgt) | |||
123 | end | 124 | end |
124 | 125 | ||
125 | -- message source | 126 | -- message source |
126 | function sendmessage(mesgt) | 127 | function send_message(mesgt) |
127 | sendheaders(mesgt) | 128 | send_headers(mesgt) |
128 | if type(mesgt.body) == "table" then sendmultipart(mesgt) | 129 | if type(mesgt.body) == "table" then send_multipart(mesgt) |
129 | elseif type(mesgt.body) == "function" then sendsource(mesgt) | 130 | elseif type(mesgt.body) == "function" then send_source(mesgt) |
130 | else sendstring(mesgt) end | 131 | else send_string(mesgt) end |
131 | end | 132 | end |
132 | 133 | ||
133 | -- set defaul headers | 134 | -- set defaul headers |
134 | local function adjustheaders(mesgt) | 135 | local function adjust_headers(mesgt) |
135 | mesgt.headers = mesgt.headers or {} | 136 | mesgt.headers = mesgt.headers or {} |
136 | mesgt.headers["mime-version"] = "1.0" | 137 | mesgt.headers["mime-version"] = "1.0" |
137 | mesgt.headers["date"] = mesgt.headers["date"] or | 138 | mesgt.headers["date"] = mesgt.headers["date"] or |
@@ -140,16 +141,16 @@ local function adjustheaders(mesgt) | |||
140 | end | 141 | end |
141 | 142 | ||
142 | function message(mesgt) | 143 | function message(mesgt) |
143 | adjustheaders(mesgt) | 144 | adjust_headers(mesgt) |
144 | -- create and return message source | 145 | -- create and return message source |
145 | local co = coroutine.create(function() sendmessage(mesgt) end) | 146 | local co = coroutine.create(function() send_message(mesgt) end) |
146 | return function() return shift(coroutine.resume(co)) end | 147 | return function() return shift(coroutine.resume(co)) end |
147 | end | 148 | end |
148 | 149 | ||
149 | function send(mailt) | 150 | function send(mailt) |
150 | local c, e = socket.tp.connect(mailt.server or SERVER, mailt.port or PORT) | 151 | local c, e = socket.tp.connect(mailt.server or SERVER, mailt.port or PORT) |
151 | if not c then return nil, e end | 152 | if not c then return nil, e end |
152 | local s, e = pcall(psend, c, mailt) | 153 | local s, e = pcall(send_p, c, mailt) |
153 | c:close() | 154 | c:close() |
154 | if s then return true | 155 | if s then return true |
155 | else return nil, e end | 156 | else return nil, e end |