diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2002-07-08 21:01:45 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2002-07-08 21:01:45 +0000 |
| commit | 5b2a124305f26d36e95b639b1c70a32368f03261 (patch) | |
| tree | 6b34fb2c047b2b88cea89b2b3aa87f546fef726d /src | |
| parent | 60e7bf48b077377c11022f34e24bbbfb596397bf (diff) | |
| download | luasocket-5b2a124305f26d36e95b639b1c70a32368f03261.tar.gz luasocket-5b2a124305f26d36e95b639b1c70a32368f03261.tar.bz2 luasocket-5b2a124305f26d36e95b639b1c70a32368f03261.zip | |
Updated for Lua 4.1-w3.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftp.lua | 117 | ||||
| -rw-r--r-- | src/smtp.lua | 64 | ||||
| -rw-r--r-- | src/url.lua | 36 |
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" | |||
| 24 | Public.BLOCKSIZE = 8192 | 24 | Public.BLOCKSIZE = 8192 |
| 25 | 25 | ||
| 26 | ----------------------------------------------------------------------------- | 26 | ----------------------------------------------------------------------------- |
| 27 | -- Required libraries | ||
| 28 | ----------------------------------------------------------------------------- | ||
| 29 | dofile "concat.lua" | ||
| 30 | dofile "url.lua" | ||
| 31 | dofile "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) |
| 95 | end | 88 | end |
| 96 | 89 | ||
| 97 | ----------------------------------------------------------------------------- | 90 | ----------------------------------------------------------------------------- |
| @@ -104,14 +97,14 @@ end | |||
| 104 | ----------------------------------------------------------------------------- | 97 | ----------------------------------------------------------------------------- |
| 105 | function Private.get_answer(control) | 98 | function 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 | ----------------------------------------------------------------------------- |
| 132 | function Private.check_answer(control, success) | 125 | function 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 | ----------------------------------------------------------------------------- |
| 157 | function Private.command(control, cmd, arg, success) | 150 | function 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) |
| 161 | end | 154 | end |
| 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 | ----------------------------------------------------------------------------- |
| 171 | function Private.greet(control) | 164 | function 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 |
| 177 | end | 170 | end |
| @@ -187,9 +180,9 @@ end | |||
| 187 | -- answer: server answer or error message | 180 | -- answer: server answer or error message |
| 188 | ----------------------------------------------------------------------------- | 181 | ----------------------------------------------------------------------------- |
| 189 | function Private.login(control, user, password) | 182 | function 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 |
| 195 | end | 188 | end |
| @@ -204,7 +197,7 @@ end | |||
| 204 | -- answer: server answer or error message | 197 | -- answer: server answer or error message |
| 205 | ----------------------------------------------------------------------------- | 198 | ----------------------------------------------------------------------------- |
| 206 | function Private.cwd(control, path) | 199 | function 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 |
| 209 | end | 202 | end |
| 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 | ----------------------------------------------------------------------------- |
| 245 | function Private.logout(control) | 238 | function 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 |
| 249 | end | 242 | end |
| @@ -259,7 +252,7 @@ end | |||
| 259 | function Private.receive_indirect(data, callback) | 252 | function 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}) |
| 306 | end | 299 | end |
| 307 | 300 | ||
| 308 | ----------------------------------------------------------------------------- | 301 | ----------------------------------------------------------------------------- |
| @@ -347,7 +340,7 @@ end | |||
| 347 | ----------------------------------------------------------------------------- | 340 | ----------------------------------------------------------------------------- |
| 348 | function Private.store(control, server, file, send_cb) | 341 | function 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}) |
| 372 | end | 365 | end |
| 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 |
| 389 | end | 382 | end |
| @@ -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 |
| 412 | end | 405 | end |
| @@ -418,7 +411,7 @@ end | |||
| 418 | ----------------------------------------------------------------------------- | 411 | ----------------------------------------------------------------------------- |
| 419 | function Private.close(control) | 412 | function Private.close(control) |
| 420 | -- disconnect | 413 | -- disconnect |
| 421 | %Private.logout(control) | 414 | Private.logout(control) |
| 422 | end | 415 | end |
| 423 | 416 | ||
| 424 | ----------------------------------------------------------------------------- | 417 | ----------------------------------------------------------------------------- |
| @@ -432,7 +425,7 @@ end | |||
| 432 | function Private.change_dir(control, segment) | 425 | function 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 |
| 438 | end | 431 | end |
| @@ -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 |
| 465 | end | 458 | end |
| 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 |
| 494 | end | 487 | end |
| @@ -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 | ----------------------------------------------------------------------------- |
| 567 | function Public.get_cb(request) | 560 | function 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) |
| 579 | end | 572 | end |
| 580 | 573 | ||
| 581 | ----------------------------------------------------------------------------- | 574 | ----------------------------------------------------------------------------- |
| @@ -591,17 +584,17 @@ end | |||
| 591 | -- err: error message if any | 584 | -- err: error message if any |
| 592 | ----------------------------------------------------------------------------- | 585 | ----------------------------------------------------------------------------- |
| 593 | function Public.put_cb(request) | 586 | function 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) |
| 605 | end | 598 | end |
| 606 | 599 | ||
| 607 | ----------------------------------------------------------------------------- | 600 | ----------------------------------------------------------------------------- |
| @@ -617,11 +610,11 @@ end | |||
| 617 | -- err: error message if any | 610 | -- err: error message if any |
| 618 | ----------------------------------------------------------------------------- | 611 | ----------------------------------------------------------------------------- |
| 619 | function Public.put(url_or_request, content) | 612 | function 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) |
| 625 | end | 618 | end |
| 626 | 619 | ||
| 627 | ----------------------------------------------------------------------------- | 620 | ----------------------------------------------------------------------------- |
| @@ -638,11 +631,11 @@ end | |||
| 638 | ----------------------------------------------------------------------------- | 631 | ----------------------------------------------------------------------------- |
| 639 | function Public.get(url_or_request) | 632 | function 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 |
| 648 | end | 641 | end |
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) |
| 69 | end | 69 | end |
| 70 | 70 | ||
| 71 | ----------------------------------------------------------------------------- | 71 | ----------------------------------------------------------------------------- |
| @@ -78,14 +78,14 @@ end | |||
| 78 | ----------------------------------------------------------------------------- | 78 | ----------------------------------------------------------------------------- |
| 79 | function Private.get_answer(control) | 79 | function 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 | ----------------------------------------------------------------------------- |
| 107 | function Private.check_answer(control, success) | 107 | function 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 | ----------------------------------------------------------------------------- |
| 128 | function Private.send_helo(sock) | 128 | function 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) |
| 132 | end | 132 | end |
| 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 | ----------------------------------------------------------------------------- |
| 142 | function Private.send_quit(sock) | 142 | function 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 |
| 148 | end | 148 | end |
| @@ -158,9 +158,9 @@ end | |||
| 158 | ----------------------------------------------------------------------------- | 158 | ----------------------------------------------------------------------------- |
| 159 | function Private.send_mail(sock, sender) | 159 | function 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) |
| 164 | end | 164 | end |
| 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") |
| 183 | end | 183 | end |
| 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 | ----------------------------------------------------------------------------- |
| 195 | function Private.send_data(sock, headers, body) | 195 | function 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) |
| 208 | end | 208 | end |
| 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 | |||
| 240 | function Private.open(server) | 240 | function 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 |
| 255 | end | 255 | end |
| @@ -270,13 +270,13 @@ end | |||
| 270 | function Private.send(sock, message) | 270 | function Private.send(sock, message) |
| 271 | local code, answer | 271 | local code, answer |
| 272 | 272 | ||
| 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) |
| 280 | end | 280 | end |
| 281 | 281 | ||
| 282 | ----------------------------------------------------------------------------- | 282 | ----------------------------------------------------------------------------- |
| @@ -289,7 +289,7 @@ end | |||
| 289 | ----------------------------------------------------------------------------- | 289 | ----------------------------------------------------------------------------- |
| 290 | function Private.close(sock) | 290 | function Private.close(sock) |
| 291 | -- QUIT | 291 | -- QUIT |
| 292 | return %Private.send_quit(sock) | 292 | return Private.send_quit(sock) |
| 293 | end | 293 | end |
| 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 | ----------------------------------------------------------------------------- |
| 307 | function Public.mail(message) | 307 | function 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 |
| 315 | end | 315 | end |
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 |
| 59 | end | 59 | end |
| @@ -99,8 +99,8 @@ end | |||
| 99 | -- corresponding absolute url | 99 | -- corresponding absolute url |
| 100 | ----------------------------------------------------------------------------- | 100 | ----------------------------------------------------------------------------- |
| 101 | function Public.absolute_url(base_url, relative_url) | 101 | function 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 |
| 125 | end | 125 | end |
| 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 | ||
| 196 | function Private.protect_segment(s) | 196 | function 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) |
| 202 | end | 202 | end |
