aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2002-07-08 21:01:45 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2002-07-08 21:01:45 +0000
commit5b2a124305f26d36e95b639b1c70a32368f03261 (patch)
tree6b34fb2c047b2b88cea89b2b3aa87f546fef726d
parent60e7bf48b077377c11022f34e24bbbfb596397bf (diff)
downloadluasocket-5b2a124305f26d36e95b639b1c70a32368f03261.tar.gz
luasocket-5b2a124305f26d36e95b639b1c70a32368f03261.tar.bz2
luasocket-5b2a124305f26d36e95b639b1c70a32368f03261.zip
Updated for Lua 4.1-w3.
-rw-r--r--src/ftp.lua117
-rw-r--r--src/smtp.lua64
-rw-r--r--src/url.lua36
3 files changed, 105 insertions, 112 deletions
diff --git a/src/ftp.lua b/src/ftp.lua
index 1af4d30..1fa48f7 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- FTP support for the Lua language 2-- FTP support for the Lua language
3-- LuaSocket 1.4 toolkit. 3-- LuaSocket 1.5 toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Date: 26/12/2000 5-- Date: 26/12/2000
6-- Conforming to: RFC 959, LTN7 6-- Conforming to: RFC 959, LTN7
@@ -24,13 +24,6 @@ Public.EMAIL = "anonymous@anonymous.org"
24Public.BLOCKSIZE = 8192 24Public.BLOCKSIZE = 8192
25 25
26----------------------------------------------------------------------------- 26-----------------------------------------------------------------------------
27-- Required libraries
28-----------------------------------------------------------------------------
29dofile "concat.lua"
30dofile "url.lua"
31dofile "code.lua"
32
33-----------------------------------------------------------------------------
34-- Tries to send DOS mode lines. Closes socket on error. 27-- Tries to send DOS mode lines. Closes socket on error.
35-- Input 28-- Input
36-- sock: server socket 29-- sock: server socket
@@ -91,7 +84,7 @@ function Private.send_command(control, cmd, arg)
91 local line 84 local line
92 if arg then line = cmd .. " " .. arg 85 if arg then line = cmd .. " " .. arg
93 else line = cmd end 86 else line = cmd end
94 return %Private.try_sendline(control, line) 87 return Private.try_sendline(control, line)
95end 88end
96 89
97----------------------------------------------------------------------------- 90-----------------------------------------------------------------------------
@@ -104,14 +97,14 @@ end
104----------------------------------------------------------------------------- 97-----------------------------------------------------------------------------
105function Private.get_answer(control) 98function Private.get_answer(control)
106 local code, lastcode, sep, _ 99 local code, lastcode, sep, _
107 local line, err = %Private.try_receive(control) 100 local line, err = Private.try_receive(control)
108 local answer = line 101 local answer = line
109 if err then return nil, err end 102 if err then return nil, err end
110 _,_, code, sep = strfind(line, "^(%d%d%d)(.)") 103 _,_, code, sep = strfind(line, "^(%d%d%d)(.)")
111 if not code or not sep then return nil, answer end 104 if not code or not sep then return nil, answer end
112 if sep == "-" then -- answer is multiline 105 if sep == "-" then -- answer is multiline
113 repeat 106 repeat
114 line, err = %Private.try_receive(control) 107 line, err = Private.try_receive(control)
115 if err then return nil, err end 108 if err then return nil, err end
116 _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)") 109 _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)")
117 answer = answer .. "\n" .. line 110 answer = answer .. "\n" .. line
@@ -130,7 +123,7 @@ end
130-- answer: server complete answer or system error message 123-- answer: server complete answer or system error message
131----------------------------------------------------------------------------- 124-----------------------------------------------------------------------------
132function Private.check_answer(control, success) 125function Private.check_answer(control, success)
133 local answer, code = %Private.get_answer(control) 126 local answer, code = Private.get_answer(control)
134 if not answer then return nil, code end 127 if not answer then return nil, code end
135 if type(success) ~= "table" then success = {success} end 128 if type(success) ~= "table" then success = {success} end
136 for i = 1, getn(success) do 129 for i = 1, getn(success) do
@@ -155,9 +148,9 @@ end
155-- answer: server complete answer or system error message 148-- answer: server complete answer or system error message
156----------------------------------------------------------------------------- 149-----------------------------------------------------------------------------
157function Private.command(control, cmd, arg, success) 150function Private.command(control, cmd, arg, success)
158 local err = %Private.send_command(control, cmd, arg) 151 local err = Private.send_command(control, cmd, arg)
159 if err then return nil, err end 152 if err then return nil, err end
160 return %Private.check_answer(control, success) 153 return Private.check_answer(control, success)
161end 154end
162 155
163----------------------------------------------------------------------------- 156-----------------------------------------------------------------------------
@@ -169,9 +162,9 @@ end
169-- answer: server answer or error message 162-- answer: server answer or error message
170----------------------------------------------------------------------------- 163-----------------------------------------------------------------------------
171function Private.greet(control) 164function Private.greet(control)
172 local code, answer = %Private.check_answer(control, {120, 220}) 165 local code, answer = Private.check_answer(control, {120, 220})
173 if code == 120 then -- please try again, somewhat busy now... 166 if code == 120 then -- please try again, somewhat busy now...
174 return %Private.check_answer(control, {220}) 167 return Private.check_answer(control, {220})
175 end 168 end
176 return code, answer 169 return code, answer
177end 170end
@@ -187,9 +180,9 @@ end
187-- answer: server answer or error message 180-- answer: server answer or error message
188----------------------------------------------------------------------------- 181-----------------------------------------------------------------------------
189function Private.login(control, user, password) 182function Private.login(control, user, password)
190 local code, answer = %Private.command(control, "user", user, {230, 331}) 183 local code, answer = Private.command(control, "user", user, {230, 331})
191 if code == 331 and password then -- need pass and we have pass 184 if code == 331 and password then -- need pass and we have pass
192 return %Private.command(control, "pass", password, {230, 202}) 185 return Private.command(control, "pass", password, {230, 202})
193 end 186 end
194 return code, answer 187 return code, answer
195end 188end
@@ -204,7 +197,7 @@ end
204-- answer: server answer or error message 197-- answer: server answer or error message
205----------------------------------------------------------------------------- 198-----------------------------------------------------------------------------
206function Private.cwd(control, path) 199function Private.cwd(control, path)
207 if path then return %Private.command(control, "cwd", path, {250}) 200 if path then return Private.command(control, "cwd", path, {250})
208 else return 250, nil end 201 else return 250, nil end
209end 202end
210 203
@@ -221,13 +214,13 @@ function Private.port(control)
221 local server, ctl_ip 214 local server, ctl_ip
222 ctl_ip, answer = control:getsockname() 215 ctl_ip, answer = control:getsockname()
223 server, answer = bind(ctl_ip, 0) 216 server, answer = bind(ctl_ip, 0)
224 server:timeout(%Public.TIMEOUT) 217 server:timeout(Public.TIMEOUT)
225 local ip, p, ph, pl 218 local ip, p, ph, pl
226 ip, p = server:getsockname() 219 ip, p = server:getsockname()
227 pl = mod(p, 256) 220 pl = mod(p, 256)
228 ph = (p - pl)/256 221 ph = (p - pl)/256
229 local arg = gsub(format("%s,%d,%d", ip, ph, pl), "%.", ",") 222 local arg = gsub(format("%s,%d,%d", ip, ph, pl), "%.", ",")
230 code, answer = %Private.command(control, "port", arg, {200}) 223 code, answer = Private.command(control, "port", arg, {200})
231 if not code then 224 if not code then
232 server:close() 225 server:close()
233 return nil, answer 226 return nil, answer
@@ -243,7 +236,7 @@ end
243-- answer: server answer or error message 236-- answer: server answer or error message
244----------------------------------------------------------------------------- 237-----------------------------------------------------------------------------
245function Private.logout(control) 238function Private.logout(control)
246 local code, answer = %Private.command(control, "quit", nil, {221}) 239 local code, answer = Private.command(control, "quit", nil, {221})
247 if code then control:close() end 240 if code then control:close() end
248 return code, answer 241 return code, answer
249end 242end
@@ -259,7 +252,7 @@ end
259function Private.receive_indirect(data, callback) 252function Private.receive_indirect(data, callback)
260 local chunk, err, res 253 local chunk, err, res
261 while not err do 254 while not err do
262 chunk, err = %Private.try_receive(data, %Public.BLOCKSIZE) 255 chunk, err = Private.try_receive(data, Public.BLOCKSIZE)
263 if err == "closed" then err = "done" end 256 if err == "closed" then err = "done" end
264 res = callback(chunk, err) 257 res = callback(chunk, err)
265 if not res then break end 258 if not res then break end
@@ -282,11 +275,11 @@ function Private.retrieve(control, server, name, is_directory, content_cb)
282 local data 275 local data
283 -- ask server for file or directory listing accordingly 276 -- ask server for file or directory listing accordingly
284 if is_directory then 277 if is_directory then
285 code, answer = %Private.cwd(control, name) 278 code, answer = Private.cwd(control, name)
286 if not code then return answer end 279 if not code then return answer end
287 code, answer = %Private.command(control, "nlst", nil, {150, 125}) 280 code, answer = Private.command(control, "nlst", nil, {150, 125})
288 else 281 else
289 code, answer = %Private.command(control, "retr", name, {150, 125}) 282 code, answer = Private.command(control, "retr", name, {150, 125})
290 end 283 end
291 if not code then return nil, answer end 284 if not code then return nil, answer end
292 data, answer = server:accept() 285 data, answer = server:accept()
@@ -295,14 +288,14 @@ function Private.retrieve(control, server, name, is_directory, content_cb)
295 control:close() 288 control:close()
296 return answer 289 return answer
297 end 290 end
298 answer = %Private.receive_indirect(data, content_cb) 291 answer = Private.receive_indirect(data, content_cb)
299 if answer then 292 if answer then
300 control:close() 293 control:close()
301 return answer 294 return answer
302 end 295 end
303 data:close() 296 data:close()
304 -- make sure file transfered ok 297 -- make sure file transfered ok
305 return %Private.check_answer(control, {226, 250}) 298 return Private.check_answer(control, {226, 250})
306end 299end
307 300
308----------------------------------------------------------------------------- 301-----------------------------------------------------------------------------
@@ -347,7 +340,7 @@ end
347----------------------------------------------------------------------------- 340-----------------------------------------------------------------------------
348function Private.store(control, server, file, send_cb) 341function Private.store(control, server, file, send_cb)
349 local data, err 342 local data, err
350 local code, answer = %Private.command(control, "stor", file, {150, 125}) 343 local code, answer = Private.command(control, "stor", file, {150, 125})
351 if not code then 344 if not code then
352 control:close() 345 control:close()
353 return nil, answer 346 return nil, answer
@@ -360,7 +353,7 @@ function Private.store(control, server, file, send_cb)
360 return nil, answer 353 return nil, answer
361 end 354 end
362 -- send whole file 355 -- send whole file
363 err = %Private.send_indirect(data, send_cb, send_cb()) 356 err = Private.send_indirect(data, send_cb, send_cb())
364 if err then 357 if err then
365 control:close() 358 control:close()
366 return nil, err 359 return nil, err
@@ -368,7 +361,7 @@ function Private.store(control, server, file, send_cb)
368 -- close connection to inform that file transmission is complete 361 -- close connection to inform that file transmission is complete
369 data:close() 362 data:close()
370 -- check if file was received correctly 363 -- check if file was received correctly
371 return %Private.check_answer(control, {226, 250}) 364 return Private.check_answer(control, {226, 250})
372end 365end
373 366
374----------------------------------------------------------------------------- 367-----------------------------------------------------------------------------
@@ -383,7 +376,7 @@ function Private.change_type(control, params)
383 local type, _ 376 local type, _
384 _, _, type = strfind(params or "", "type=(.)") 377 _, _, type = strfind(params or "", "type=(.)")
385 if type == "a" or type == "i" then 378 if type == "a" or type == "i" then
386 local code, err = %Private.command(control, "type", type, {200}) 379 local code, err = Private.command(control, "type", type, {200})
387 if not code then return err end 380 if not code then return err end
388 end 381 end
389end 382end
@@ -401,12 +394,12 @@ function Private.open(parsed)
401 local control, err = connect(parsed.host, parsed.port) 394 local control, err = connect(parsed.host, parsed.port)
402 if not control then return nil, err end 395 if not control then return nil, err end
403 -- make sure we don't block forever 396 -- make sure we don't block forever
404 control:timeout(%Public.TIMEOUT) 397 control:timeout(Public.TIMEOUT)
405 -- check greeting 398 -- check greeting
406 local code, answer = %Private.greet(control) 399 local code, answer = Private.greet(control)
407 if not code then return nil, answer end 400 if not code then return nil, answer end
408 -- try to log in 401 -- try to log in
409 code, err = %Private.login(control, parsed.user, parsed.password) 402 code, err = Private.login(control, parsed.user, parsed.password)
410 if not code then return nil, err 403 if not code then return nil, err
411 else return control end 404 else return control end
412end 405end
@@ -418,7 +411,7 @@ end
418----------------------------------------------------------------------------- 411-----------------------------------------------------------------------------
419function Private.close(control) 412function Private.close(control)
420 -- disconnect 413 -- disconnect
421 %Private.logout(control) 414 Private.logout(control)
422end 415end
423 416
424----------------------------------------------------------------------------- 417-----------------------------------------------------------------------------
@@ -432,7 +425,7 @@ end
432function Private.change_dir(control, segment) 425function Private.change_dir(control, segment)
433 local n = getn(segment) 426 local n = getn(segment)
434 for i = 1, n-1 do 427 for i = 1, n-1 do
435 local code, answer = %Private.cwd(control, segment[i]) 428 local code, answer = Private.cwd(control, segment[i])
436 if not code then return answer end 429 if not code then return answer end
437 end 430 end
438end 431end
@@ -457,10 +450,10 @@ function Private.upload(control, request, segment)
457 end 450 end
458 content_cb = request.content_cb 451 content_cb = request.content_cb
459 -- setup passive connection 452 -- setup passive connection
460 local server, answer = %Private.port(control) 453 local server, answer = Private.port(control)
461 if not server then return answer end 454 if not server then return answer end
462 -- ask server to receive file 455 -- ask server to receive file
463 code, answer = %Private.store(control, server, name, content_cb) 456 code, answer = Private.store(control, server, name, content_cb)
464 if not code then return answer end 457 if not code then return answer end
465end 458end
466 459
@@ -485,10 +478,10 @@ function Private.download(control, request, segment)
485 return "Invalid file path" 478 return "Invalid file path"
486 end 479 end
487 -- setup passive connection 480 -- setup passive connection
488 local server, answer = %Private.port(control) 481 local server, answer = Private.port(control)
489 if not server then return answer end 482 if not server then return answer end
490 -- ask server to send file or directory listing 483 -- ask server to send file or directory listing
491 code, answer = %Private.retrieve(control, server, name, 484 code, answer = Private.retrieve(control, server, name,
492 is_directory, content_cb) 485 is_directory, content_cb)
493 if not code then return answer end 486 if not code then return answer end
494end 487end
@@ -510,7 +503,7 @@ function Private.parse_url(request)
510 user = "anonymous", 503 user = "anonymous",
511 port = 21, 504 port = 21,
512 path = "/", 505 path = "/",
513 password = %Public.EMAIL, 506 password = Public.EMAIL,
514 scheme = "ftp" 507 scheme = "ftp"
515 }) 508 })
516 -- explicit login information overrides that given by URL 509 -- explicit login information overrides that given by URL
@@ -565,17 +558,17 @@ end
565-- err: error message if any 558-- err: error message if any
566----------------------------------------------------------------------------- 559-----------------------------------------------------------------------------
567function Public.get_cb(request) 560function Public.get_cb(request)
568 local parsed = %Private.parse_url(request) 561 local parsed = Private.parse_url(request)
569 if parsed.scheme ~= "ftp" then 562 if parsed.scheme ~= "ftp" then
570 return format("unknown scheme '%s'", parsed.scheme) 563 return format("unknown scheme '%s'", parsed.scheme)
571 end 564 end
572 local control, err = %Private.open(parsed) 565 local control, err = Private.open(parsed)
573 if not control then return err end 566 if not control then return err end
574 local segment = %Private.parse_path(parsed) 567 local segment = Private.parse_path(parsed)
575 return %Private.change_dir(control, segment) or 568 return Private.change_dir(control, segment) or
576 %Private.change_type(control, parsed.params) or 569 Private.change_type(control, parsed.params) or
577 %Private.download(control, request, segment) or 570 Private.download(control, request, segment) or
578 %Private.close(control) 571 Private.close(control)
579end 572end
580 573
581----------------------------------------------------------------------------- 574-----------------------------------------------------------------------------
@@ -591,17 +584,17 @@ end
591-- err: error message if any 584-- err: error message if any
592----------------------------------------------------------------------------- 585-----------------------------------------------------------------------------
593function Public.put_cb(request) 586function Public.put_cb(request)
594 local parsed = %Private.parse_url(request) 587 local parsed = Private.parse_url(request)
595 if parsed.scheme ~= "ftp" then 588 if parsed.scheme ~= "ftp" then
596 return format("unknown scheme '%s'", parsed.scheme) 589 return format("unknown scheme '%s'", parsed.scheme)
597 end 590 end
598 local control, err = %Private.open(parsed) 591 local control, err = Private.open(parsed)
599 if not control then return err end 592 if not control then return err end
600 local segment = %Private.parse_path(parsed) 593 local segment = Private.parse_path(parsed)
601 return %Private.change_dir(control, segment) or 594 return Private.change_dir(control, segment) or
602 %Private.change_type(control, parsed.params) or 595 Private.change_type(control, parsed.params) or
603 %Private.upload(control, request, segment) or 596 Private.upload(control, request, segment) or
604 %Private.close(control) 597 Private.close(control)
605end 598end
606 599
607----------------------------------------------------------------------------- 600-----------------------------------------------------------------------------
@@ -617,11 +610,11 @@ end
617-- err: error message if any 610-- err: error message if any
618----------------------------------------------------------------------------- 611-----------------------------------------------------------------------------
619function Public.put(url_or_request, content) 612function Public.put(url_or_request, content)
620 local request = %Private.build_request(url_or_request) 613 local request = Private.build_request(url_or_request)
621 request.content_cb = function() 614 request.content_cb = function()
622 return %content, strlen(%content) 615 return content, strlen(content)
623 end 616 end
624 return %Public.put_cb(request) 617 return Public.put_cb(request)
625end 618end
626 619
627----------------------------------------------------------------------------- 620-----------------------------------------------------------------------------
@@ -638,11 +631,11 @@ end
638----------------------------------------------------------------------------- 631-----------------------------------------------------------------------------
639function Public.get(url_or_request) 632function Public.get(url_or_request)
640 local cat = Concat.create() 633 local cat = Concat.create()
641 local request = %Private.build_request(url_or_request) 634 local request = Private.build_request(url_or_request)
642 request.content_cb = function(chunk, err) 635 request.content_cb = function(chunk, err)
643 if chunk then %cat:addstring(chunk) end 636 if chunk then cat:addstring(chunk) end
644 return 1 637 return 1
645 end 638 end
646 local err = %Public.get_cb(request) 639 local err = Public.get_cb(request)
647 return cat:getresult(), err 640 return cat:getresult(), err
648end 641end
diff --git a/src/smtp.lua b/src/smtp.lua
index 7450792..72a0e5a 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- SMTP support for the Lua language. 2-- SMTP support for the Lua language.
3-- LuaSocket 1.4 toolkit 3-- LuaSocket 1.5 toolkit
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Date: 26/12/2000 5-- Date: 26/12/2000
6-- Conforming to: RFC 821, LTN7 6-- Conforming to: RFC 821, LTN7
@@ -65,7 +65,7 @@ function Private.send_command(sock, command, param)
65 local line 65 local line
66 if param then line = command .. " " .. param .. "\r\n" 66 if param then line = command .. " " .. param .. "\r\n"
67 else line = command .. "\r\n" end 67 else line = command .. "\r\n" end
68 return %Private.try_send(sock, line) 68 return Private.try_send(sock, line)
69end 69end
70 70
71----------------------------------------------------------------------------- 71-----------------------------------------------------------------------------
@@ -78,14 +78,14 @@ end
78----------------------------------------------------------------------------- 78-----------------------------------------------------------------------------
79function Private.get_answer(control) 79function Private.get_answer(control)
80 local code, lastcode, sep, _ 80 local code, lastcode, sep, _
81 local line, err = %Private.try_receive(control) 81 local line, err = Private.try_receive(control)
82 local answer = line 82 local answer = line
83 if err then return nil, err end 83 if err then return nil, err end
84 _,_, code, sep = strfind(line, "^(%d%d%d)(.)") 84 _,_, code, sep = strfind(line, "^(%d%d%d)(.)")
85 if not code or not sep then return nil, answer end 85 if not code or not sep then return nil, answer end
86 if sep == "-" then -- answer is multiline 86 if sep == "-" then -- answer is multiline
87 repeat 87 repeat
88 line, err = %Private.try_receive(control) 88 line, err = Private.try_receive(control)
89 if err then return nil, err end 89 if err then return nil, err end
90 _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)") 90 _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)")
91 answer = answer .. "\n" .. line 91 answer = answer .. "\n" .. line
@@ -105,7 +105,7 @@ end
105-- answer: complete server answer or system error message 105-- answer: complete server answer or system error message
106----------------------------------------------------------------------------- 106-----------------------------------------------------------------------------
107function Private.check_answer(control, success) 107function Private.check_answer(control, success)
108 local answer, code = %Private.get_answer(control) 108 local answer, code = Private.get_answer(control)
109 if not answer then return nil, code end 109 if not answer then return nil, code end
110 if type(success) ~= "table" then success = {success} end 110 if type(success) ~= "table" then success = {success} end
111 for i = 1, getn(success) do 111 for i = 1, getn(success) do
@@ -126,9 +126,9 @@ end
126-- answer: complete server reply 126-- answer: complete server reply
127----------------------------------------------------------------------------- 127-----------------------------------------------------------------------------
128function Private.send_helo(sock) 128function Private.send_helo(sock)
129 local err = %Private.send_command(sock, "HELO", %Public.DOMAIN) 129 local err = Private.send_command(sock, "HELO", Public.DOMAIN)
130 if err then return nil, err end 130 if err then return nil, err end
131 return %Private.check_answer(sock, 250) 131 return Private.check_answer(sock, 250)
132end 132end
133 133
134----------------------------------------------------------------------------- 134-----------------------------------------------------------------------------
@@ -140,9 +140,9 @@ end
140-- answer: complete server reply or error message 140-- answer: complete server reply or error message
141----------------------------------------------------------------------------- 141-----------------------------------------------------------------------------
142function Private.send_quit(sock) 142function Private.send_quit(sock)
143 local err = %Private.send_command(sock, "QUIT") 143 local err = Private.send_command(sock, "QUIT")
144 if err then return nil, err end 144 if err then return nil, err end
145 local code, answer = %Private.check_answer(sock, 221) 145 local code, answer = Private.check_answer(sock, 221)
146 sock:close() 146 sock:close()
147 return code, answer 147 return code, answer
148end 148end
@@ -158,9 +158,9 @@ end
158----------------------------------------------------------------------------- 158-----------------------------------------------------------------------------
159function Private.send_mail(sock, sender) 159function Private.send_mail(sock, sender)
160 local param = format("FROM:<%s>", sender or "") 160 local param = format("FROM:<%s>", sender or "")
161 local err = %Private.send_command(sock, "MAIL", param) 161 local err = Private.send_command(sock, "MAIL", param)
162 if err then return nil, err end 162 if err then return nil, err end
163 return %Private.check_answer(sock, 250) 163 return Private.check_answer(sock, 250)
164end 164end
165 165
166----------------------------------------------------------------------------- 166-----------------------------------------------------------------------------
@@ -175,11 +175,11 @@ function Private.send_headers(sock, headers)
175 local err 175 local err
176 -- send request headers 176 -- send request headers
177 for i, v in headers or {} do 177 for i, v in headers or {} do
178 err = %Private.try_send(sock, i .. ": " .. v .. "\r\n") 178 err = Private.try_send(sock, i .. ": " .. v .. "\r\n")
179 if err then return err end 179 if err then return err end
180 end 180 end
181 -- mark end of request headers 181 -- mark end of request headers
182 return %Private.try_send(sock, "\r\n") 182 return Private.try_send(sock, "\r\n")
183end 183end
184 184
185----------------------------------------------------------------------------- 185-----------------------------------------------------------------------------
@@ -193,18 +193,18 @@ end
193-- answer: complete server reply or error message 193-- answer: complete server reply or error message
194----------------------------------------------------------------------------- 194-----------------------------------------------------------------------------
195function Private.send_data(sock, headers, body) 195function Private.send_data(sock, headers, body)
196 local err = %Private.send_command(sock, "DATA") 196 local err = Private.send_command(sock, "DATA")
197 if err then return nil, err end 197 if err then return nil, err end
198 local code, answer = %Private.check_answer(sock, 354) 198 local code, answer = Private.check_answer(sock, 354)
199 if not code then return nil, answer end 199 if not code then return nil, answer end
200 -- avoid premature end in message body 200 -- avoid premature end in message body
201 body = gsub(body or "", "\n%.", "\n%.%.") 201 body = gsub(body or "", "\n%.", "\n%.%.")
202 -- mark end of message body 202 -- mark end of message body
203 body = body .. "\r\n.\r\n" 203 body = body .. "\r\n.\r\n"
204 err = %Private.send_headers(sock, headers) 204 err = Private.send_headers(sock, headers)
205 if err then return nil, err end 205 if err then return nil, err end
206 err = %Private.try_send(sock, body) 206 err = Private.try_send(sock, body)
207 return %Private.check_answer(sock, 250) 207 return Private.check_answer(sock, 250)
208end 208end
209 209
210----------------------------------------------------------------------------- 210-----------------------------------------------------------------------------
@@ -221,9 +221,9 @@ function Private.send_rcpt(sock, rcpt)
221 local code, answer = nil, "No recipient specified" 221 local code, answer = nil, "No recipient specified"
222 if type(rcpt) ~= "table" then rcpt = {rcpt} end 222 if type(rcpt) ~= "table" then rcpt = {rcpt} end
223 for i = 1, getn(rcpt) do 223 for i = 1, getn(rcpt) do
224 err = %Private.send_command(sock, "RCPT", format("TO:<%s>", rcpt[i])) 224 err = Private.send_command(sock, "RCPT", format("TO:<%s>", rcpt[i]))
225 if err then return nil, err end 225 if err then return nil, err end
226 code, answer = %Private.check_answer(sock, {250, 251}) 226 code, answer = Private.check_answer(sock, {250, 251})
227 if not code then return code, answer end 227 if not code then return code, answer end
228 end 228 end
229 return code, answer 229 return code, answer
@@ -240,16 +240,16 @@ end
240function Private.open(server) 240function Private.open(server)
241 local code, answer 241 local code, answer
242 -- default server 242 -- default server
243 server = server or %Public.SERVER 243 server = server or Public.SERVER
244 -- connect to server and make sure we won't hang 244 -- connect to server and make sure we won't hang
245 local sock, err = connect(server, %Public.PORT) 245 local sock, err = connect(server, Public.PORT)
246 if not sock then return nil, err end 246 if not sock then return nil, err end
247 sock:timeout(%Public.TIMEOUT) 247 sock:timeout(Public.TIMEOUT)
248 -- initial server greeting 248 -- initial server greeting
249 code, answer = %Private.check_answer(sock, 220) 249 code, answer = Private.check_answer(sock, 220)
250 if not code then return nil, answer end 250 if not code then return nil, answer end
251 -- HELO 251 -- HELO
252 code, answer = %Private.send_helo(sock) 252 code, answer = Private.send_helo(sock)
253 if not code then return nil, answer end 253 if not code then return nil, answer end
254 return sock 254 return sock
255end 255end
@@ -270,13 +270,13 @@ end
270function Private.send(sock, message) 270function Private.send(sock, message)
271 local code, answer 271 local code, answer
272 -- MAIL 272 -- MAIL
273 code, answer = %Private.send_mail(sock, message.from) 273 code, answer = Private.send_mail(sock, message.from)
274 if not code then return nil, answer end 274 if not code then return nil, answer end
275 -- RCPT 275 -- RCPT
276 code, answer = %Private.send_rcpt(sock, message.rcpt) 276 code, answer = Private.send_rcpt(sock, message.rcpt)
277 if not code then return nil, answer end 277 if not code then return nil, answer end
278 -- DATA 278 -- DATA
279 return %Private.send_data(sock, message.headers, message.body) 279 return Private.send_data(sock, message.headers, message.body)
280end 280end
281 281
282----------------------------------------------------------------------------- 282-----------------------------------------------------------------------------
@@ -289,7 +289,7 @@ end
289----------------------------------------------------------------------------- 289-----------------------------------------------------------------------------
290function Private.close(sock) 290function Private.close(sock)
291 -- QUIT 291 -- QUIT
292 return %Private.send_quit(sock) 292 return Private.send_quit(sock)
293end 293end
294 294
295----------------------------------------------------------------------------- 295-----------------------------------------------------------------------------
@@ -305,11 +305,11 @@ end
305-- nil if successfull, error message in case of error 305-- nil if successfull, error message in case of error
306----------------------------------------------------------------------------- 306-----------------------------------------------------------------------------
307function Public.mail(message) 307function Public.mail(message)
308 local sock, err = %Private.open(message.server) 308 local sock, err = Private.open(message.server)
309 if not sock then return err end 309 if not sock then return err end
310 local code, answer = %Private.send(sock, message) 310 local code, answer = Private.send(sock, message)
311 if not code then return answer end 311 if not code then return answer end
312 code, answer = %Private.close(sock) 312 code, answer = Private.close(sock)
313 if code then return nil end 313 if code then return nil end
314 return answer 314 return answer
315end 315end
diff --git a/src/url.lua b/src/url.lua
index 673c9ac..e17bcf5 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- URI parsing, composition and relative URL resolution 2-- URI parsing, composition and relative URL resolution
3-- LuaSocket 1.4 toolkit. 3-- LuaSocket 1.5 toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Date: 20/7/2001 5-- Date: 20/7/2001
6-- Conforming to: RFC 2396, LTN7 6-- Conforming to: RFC 2396, LTN7
@@ -36,24 +36,24 @@ function Public.parse_url(url, default)
36 -- remove whitespace 36 -- remove whitespace
37 url = gsub(url, "%s", "") 37 url = gsub(url, "%s", "")
38 -- get fragment 38 -- get fragment
39 url = gsub(url, "#(.*)$", function(f) %parsed.fragment = f end) 39 url = gsub(url, "#(.*)$", function(f) parsed.fragment = f end)
40 -- get scheme 40 -- get scheme
41 url = gsub(url, "^([%w][%w%+%-%.]*)%:", function(s) %parsed.scheme = s end) 41 url = gsub(url, "^([%w][%w%+%-%.]*)%:", function(s) parsed.scheme = s end)
42 -- get authority 42 -- get authority
43 url = gsub(url, "^//([^/]*)", function(n) %parsed.authority = n end) 43 url = gsub(url, "^//([^/]*)", function(n) parsed.authority = n end)
44 -- get query string 44 -- get query string
45 url = gsub(url, "%?(.*)", function(q) %parsed.query = q end) 45 url = gsub(url, "%?(.*)", function(q) parsed.query = q end)
46 -- get params 46 -- get params
47 url = gsub(url, "%;(.*)", function(p) %parsed.params = p end) 47 url = gsub(url, "%;(.*)", function(p) parsed.params = p end)
48 if url ~= "" then parsed.path = url end 48 if url ~= "" then parsed.path = url end
49 local authority = parsed.authority 49 local authority = parsed.authority
50 if not authority then return parsed end 50 if not authority then return parsed end
51 authority = gsub(authority,"^([^@]*)@",function(u) %parsed.userinfo = u end) 51 authority = gsub(authority,"^([^@]*)@",function(u) parsed.userinfo = u end)
52 authority = gsub(authority, ":([^:]*)$", function(p) %parsed.port = p end) 52 authority = gsub(authority, ":([^:]*)$", function(p) parsed.port = p end)
53 if authority ~= "" then parsed.host = authority end 53 if authority ~= "" then parsed.host = authority end
54 local userinfo = parsed.userinfo 54 local userinfo = parsed.userinfo
55 if not userinfo then return parsed end 55 if not userinfo then return parsed end
56 userinfo = gsub(userinfo, ":([^:]*)$", function(p) %parsed.password = p end) 56 userinfo = gsub(userinfo, ":([^:]*)$", function(p) parsed.password = p end)
57 parsed.user = userinfo 57 parsed.user = userinfo
58 return parsed 58 return parsed
59end 59end
@@ -99,8 +99,8 @@ end
99-- corresponding absolute url 99-- corresponding absolute url
100----------------------------------------------------------------------------- 100-----------------------------------------------------------------------------
101function Public.absolute_url(base_url, relative_url) 101function Public.absolute_url(base_url, relative_url)
102 local base = %Public.parse_url(base_url) 102 local base = Public.parse_url(base_url)
103 local relative = %Public.parse_url(relative_url) 103 local relative = Public.parse_url(relative_url)
104 if not base then return relative_url 104 if not base then return relative_url
105 elseif not relative then return base_url 105 elseif not relative then return base_url
106 elseif relative.scheme then return relative_url 106 elseif relative.scheme then return relative_url
@@ -117,10 +117,10 @@ function Public.absolute_url(base_url, relative_url)
117 end 117 end
118 end 118 end
119 else 119 else
120 relative.path = %Private.absolute_path(base.path,relative.path) 120 relative.path = Private.absolute_path(base.path,relative.path)
121 end 121 end
122 end 122 end
123 return %Public.build_url(relative) 123 return Public.build_url(relative)
124 end 124 end
125end 125end
126 126
@@ -135,7 +135,7 @@ function Public.parse_path(path)
135 local parsed = {} 135 local parsed = {}
136 path = path or "" 136 path = path or ""
137 path = gsub(path, "%s", "") 137 path = gsub(path, "%s", "")
138 gsub(path, "([^/]+)", function (s) tinsert(%parsed, s) end) 138 gsub(path, "([^/]+)", function (s) tinsert(parsed, s) end)
139 for i = 1, getn(parsed) do 139 for i = 1, getn(parsed) do
140 parsed[i] = Code.unescape(parsed[i]) 140 parsed[i] = Code.unescape(parsed[i])
141 end 141 end
@@ -166,11 +166,11 @@ function Public.build_path(parsed, unsafe)
166 end 166 end
167 else 167 else
168 for i = 1, n-1 do 168 for i = 1, n-1 do
169 path = path .. %Private.protect_segment(parsed[i]) 169 path = path .. Private.protect_segment(parsed[i])
170 path = path .. "/" 170 path = path .. "/"
171 end 171 end
172 if n > 0 then 172 if n > 0 then
173 path = path .. %Private.protect_segment(parsed[n]) 173 path = path .. Private.protect_segment(parsed[n])
174 if parsed.is_directory then path = path .. "/" end 174 if parsed.is_directory then path = path .. "/" end
175 end 175 end
176 end 176 end
@@ -194,9 +194,9 @@ Private.segment_set = Private.make_set {
194} 194}
195 195
196function Private.protect_segment(s) 196function Private.protect_segment(s)
197 local segment_set = %Private.segment_set 197 local segment_set = Private.segment_set
198 return gsub(s, "(%W)", function (c) 198 return gsub(s, "(%W)", function (c)
199 if %segment_set[c] then return c 199 if segment_set[c] then return c
200 else return Code.escape(c) end 200 else return Code.escape(c) end
201 end) 201 end)
202end 202end