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 |
