aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-03-22 04:15:03 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-03-22 04:15:03 +0000
commit1fa65d89ca5dc64756f7933d7cc3f524e4627dce (patch)
treedf614c8b86b0f7c2f45c2afcacc993ab3c0dcf11 /src
parent4919a83d2271a9e43b83c7d488e3f94c850681e3 (diff)
downloadluasocket-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.lua41
-rw-r--r--src/ltn12.lua13
-rw-r--r--src/smtp.lua43
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
40end 40end
41 41
42local function shift(a, b, c, d) 42local function receive_headers(reqt, respt)
43 return c, d 43 local headers = {}
44end 44 local sock = respt.tmp.sock
45 45 local line, name, value, _
46-- resquest_p forward declaration 46 -- store results
47local request_p 47 respt.headers = headers
48
49local 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
104end 104end
105 105
106local function receive_body_bylength(sock, length, sink) 106local 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))
246end 246end
247 247
248function adjust_headers(reqt, respt) 248local 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
262end 262end
263 263
264function parse_url(reqt, respt) 264local 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
281end 281end
282 282
283-- forward declaration
284local request_p
285
283local function should_authorize(reqt, respt) 286local 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
288end 293end
289 294
290local function clone(headers) 295local 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
339end 344end
340 345
346-- execute a request of through an exception
341function request_p(reqt, respt) 347function 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
24function filter.cycle(low, ctx, extra) 24function 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
33local function chain2(f1, f2) 34local 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
40function filter.chain(...) 43function 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
76function source.simplify(src) 80function 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
99function source.rewind(src) 104function 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
113function source.chain(src, f) 119function 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
159function sink.simplify(snk) 167function 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
197function sink.chain(f, snk) 206function 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
211function pump(src, snk) 222function 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)
21ZONE = "-0000" 21ZONE = "-0000"
22 22
23function stuff()
24 return ltn12.filter.cycle(dot, 2)
25end
26
27local function shift(a, b, c) 23local function shift(a, b, c)
28 return b, c 24 return b, c
29end 25end
30 26
27-- high level stuffing filter
28function stuff()
29 return ltn12.filter.cycle(dot, 2)
30end
31
31-- send message or throw an exception 32-- send message or throw an exception
32function psend(control, mailt) 33local 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)
62end 63end
63 64
64-- sendmessage forward declaration 65-- send_message forward declaration
65local sendmessage 66local send_message
66 67
67-- yield multipart message body from a multipart message table 68-- yield multipart message body from a multipart message table
68local function sendmultipart(mesgt) 69local 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)
84end 85end
85 86
86-- yield message body from a source 87-- yield message body from a source
87local function sendsource(mesgt) 88local 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)
101end 102end
102 103
103-- yield message body from a string 104-- yield message body from a string
104local function sendstring(mesgt) 105local 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)
114end 115end
115 116
116-- yield the headers one by one 117-- yield the headers one by one
117local function sendheaders(mesgt) 118local 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)
123end 124end
124 125
125-- message source 126-- message source
126function sendmessage(mesgt) 127function 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
131end 132end
132 133
133-- set defaul headers 134-- set defaul headers
134local function adjustheaders(mesgt) 135local 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)
140end 141end
141 142
142function message(mesgt) 143function 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
147end 148end
148 149
149function send(mailt) 150function 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