diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2011-05-25 20:57:22 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2011-05-25 20:57:22 +0000 |
| commit | 3a8ba90dfb0c2eb224f317dd692ede426691e72a (patch) | |
| tree | fe1cc5379a2e0e031663fe9c15d908653844bc73 | |
| parent | bce60be30fe8e9c1b0eb33128c23c93d7bca5303 (diff) | |
| download | luasocket-3a8ba90dfb0c2eb224f317dd692ede426691e72a.tar.gz luasocket-3a8ba90dfb0c2eb224f317dd692ede426691e72a.tar.bz2 luasocket-3a8ba90dfb0c2eb224f317dd692ede426691e72a.zip | |
Saving before big changes to support IPv6.
| -rw-r--r-- | FIX | 11 | ||||
| -rw-r--r-- | NEW | 46 | ||||
| -rw-r--r-- | doc/ftp.html | 6 | ||||
| -rw-r--r-- | doc/http.html | 13 | ||||
| -rw-r--r-- | doc/index.html | 16 | ||||
| -rw-r--r-- | doc/mime.html | 10 | ||||
| -rw-r--r-- | doc/smtp.html | 13 | ||||
| -rw-r--r-- | doc/url.html | 5 | ||||
| -rw-r--r-- | etc/dict.lua | 44 | ||||
| -rw-r--r-- | etc/get.lua | 106 | ||||
| -rw-r--r-- | etc/lp.lua | 8 | ||||
| -rw-r--r-- | etc/tftp.lua | 68 | ||||
| -rw-r--r-- | makefile | 16 | ||||
| -rw-r--r-- | src/buffer.c | 14 | ||||
| -rw-r--r-- | src/buffer.h | 4 | ||||
| -rw-r--r-- | src/ftp.lua | 4 | ||||
| -rw-r--r-- | src/inet.c | 3 | ||||
| -rw-r--r-- | src/makefile | 173 | ||||
| -rw-r--r-- | src/mbox.lua | 40 | ||||
| -rw-r--r-- | src/tp.lua | 2 | ||||
| -rw-r--r-- | src/url.lua | 122 | ||||
| -rw-r--r-- | src/usocket.c | 6 | ||||
| -rw-r--r-- | src/wsocket.c | 8 | ||||
| -rw-r--r-- | test/ftptest.lua | 8 | ||||
| -rw-r--r-- | test/httptest.lua | 188 | ||||
| -rw-r--r-- | test/smtptest.lua | 104 | ||||
| -rw-r--r-- | test/testclnt.lua | 122 | ||||
| -rw-r--r-- | test/testsupport.lua | 14 | ||||
| -rw-r--r-- | test/urltest.lua | 620 | ||||
| -rw-r--r-- | test/utestclnt.lua | 2 |
30 files changed, 947 insertions, 849 deletions
| @@ -1,15 +1,14 @@ | |||
| 1 | http was preserving old host header during redirects | ||
| 2 | fix smtp.send hang on source error | ||
| 3 | add create field to FTP and SMTP and fix HTTP ugliness | ||
| 4 | clean timeout argument to open functions in SMTP, HTTP and FTP | ||
| 5 | eliminate globals from namespaces created by module(). | ||
| 6 | |||
| 7 | 1 | ||
| 8 | 2 | ||
| 9 | 3 | ||
| 10 | 4 | ||
| 11 | 5 | ||
| 12 | 6 | ||
| 7 | http was preserving old host header during redirects | ||
| 8 | fix smtp.send hang on source error | ||
| 9 | add create field to FTP and SMTP and fix HTTP ugliness | ||
| 10 | clean timeout argument to open functions in SMTP, HTTP and FTP | ||
| 11 | eliminate globals from namespaces created by module(). | ||
| 13 | url.absolute was not working when base_url was already parsed | 12 | url.absolute was not working when base_url was already parsed |
| 14 | http.request was redirecting even when the location header was empty | 13 | http.request was redirecting even when the location header was empty |
| 15 | tcp{client}:shutdown() was checking for group instead of class. | 14 | tcp{client}:shutdown() was checking for group instead of class. |
| @@ -2,19 +2,37 @@ What's New | |||
| 2 | 2 | ||
| 3 | This is just a bug-fix/update release. | 3 | This is just a bug-fix/update release. |
| 4 | 4 | ||
| 5 | * Fixed: manual links to home.html changed to index.html (Robert Hahn) | 5 | * Fixed: manual sample of HTTP authentication now uses correct |
| 6 | * Fixed: mime.unb64() returns empty string on results that start | 6 | "authorization" header (Alexandre Ittner); |
| 7 | with a null character (Robert Raschke) | 7 | * Fixed: failure on bind() was destroying the socket (Sam Roberts); |
| 8 | * Fixed: HTTP now automatically redirecting on 303 and 307 (Jonathan Gray) | 8 | * Fixed: receive() returns immediatelly if prefix can satisfy |
| 9 | * Fixed: sleep(-1) could sleep forever wasting CPU. Now it | 9 | bytes requested (M Joonas Pihlaja); |
| 10 | returns immediately (MPB); | 10 | * Fixed: multicast didn't work on Windows, or anywhere |
| 11 | else for that matter (Herbert Leuwer, Adrian Sietsma); | ||
| 12 | * Fixed: select() now reports an error when called with more | ||
| 13 | sockets than FD_SETSIZE (Lorenzo Leonini); | ||
| 14 | * Fixed: manual links to home.html changed to index.html (Robert Hahn); | ||
| 15 | * Fixed: mime.unb64() would return an empty string on results that started | ||
| 16 | with a null character (Robert Raschke); | ||
| 17 | * Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray); | ||
| 18 | * Fixed: calling sleep() with negative numbers could | ||
| 19 | block forever, wasting CPU. Now it returns immediately (MPB); | ||
| 20 | * Improved: FTP commands are now sent in upper case to | ||
| 21 | help buggy servers (Anders Eurenius); | ||
| 22 | * Improved: known headers now sent in canonic | ||
| 23 | capitalization to help buggy servers (Joseph Stewart); | ||
| 24 | * Improved: Clarified tcp:receive() in the manual (MPB); | ||
| 25 | * Improved: Decent makefiles (LHF). | ||
| 26 | * Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei). | ||
| 11 | 27 | ||
| 12 | * Improved: FTP commands are now sent in upper case to | ||
| 13 | help buggy servers (Anders Eurenius) | ||
| 14 | * Improved: known headers now sent in canonic | ||
| 15 | capitalization to help buggy servers (Joseph Stewart); | ||
| 16 | * Improved: Clarified tcp:receive() in the manual (MPB); | ||
| 17 | 28 | ||
| 18 | * Fixed: multicast didn't work on Windows (Herbert Leuwer, Adrian Sietsma) | 29 | Yuri's bug? |
| 19 | * Fixed: select() reports an error when called with more | 30 | Dahlberg |
| 20 | sockets than FD_SETSIZE (Lorenzo Leonini) | 31 | Sam Roberts |
| 32 | Thomas Harning Jr. | ||
| 33 | Sebastien Perin | ||
| 34 | remove getn in all files | ||
| 35 | ltn12.pump.all( | ||
| 36 | ltn12.source.file(io.open("original.png")), | ||
| 37 | ltn12.sink.file(io.open("copy.png", "wb")) | ||
| 38 | ) | ||
diff --git a/doc/ftp.html b/doc/ftp.html index 1f6335e..3f23a4a 100644 --- a/doc/ftp.html +++ b/doc/ftp.html | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | FTP (File Transfer Protocol) is a protocol used to transfer files | 42 | FTP (File Transfer Protocol) is a protocol used to transfer files |
| 43 | between hosts. The <tt>ftp</tt> namespace offers thorough support | 43 | between hosts. The <tt>ftp</tt> namespace offers thorough support |
| 44 | to FTP, under a simple interface. The implementation conforms to | 44 | to FTP, under a simple interface. The implementation conforms to |
| 45 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc0959.txt">RFC 959</a>. | 45 | <a href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</a>. |
| 46 | </p> | 46 | </p> |
| 47 | 47 | ||
| 48 | <p> | 48 | <p> |
| @@ -70,8 +70,8 @@ local ftp = require("socket.ftp") | |||
| 70 | 70 | ||
| 71 | <p> | 71 | <p> |
| 72 | URLs MUST conform to | 72 | URLs MUST conform to |
| 73 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC | 73 | <a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>, |
| 74 | 1738</a>, that is, an URL is a string in the form: | 74 | that is, an URL is a string in the form: |
| 75 | </p> | 75 | </p> |
| 76 | 76 | ||
| 77 | <blockquote> | 77 | <blockquote> |
diff --git a/doc/http.html b/doc/http.html index a274aef..66282a4 100644 --- a/doc/http.html +++ b/doc/http.html | |||
| @@ -45,8 +45,7 @@ namespace offers full support for the client side of the HTTP | |||
| 45 | protocol (i.e., | 45 | protocol (i.e., |
| 46 | the facilities that would be used by a web-browser implementation). The | 46 | the facilities that would be used by a web-browser implementation). The |
| 47 | implementation conforms to the HTTP/1.1 standard, | 47 | implementation conforms to the HTTP/1.1 standard, |
| 48 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC | 48 | <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>. |
| 49 | 2616</a>. | ||
| 50 | </p> | 49 | </p> |
| 51 | 50 | ||
| 52 | <p> | 51 | <p> |
| @@ -67,8 +66,7 @@ local http = require("socket.http") | |||
| 67 | 66 | ||
| 68 | <p> | 67 | <p> |
| 69 | URLs must conform to | 68 | URLs must conform to |
| 70 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC | 69 | <a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>, |
| 71 | 1738</a>, | ||
| 72 | that is, an URL is a string in the form: | 70 | that is, an URL is a string in the form: |
| 73 | </p> | 71 | </p> |
| 74 | 72 | ||
| @@ -199,8 +197,7 @@ it usually returns a message body (a web page informing the | |||
| 199 | URL was not found or some other useless page). To make sure the | 197 | URL was not found or some other useless page). To make sure the |
| 200 | operation was successful, check the returned status <tt>code</tt>. For | 198 | operation was successful, check the returned status <tt>code</tt>. For |
| 201 | a list of the possible values and their meanings, refer to <a | 199 | a list of the possible values and their meanings, refer to <a |
| 202 | href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC | 200 | href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>. |
| 203 | 2616</a>. | ||
| 204 | </p> | 201 | </p> |
| 205 | 202 | ||
| 206 | <p class=description> | 203 | <p class=description> |
| @@ -278,7 +275,7 @@ download and return status "401 Authentication Required". | |||
| 278 | The HTTP/1.1 standard defines two authentication methods: the Basic | 275 | The HTTP/1.1 standard defines two authentication methods: the Basic |
| 279 | Authentication Scheme and the Digest Authentication Scheme, both | 276 | Authentication Scheme and the Digest Authentication Scheme, both |
| 280 | explained in detail in | 277 | explained in detail in |
| 281 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2068.txt">RFC 2068</a>. | 278 | <a href="http://www.ietf.org/rfc/rfc2068.txt">RFC 2068</a>. |
| 282 | </p> | 279 | </p> |
| 283 | 280 | ||
| 284 | <p class=note>The Basic Authentication Scheme sends | 281 | <p class=note>The Basic Authentication Scheme sends |
| @@ -304,7 +301,7 @@ b, c, h = http.request("http://fulano:silva@www.example.com/private/index.html") | |||
| 304 | -- the request directly. | 301 | -- the request directly. |
| 305 | r, c = http.request { | 302 | r, c = http.request { |
| 306 | url = "http://www.example.com/private/index.html", | 303 | url = "http://www.example.com/private/index.html", |
| 307 | headers = { authentication = "Basic " .. (mime.b64("fulano:silva")) } | 304 | headers = { authorization = "Basic " .. (mime.b64("fulano:silva")) } |
| 308 | } | 305 | } |
| 309 | </pre> | 306 | </pre> |
| 310 | 307 | ||
diff --git a/doc/index.html b/doc/index.html index 5b54c59..665b97b 100644 --- a/doc/index.html +++ b/doc/index.html | |||
| @@ -138,18 +138,22 @@ all! | |||
| 138 | </p> | 138 | </p> |
| 139 | 139 | ||
| 140 | <ul> | 140 | <ul> |
| 141 | <li> Fixed: manual sample of HTTP authentication now uses correct | ||
| 142 | "authorization" header (Alexandre Ittner); | ||
| 143 | <li> Fixed: receive() returns immediatelly if prefix can satisfy | ||
| 144 | bytes requested (M Joonas Pihlaja); | ||
| 141 | <li> Fixed: multicast didn't work on Windows, or anywhere | 145 | <li> Fixed: multicast didn't work on Windows, or anywhere |
| 142 | else for that matter (Herbert Leuwer, Adrian Sietsma) | 146 | else for that matter (Herbert Leuwer, Adrian Sietsma); |
| 143 | <li> Fixed: select() now reports an error when called with more | 147 | <li> Fixed: select() now reports an error when called with more |
| 144 | sockets than FD_SETSIZE (Lorenzo Leonini) | 148 | sockets than FD_SETSIZE (Lorenzo Leonini); |
| 145 | <li> Fixed: manual links to home.html changed to index.html (Robert Hahn) | 149 | <li> Fixed: manual links to home.html changed to index.html (Robert Hahn); |
| 146 | <li> Fixed: mime.unb64() would return an empty string on results that started | 150 | <li> Fixed: mime.unb64() would return an empty string on results that started |
| 147 | with a null character (Robert Raschke) | 151 | with a null character (Robert Raschke); |
| 148 | <li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray) | 152 | <li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray); |
| 149 | <li> Fixed: calling sleep() with negative numbers could | 153 | <li> Fixed: calling sleep() with negative numbers could |
| 150 | block forever, wasting CPU. Now it returns immediately (MPB); | 154 | block forever, wasting CPU. Now it returns immediately (MPB); |
| 151 | <li> Improved: FTP commands are now sent in upper case to | 155 | <li> Improved: FTP commands are now sent in upper case to |
| 152 | help buggy servers (Anders Eurenius) | 156 | help buggy servers (Anders Eurenius); |
| 153 | <li> Improved: known headers now sent in canonic | 157 | <li> Improved: known headers now sent in canonic |
| 154 | capitalization to help buggy servers (Joseph Stewart); | 158 | capitalization to help buggy servers (Joseph Stewart); |
| 155 | <li> Improved: Clarified tcp:receive() in the manual (MPB); | 159 | <li> Improved: Clarified tcp:receive() in the manual (MPB); |
diff --git a/doc/mime.html b/doc/mime.html index 9844744..ae136fd 100644 --- a/doc/mime.html +++ b/doc/mime.html | |||
| @@ -44,11 +44,11 @@ content transfer encodings, such as Base64 and Quoted-Printable. | |||
| 44 | It also provides functions to break text into lines and change | 44 | It also provides functions to break text into lines and change |
| 45 | the end-of-line convention. | 45 | the end-of-line convention. |
| 46 | MIME is described mainly in | 46 | MIME is described mainly in |
| 47 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2045.txt">RFC 2045</a>, | 47 | <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>, |
| 48 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">2046</a>, | 48 | <a href="http://www.ietf.org/rfc/rfc2046.txt">2046</a>, |
| 49 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2047</a>, | 49 | <a href="http://www.ietf.org/rfc/rfc2047.txt">2047</a>, |
| 50 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2048</a>, and | 50 | <a href="http://www.ietf.org/rfc/rfc2047.txt">2048</a>, and |
| 51 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2048.txt">2049</a>. | 51 | <a href="http://www.ietf.org/rfc/rfc2048.txt">2049</a>. |
| 52 | </p> | 52 | </p> |
| 53 | 53 | ||
| 54 | <p> | 54 | <p> |
diff --git a/doc/smtp.html b/doc/smtp.html index 980b821..2ef673a 100644 --- a/doc/smtp.html +++ b/doc/smtp.html | |||
| @@ -48,14 +48,13 @@ control (if you bother to read the code). | |||
| 48 | </p> | 48 | </p> |
| 49 | 49 | ||
| 50 | <p>The implementation conforms to the Simple Mail Transfer Protocol, | 50 | <p>The implementation conforms to the Simple Mail Transfer Protocol, |
| 51 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>. | 51 | <a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a>. |
| 52 | Another RFC of interest is <a | 52 | Another RFC of interest is <a |
| 53 | href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>, | 53 | href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>, |
| 54 | which governs the Internet Message Format. | 54 | which governs the Internet Message Format. |
| 55 | Multipart messages (those that contain attachments) are part | 55 | Multipart messages (those that contain attachments) are part |
| 56 | of the MIME standard, but described mainly | 56 | of the MIME standard, but described mainly |
| 57 | in <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">RFC | 57 | in <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> |
| 58 | 2046</a> | ||
| 59 | 58 | ||
| 60 | <p> In the description below, good understanding of <a | 59 | <p> In the description below, good understanding of <a |
| 61 | href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters | 60 | href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters |
| @@ -196,7 +195,7 @@ part of the message and will not be sent to anyone. | |||
| 196 | </p> | 195 | </p> |
| 197 | 196 | ||
| 198 | <p class=note> | 197 | <p class=note> |
| 199 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a> | 198 | <a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a> |
| 200 | has two <em>important and short</em> sections, "3.6.3. Destination address | 199 | has two <em>important and short</em> sections, "3.6.3. Destination address |
| 201 | fields" and "5. Security considerations", explaining the proper | 200 | fields" and "5. Security considerations", explaining the proper |
| 202 | use of these headers. Here is a summary of what it says: | 201 | use of these headers. Here is a summary of what it says: |
| @@ -236,9 +235,9 @@ exactly what you <em>don't</em> want to happen! | |||
| 236 | 235 | ||
| 237 | <p class=note> | 236 | <p class=note> |
| 238 | I hope this clarifies the issue. Otherwise, please refer to | 237 | I hope this clarifies the issue. Otherwise, please refer to |
| 239 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a> | 238 | <a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a> |
| 240 | and | 239 | and |
| 241 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>. | 240 | <a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>. |
| 242 | </p> | 241 | </p> |
| 243 | 242 | ||
| 244 | <pre class=example> | 243 | <pre class=example> |
diff --git a/doc/url.html b/doc/url.html index 303e05d..9f234d9 100644 --- a/doc/url.html +++ b/doc/url.html | |||
| @@ -42,8 +42,7 @@ | |||
| 42 | The <tt>url</tt> namespace provides functions to parse, protect, | 42 | The <tt>url</tt> namespace provides functions to parse, protect, |
| 43 | and build URLs, as well as functions to compose absolute URLs | 43 | and build URLs, as well as functions to compose absolute URLs |
| 44 | from base and relative URLs, according to | 44 | from base and relative URLs, according to |
| 45 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC | 45 | <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. |
| 46 | 2396</a>. | ||
| 47 | </p> | 46 | </p> |
| 48 | 47 | ||
| 49 | <p> | 48 | <p> |
| @@ -91,7 +90,7 @@ The function returns a string with the absolute URL. | |||
| 91 | <p class=note> | 90 | <p class=note> |
| 92 | Note: The rules that | 91 | Note: The rules that |
| 93 | govern the composition are fairly complex, and are described in detail in | 92 | govern the composition are fairly complex, and are described in detail in |
| 94 | <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC 2396</a>. | 93 | <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. |
| 95 | The example bellow should give an idea of what the rules are. | 94 | The example bellow should give an idea of what the rules are. |
| 96 | </p> | 95 | </p> |
| 97 | 96 | ||
diff --git a/etc/dict.lua b/etc/dict.lua index 5c85aae..6eb3210 100644 --- a/etc/dict.lua +++ b/etc/dict.lua | |||
| @@ -44,48 +44,48 @@ function metat.__index:check(ok) | |||
| 44 | end | 44 | end |
| 45 | 45 | ||
| 46 | function metat.__index:getdef() | 46 | function metat.__index:getdef() |
| 47 | local line = socket.try(self.tp:receive()) | 47 | local line = socket.try(self.tp:receive()) |
| 48 | local def = {} | 48 | local def = {} |
| 49 | while line ~= "." do | 49 | while line ~= "." do |
| 50 | table.insert(def, line) | 50 | table.insert(def, line) |
| 51 | line = socket.try(self.tp:receive()) | 51 | line = socket.try(self.tp:receive()) |
| 52 | end | 52 | end |
| 53 | return table.concat(def, "\n") | 53 | return table.concat(def, "\n") |
| 54 | end | 54 | end |
| 55 | 55 | ||
| 56 | function metat.__index:define(database, word) | 56 | function metat.__index:define(database, word) |
| 57 | database = database or "!" | 57 | database = database or "!" |
| 58 | socket.try(self.tp:command("DEFINE", database .. " " .. word)) | 58 | socket.try(self.tp:command("DEFINE", database .. " " .. word)) |
| 59 | local code, count = self:check(150) | 59 | local code, count = self:check(150) |
| 60 | local defs = {} | 60 | local defs = {} |
| 61 | for i = 1, count do | 61 | for i = 1, count do |
| 62 | self:check(151) | 62 | self:check(151) |
| 63 | table.insert(defs, self:getdef()) | 63 | table.insert(defs, self:getdef()) |
| 64 | end | 64 | end |
| 65 | self:check(250) | 65 | self:check(250) |
| 66 | return defs | 66 | return defs |
| 67 | end | 67 | end |
| 68 | 68 | ||
| 69 | function metat.__index:match(database, strat, word) | 69 | function metat.__index:match(database, strat, word) |
| 70 | database = database or "!" | 70 | database = database or "!" |
| 71 | strat = strat or "." | 71 | strat = strat or "." |
| 72 | socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word)) | 72 | socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word)) |
| 73 | self:check(152) | 73 | self:check(152) |
| 74 | local mat = {} | 74 | local mat = {} |
| 75 | local line = socket.try(self.tp:receive()) | 75 | local line = socket.try(self.tp:receive()) |
| 76 | while line ~= '.' do | 76 | while line ~= '.' do |
| 77 | database, word = socket.skip(2, string.find(line, "(%S+) (.*)")) | 77 | database, word = socket.skip(2, string.find(line, "(%S+) (.*)")) |
| 78 | if not mat[database] then mat[database] = {} end | 78 | if not mat[database] then mat[database] = {} end |
| 79 | table.insert(mat[database], word) | 79 | table.insert(mat[database], word) |
| 80 | line = socket.try(self.tp:receive()) | 80 | line = socket.try(self.tp:receive()) |
| 81 | end | 81 | end |
| 82 | self:check(250) | 82 | self:check(250) |
| 83 | return mat | 83 | return mat |
| 84 | end | 84 | end |
| 85 | 85 | ||
| 86 | function metat.__index:quit() | 86 | function metat.__index:quit() |
| 87 | self.tp:command("QUIT") | 87 | self.tp:command("QUIT") |
| 88 | return self:check(221) | 88 | return self:check(221) |
| 89 | end | 89 | end |
| 90 | 90 | ||
| 91 | function metat.__index:close() | 91 | function metat.__index:close() |
diff --git a/etc/get.lua b/etc/get.lua index 09f639d..0d631c2 100644 --- a/etc/get.lua +++ b/etc/get.lua | |||
| @@ -12,53 +12,53 @@ local ltn12 = require("ltn12") | |||
| 12 | 12 | ||
| 13 | -- formats a number of seconds into human readable form | 13 | -- formats a number of seconds into human readable form |
| 14 | function nicetime(s) | 14 | function nicetime(s) |
| 15 | local l = "s" | 15 | local l = "s" |
| 16 | if s > 60 then | 16 | if s > 60 then |
| 17 | s = s / 60 | 17 | s = s / 60 |
| 18 | l = "m" | 18 | l = "m" |
| 19 | if s > 60 then | 19 | if s > 60 then |
| 20 | s = s / 60 | 20 | s = s / 60 |
| 21 | l = "h" | 21 | l = "h" |
| 22 | if s > 24 then | 22 | if s > 24 then |
| 23 | s = s / 24 | 23 | s = s / 24 |
| 24 | l = "d" -- hmmm | 24 | l = "d" -- hmmm |
| 25 | end | 25 | end |
| 26 | end | 26 | end |
| 27 | end | 27 | end |
| 28 | if l == "s" then return string.format("%5.0f%s", s, l) | 28 | if l == "s" then return string.format("%5.0f%s", s, l) |
| 29 | else return string.format("%5.2f%s", s, l) end | 29 | else return string.format("%5.2f%s", s, l) end |
| 30 | end | 30 | end |
| 31 | 31 | ||
| 32 | -- formats a number of bytes into human readable form | 32 | -- formats a number of bytes into human readable form |
| 33 | function nicesize(b) | 33 | function nicesize(b) |
| 34 | local l = "B" | 34 | local l = "B" |
| 35 | if b > 1024 then | 35 | if b > 1024 then |
| 36 | b = b / 1024 | 36 | b = b / 1024 |
| 37 | l = "KB" | 37 | l = "KB" |
| 38 | if b > 1024 then | 38 | if b > 1024 then |
| 39 | b = b / 1024 | 39 | b = b / 1024 |
| 40 | l = "MB" | 40 | l = "MB" |
| 41 | if b > 1024 then | 41 | if b > 1024 then |
| 42 | b = b / 1024 | 42 | b = b / 1024 |
| 43 | l = "GB" -- hmmm | 43 | l = "GB" -- hmmm |
| 44 | end | 44 | end |
| 45 | end | 45 | end |
| 46 | end | 46 | end |
| 47 | return string.format("%7.2f%2s", b, l) | 47 | return string.format("%7.2f%2s", b, l) |
| 48 | end | 48 | end |
| 49 | 49 | ||
| 50 | -- returns a string with the current state of the download | 50 | -- returns a string with the current state of the download |
| 51 | local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining" | 51 | local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining" |
| 52 | local elapsed_s = "%s received, %s/s throughput, %s elapsed " | 52 | local elapsed_s = "%s received, %s/s throughput, %s elapsed " |
| 53 | function gauge(got, delta, size) | 53 | function gauge(got, delta, size) |
| 54 | local rate = got / delta | 54 | local rate = got / delta |
| 55 | if size and size >= 1 then | 55 | if size and size >= 1 then |
| 56 | return string.format(remaining_s, nicesize(got), nicesize(rate), | 56 | return string.format(remaining_s, nicesize(got), nicesize(rate), |
| 57 | 100*got/size, nicetime((size-got)/rate)) | 57 | 100*got/size, nicetime((size-got)/rate)) |
| 58 | else | 58 | else |
| 59 | return string.format(elapsed_s, nicesize(got), | 59 | return string.format(elapsed_s, nicesize(got), |
| 60 | nicesize(rate), nicetime(delta)) | 60 | nicesize(rate), nicetime(delta)) |
| 61 | end | 61 | end |
| 62 | end | 62 | end |
| 63 | 63 | ||
| 64 | -- creates a new instance of a receive_cb that saves to disk | 64 | -- creates a new instance of a receive_cb that saves to disk |
| @@ -89,10 +89,10 @@ end | |||
| 89 | 89 | ||
| 90 | -- determines the size of a http file | 90 | -- determines the size of a http file |
| 91 | function gethttpsize(u) | 91 | function gethttpsize(u) |
| 92 | local r, c, h = http.request {method = "HEAD", url = u} | 92 | local r, c, h = http.request {method = "HEAD", url = u} |
| 93 | if c == 200 then | 93 | if c == 200 then |
| 94 | return tonumber(h["content-length"]) | 94 | return tonumber(h["content-length"]) |
| 95 | end | 95 | end |
| 96 | end | 96 | end |
| 97 | 97 | ||
| 98 | -- downloads a file using the http protocol | 98 | -- downloads a file using the http protocol |
| @@ -101,7 +101,7 @@ function getbyhttp(u, file) | |||
| 101 | -- only print feedback if output is not stdout | 101 | -- only print feedback if output is not stdout |
| 102 | if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end | 102 | if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end |
| 103 | local r, c, h, s = http.request {url = u, sink = save } | 103 | local r, c, h, s = http.request {url = u, sink = save } |
| 104 | if c ~= 200 then io.stderr:write(s or c, "\n") end | 104 | if c ~= 200 then io.stderr:write(s or c, "\n") end |
| 105 | end | 105 | end |
| 106 | 106 | ||
| 107 | -- downloads a file using the ftp protocol | 107 | -- downloads a file using the ftp protocol |
| @@ -114,29 +114,29 @@ function getbyftp(u, file) | |||
| 114 | gett.sink = save | 114 | gett.sink = save |
| 115 | gett.type = "i" | 115 | gett.type = "i" |
| 116 | local ret, err = ftp.get(gett) | 116 | local ret, err = ftp.get(gett) |
| 117 | if err then print(err) end | 117 | if err then print(err) end |
| 118 | end | 118 | end |
| 119 | 119 | ||
| 120 | -- determines the scheme | 120 | -- determines the scheme |
| 121 | function getscheme(u) | 121 | function getscheme(u) |
| 122 | -- this is an heuristic to solve a common invalid url poblem | 122 | -- this is an heuristic to solve a common invalid url poblem |
| 123 | if not string.find(u, "//") then u = "//" .. u end | 123 | if not string.find(u, "//") then u = "//" .. u end |
| 124 | local parsed = url.parse(u, {scheme = "http"}) | 124 | local parsed = url.parse(u, {scheme = "http"}) |
| 125 | return parsed.scheme | 125 | return parsed.scheme |
| 126 | end | 126 | end |
| 127 | 127 | ||
| 128 | -- gets a file either by http or ftp, saving as <name> | 128 | -- gets a file either by http or ftp, saving as <name> |
| 129 | function get(u, name) | 129 | function get(u, name) |
| 130 | local fout = name and io.open(name, "wb") | 130 | local fout = name and io.open(name, "wb") |
| 131 | local scheme = getscheme(u) | 131 | local scheme = getscheme(u) |
| 132 | if scheme == "ftp" then getbyftp(u, fout) | 132 | if scheme == "ftp" then getbyftp(u, fout) |
| 133 | elseif scheme == "http" then getbyhttp(u, fout) | 133 | elseif scheme == "http" then getbyhttp(u, fout) |
| 134 | else print("unknown scheme" .. scheme) end | 134 | else print("unknown scheme" .. scheme) end |
| 135 | end | 135 | end |
| 136 | 136 | ||
| 137 | -- main program | 137 | -- main program |
| 138 | arg = arg or {} | 138 | arg = arg or {} |
| 139 | if table.getn(arg) < 1 then | 139 | if table.getn(arg) < 1 then |
| 140 | io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n") | 140 | io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n") |
| 141 | os.exit(1) | 141 | os.exit(1) |
| 142 | else get(arg[1], arg[2]) end | 142 | else get(arg[1], arg[2]) end |
| @@ -268,11 +268,11 @@ send = socket.protect(function(option) | |||
| 268 | local class = string.sub(option.class or localip or localhost,1,31) | 268 | local class = string.sub(option.class or localip or localhost,1,31) |
| 269 | local _,_,ctlfn = string.find(file,".*[%/%\\](.*)") | 269 | local _,_,ctlfn = string.find(file,".*[%/%\\](.*)") |
| 270 | ctlfn = string.sub(ctlfn or file,1,131) | 270 | ctlfn = string.sub(ctlfn or file,1,131) |
| 271 | local cfile = | 271 | local cfile = |
| 272 | string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n", | 272 | string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n", |
| 273 | localhost, | 273 | localhost, |
| 274 | class, | 274 | class, |
| 275 | option.job or "LuaSocket", | 275 | option.job or "LuaSocket", |
| 276 | user, | 276 | user, |
| 277 | fmt, lpfile, | 277 | fmt, lpfile, |
| 278 | lpfile, | 278 | lpfile, |
diff --git a/etc/tftp.lua b/etc/tftp.lua index c028b20..4051e74 100644 --- a/etc/tftp.lua +++ b/etc/tftp.lua | |||
| @@ -35,18 +35,18 @@ local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"} | |||
| 35 | -- Packet creation functions | 35 | -- Packet creation functions |
| 36 | ----------------------------------------------------------------------------- | 36 | ----------------------------------------------------------------------------- |
| 37 | local function RRQ(source, mode) | 37 | local function RRQ(source, mode) |
| 38 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) | 38 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | local function WRQ(source, mode) | 41 | local function WRQ(source, mode) |
| 42 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) | 42 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) |
| 43 | end | 43 | end |
| 44 | 44 | ||
| 45 | local function ACK(block) | 45 | local function ACK(block) |
| 46 | local low, high | 46 | local low, high |
| 47 | low = math.mod(block, 256) | 47 | low = math.mod(block, 256) |
| 48 | high = (block - low)/256 | 48 | high = (block - low)/256 |
| 49 | return char(0, OP_ACK, high, low) | 49 | return char(0, OP_ACK, high, low) |
| 50 | end | 50 | end |
| 51 | 51 | ||
| 52 | local function get_OP(dgram) | 52 | local function get_OP(dgram) |
| @@ -58,16 +58,16 @@ end | |||
| 58 | -- Packet analysis functions | 58 | -- Packet analysis functions |
| 59 | ----------------------------------------------------------------------------- | 59 | ----------------------------------------------------------------------------- |
| 60 | local function split_DATA(dgram) | 60 | local function split_DATA(dgram) |
| 61 | local block = byte(dgram, 3)*256 + byte(dgram, 4) | 61 | local block = byte(dgram, 3)*256 + byte(dgram, 4) |
| 62 | local data = string.sub(dgram, 5) | 62 | local data = string.sub(dgram, 5) |
| 63 | return block, data | 63 | return block, data |
| 64 | end | 64 | end |
| 65 | 65 | ||
| 66 | local function get_ERROR(dgram) | 66 | local function get_ERROR(dgram) |
| 67 | local code = byte(dgram, 3)*256 + byte(dgram, 4) | 67 | local code = byte(dgram, 3)*256 + byte(dgram, 4) |
| 68 | local msg | 68 | local msg |
| 69 | _,_, msg = string.find(dgram, "(.*)\000", 5) | 69 | _,_, msg = string.find(dgram, "(.*)\000", 5) |
| 70 | return string.format("error code %d: %s", code, msg) | 70 | return string.format("error code %d: %s", code, msg) |
| 71 | end | 71 | end |
| 72 | 72 | ||
| 73 | ----------------------------------------------------------------------------- | 73 | ----------------------------------------------------------------------------- |
| @@ -77,40 +77,40 @@ local function tget(gett) | |||
| 77 | local retries, dgram, sent, datahost, dataport, code | 77 | local retries, dgram, sent, datahost, dataport, code |
| 78 | local last = 0 | 78 | local last = 0 |
| 79 | socket.try(gett.host, "missing host") | 79 | socket.try(gett.host, "missing host") |
| 80 | local con = socket.try(socket.udp()) | 80 | local con = socket.try(socket.udp()) |
| 81 | local try = socket.newtry(function() con:close() end) | 81 | local try = socket.newtry(function() con:close() end) |
| 82 | -- convert from name to ip if needed | 82 | -- convert from name to ip if needed |
| 83 | gett.host = try(socket.dns.toip(gett.host)) | 83 | gett.host = try(socket.dns.toip(gett.host)) |
| 84 | con:settimeout(1) | 84 | con:settimeout(1) |
| 85 | -- first packet gives data host/port to be used for data transfers | 85 | -- first packet gives data host/port to be used for data transfers |
| 86 | local path = string.gsub(gett.path or "", "^/", "") | 86 | local path = string.gsub(gett.path or "", "^/", "") |
| 87 | path = url.unescape(path) | 87 | path = url.unescape(path) |
| 88 | retries = 0 | 88 | retries = 0 |
| 89 | repeat | 89 | repeat |
| 90 | sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port)) | 90 | sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port)) |
| 91 | dgram, datahost, dataport = con:receivefrom() | 91 | dgram, datahost, dataport = con:receivefrom() |
| 92 | retries = retries + 1 | 92 | retries = retries + 1 |
| 93 | until dgram or datahost ~= "timeout" or retries > 5 | 93 | until dgram or datahost ~= "timeout" or retries > 5 |
| 94 | try(dgram, datahost) | 94 | try(dgram, datahost) |
| 95 | -- associate socket with data host/port | 95 | -- associate socket with data host/port |
| 96 | try(con:setpeername(datahost, dataport)) | 96 | try(con:setpeername(datahost, dataport)) |
| 97 | -- default sink | 97 | -- default sink |
| 98 | local sink = gett.sink or ltn12.sink.null() | 98 | local sink = gett.sink or ltn12.sink.null() |
| 99 | -- process all data packets | 99 | -- process all data packets |
| 100 | while 1 do | 100 | while 1 do |
| 101 | -- decode packet | 101 | -- decode packet |
| 102 | code = get_OP(dgram) | 102 | code = get_OP(dgram) |
| 103 | try(code ~= OP_ERROR, get_ERROR(dgram)) | 103 | try(code ~= OP_ERROR, get_ERROR(dgram)) |
| 104 | try(code == OP_DATA, "unhandled opcode " .. code) | 104 | try(code == OP_DATA, "unhandled opcode " .. code) |
| 105 | -- get data packet parts | 105 | -- get data packet parts |
| 106 | local block, data = split_DATA(dgram) | 106 | local block, data = split_DATA(dgram) |
| 107 | -- if not repeated, write | 107 | -- if not repeated, write |
| 108 | if block == last+1 then | 108 | if block == last+1 then |
| 109 | try(sink(data)) | 109 | try(sink(data)) |
| 110 | last = block | 110 | last = block |
| 111 | end | 111 | end |
| 112 | -- last packet brings less than 512 bytes of data | 112 | -- last packet brings less than 512 bytes of data |
| 113 | if string.len(data) < 512 then | 113 | if string.len(data) < 512 then |
| 114 | try(con:send(ACK(block))) | 114 | try(con:send(ACK(block))) |
| 115 | try(con:close()) | 115 | try(con:close()) |
| 116 | try(sink(nil)) | 116 | try(sink(nil)) |
| @@ -118,13 +118,13 @@ local function tget(gett) | |||
| 118 | end | 118 | end |
| 119 | -- get the next packet | 119 | -- get the next packet |
| 120 | retries = 0 | 120 | retries = 0 |
| 121 | repeat | 121 | repeat |
| 122 | sent = try(con:send(ACK(last))) | 122 | sent = try(con:send(ACK(last))) |
| 123 | dgram, err = con:receive() | 123 | dgram, err = con:receive() |
| 124 | retries = retries + 1 | 124 | retries = retries + 1 |
| 125 | until dgram or err ~= "timeout" or retries > 5 | 125 | until dgram or err ~= "timeout" or retries > 5 |
| 126 | try(dgram, err) | 126 | try(dgram, err) |
| 127 | end | 127 | end |
| 128 | end | 128 | end |
| 129 | 129 | ||
| 130 | local default = { | 130 | local default = { |
| @@ -1,21 +1,13 @@ | |||
| 1 | PLAT= none | 1 | PLAT?= macosx |
| 2 | PLATS= macosx linux | 2 | PLATS= macosx linux win32 |
| 3 | 3 | ||
| 4 | #------ | 4 | #------ |
| 5 | # Hopefully no need to change anything below this line | 5 | # Hopefully no need to change anything below this line |
| 6 | # | 6 | # |
| 7 | all: $(PLAT) | 7 | all: $(PLAT) |
| 8 | 8 | ||
| 9 | none: | 9 | $(PLATS) none install local clean: |
| 10 | @echo "Please run" | 10 | @cd src; $(MAKE) $@ |
| 11 | @echo " make PLATFORM" | ||
| 12 | @echo "where PLATFORM is one of these:" | ||
| 13 | @echo " $(PLATS)" | ||
| 14 | |||
| 15 | $(PLATS) install local clean: | ||
| 16 | cd src; $(MAKE) $@ | ||
| 17 | |||
| 18 | dummy: | ||
| 19 | 11 | ||
| 20 | test: dummy | 12 | test: dummy |
| 21 | lua test/hello.lua | 13 | lua test/hello.lua |
diff --git a/src/buffer.c b/src/buffer.c index 363da3d..5be0faf 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -42,7 +42,7 @@ int buffer_open(lua_State *L) { | |||
| 42 | * Initializes C structure | 42 | * Initializes C structure |
| 43 | \*-------------------------------------------------------------------------*/ | 43 | \*-------------------------------------------------------------------------*/ |
| 44 | void buffer_init(p_buffer buf, p_io io, p_timeout tm) { | 44 | void buffer_init(p_buffer buf, p_io io, p_timeout tm) { |
| 45 | buf->first = buf->last = 0; | 45 | buf->first = buf->last = 0; |
| 46 | buf->io = io; | 46 | buf->io = io; |
| 47 | buf->tm = tm; | 47 | buf->tm = tm; |
| 48 | buf->received = buf->sent = 0; | 48 | buf->received = buf->sent = 0; |
| @@ -122,9 +122,15 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { | |||
| 122 | if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); | 122 | if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); |
| 123 | else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); | 123 | else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); |
| 124 | else luaL_argcheck(L, 0, 2, "invalid receive pattern"); | 124 | else luaL_argcheck(L, 0, 2, "invalid receive pattern"); |
| 125 | /* get a fixed number of bytes (minus what was already partially | 125 | /* get a fixed number of bytes (minus what was already partially |
| 126 | * received) */ | 126 | * received) */ |
| 127 | } else err = recvraw(buf, (size_t) lua_tonumber(L, 2)-size, &b); | 127 | } else { |
| 128 | double n = lua_tonumber(L, 2); | ||
| 129 | size_t wanted = (size_t) n; | ||
| 130 | luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); | ||
| 131 | if (size == 0 || wanted > size) | ||
| 132 | err = recvraw(buf, wanted-size, &b); | ||
| 133 | } | ||
| 128 | /* check if there was an error */ | 134 | /* check if there was an error */ |
| 129 | if (err != IO_DONE) { | 135 | if (err != IO_DONE) { |
| 130 | /* we can't push anyting in the stack before pushing the | 136 | /* we can't push anyting in the stack before pushing the |
diff --git a/src/buffer.h b/src/buffer.h index 58838d1..1281bb3 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -29,8 +29,8 @@ typedef struct t_buffer_ { | |||
| 29 | size_t sent, received; /* bytes sent, and bytes received */ | 29 | size_t sent, received; /* bytes sent, and bytes received */ |
| 30 | p_io io; /* IO driver used for this buffer */ | 30 | p_io io; /* IO driver used for this buffer */ |
| 31 | p_timeout tm; /* timeout management for this buffer */ | 31 | p_timeout tm; /* timeout management for this buffer */ |
| 32 | size_t first, last; /* index of first and last bytes of stored data */ | 32 | size_t first, last; /* index of first and last bytes of stored data */ |
| 33 | char data[BUF_SIZE]; /* storage space for buffer data */ | 33 | char data[BUF_SIZE]; /* storage space for buffer data */ |
| 34 | } t_buffer; | 34 | } t_buffer; |
| 35 | typedef t_buffer *p_buffer; | 35 | typedef t_buffer *p_buffer; |
| 36 | 36 | ||
diff --git a/src/ftp.lua b/src/ftp.lua index f27e838..c90a65c 100644 --- a/src/ftp.lua +++ b/src/ftp.lua | |||
| @@ -212,8 +212,8 @@ local function tput(putt) | |||
| 212 | end | 212 | end |
| 213 | 213 | ||
| 214 | local default = { | 214 | local default = { |
| 215 | path = "/", | 215 | path = "/", |
| 216 | scheme = "ftp" | 216 | scheme = "ftp" |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | local function parse(u) | 219 | local function parse(u) |
| @@ -213,7 +213,7 @@ const char *inet_tryconnect(p_socket ps, const char *address, | |||
| 213 | memset(&remote, 0, sizeof(remote)); | 213 | memset(&remote, 0, sizeof(remote)); |
| 214 | remote.sin_family = AF_INET; | 214 | remote.sin_family = AF_INET; |
| 215 | remote.sin_port = htons(port); | 215 | remote.sin_port = htons(port); |
| 216 | if (strcmp(address, "*")) { | 216 | if (strcmp(address, "*")) { |
| 217 | if (!inet_aton(address, &remote.sin_addr)) { | 217 | if (!inet_aton(address, &remote.sin_addr)) { |
| 218 | struct hostent *hp = NULL; | 218 | struct hostent *hp = NULL; |
| 219 | struct in_addr **addr; | 219 | struct in_addr **addr; |
| @@ -248,7 +248,6 @@ const char *inet_trybind(p_socket ps, const char *address, unsigned short port) | |||
| 248 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); | 248 | memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); |
| 249 | } | 249 | } |
| 250 | err = socket_bind(ps, (SA *) &local, sizeof(local)); | 250 | err = socket_bind(ps, (SA *) &local, sizeof(local)); |
| 251 | if (err != IO_DONE) socket_destroy(ps); | ||
| 252 | return socket_strerror(err); | 251 | return socket_strerror(err); |
| 253 | } | 252 | } |
| 254 | 253 | ||
diff --git a/src/makefile b/src/makefile index 3351997..701feb3 100644 --- a/src/makefile +++ b/src/makefile | |||
| @@ -1,8 +1,13 @@ | |||
| 1 | PLAT = none | 1 | PLAT?=macosx |
| 2 | |||
| 2 | INSTALL_DATA=cp | 3 | INSTALL_DATA=cp |
| 3 | INSTALL_EXEC=cp | 4 | INSTALL_EXEC=cp |
| 4 | INSTALL_TOP= /opt/local | 5 | INSTALL_TOP=/opt/local |
| 5 | LUAINC= $(LUAINC_$(PLAT)) | 6 | |
| 7 | LUAINC_macosx=/opt/local/include | ||
| 8 | LUAINC_linux=/usr/include/lua5.1 | ||
| 9 | LUAINC_win32="../../lua-5.1.3/src" | ||
| 10 | LUALIB_win32="../../lua-5.1.3" | ||
| 6 | 11 | ||
| 7 | #------ | 12 | #------ |
| 8 | # Install directories | 13 | # Install directories |
| @@ -15,40 +20,76 @@ INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime | |||
| 15 | INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime | 20 | INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime |
| 16 | 21 | ||
| 17 | #------ | 22 | #------ |
| 18 | # Output file names | 23 | # Supported platforms |
| 19 | # | 24 | # |
| 20 | EXT=so | 25 | PLATS= macosx linux win32 |
| 21 | SOCKET_V=2.0.3 | ||
| 22 | MIME_V=1.0.3 | ||
| 23 | SOCKET_SO=socket.$(EXT).$(SOCKET_V) | ||
| 24 | MIME_SO=mime.$(EXT).$(MIME_V) | ||
| 25 | UNIX_SO=unix.$(EXT) | ||
| 26 | 26 | ||
| 27 | #------ | 27 | #------ |
| 28 | # Compiler and linker settings | 28 | # Compiler and linker settings |
| 29 | # for Mac OS X | 29 | # for Mac OS X |
| 30 | LUAINC_macosx= -I/opt/local/include | 30 | SO_macosx=so |
| 31 | O_macosx=o | ||
| 31 | CC_macosx=gcc | 32 | CC_macosx=gcc |
| 32 | DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \ | 33 | DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \ |
| 33 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ | 34 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ |
| 34 | -DMIME_API='__attribute__((visibility("default")))' | 35 | -DMIME_API='__attribute__((visibility("default")))' |
| 35 | CFLAGS_macosx= $(LUAINC) $(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common \ | 36 | CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ |
| 36 | -fvisibility=hidden | 37 | -fvisibility=hidden |
| 37 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup | 38 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o |
| 38 | LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc | 39 | LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc |
| 40 | SOCKET_macosx=usocket.o | ||
| 39 | 41 | ||
| 40 | #------ | 42 | #------ |
| 41 | # Compiler and linker settings | 43 | # Compiler and linker settings |
| 42 | # for Linux | 44 | # for Linux |
| 43 | LUAINC_linux= -I/usr/local/include/lua5.1 | 45 | SO_linux=so |
| 46 | O_linux=o | ||
| 44 | CC_linux=gcc | 47 | CC_linux=gcc |
| 45 | DEF_linux=-DLUASOCKET_DEBUG \ | 48 | DEF_linux=-DLUASOCKET_DEBUG \ |
| 46 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ | 49 | -DLUASOCKET_API='__attribute__((visibility("default")))' \ |
| 47 | -DMIME_API='__attribute__((visibility("default")))' | 50 | -DMIME_API='__attribute__((visibility("default")))' |
| 48 | CFLAGS_linux= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \ | 51 | CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \ |
| 49 | -fvisibility=hidden | 52 | -fvisibility=hidden |
| 50 | LDFLAGS_linux=-O -shared -fpic | 53 | LDFLAGS_linux=-O -shared -fpic -o |
| 51 | LD_linux= gcc | 54 | LD_linux=gcc |
| 55 | SOCKET_linux=usocket.o | ||
| 56 | |||
| 57 | #------ | ||
| 58 | # Compiler and linker settings | ||
| 59 | # for Win32 | ||
| 60 | SO_win32=dll | ||
| 61 | O_win32=obj | ||
| 62 | CC_win32=cl | ||
| 63 | DEF_win32= /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" \ | ||
| 64 | /D "LUASOCKET_API=__declspec(dllexport)" /D "LUASOCKET_DEBUG" \ | ||
| 65 | /D "_CRT_SECURE_NO_WARNINGS" /D "_WINDLL" | ||
| 66 | CFLAGS_win32=/I$(LUAINC) $(DEF) /O2 /Ot /MD /W3 /nologo | ||
| 67 | LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \ | ||
| 68 | /LIBPATH:$(LUALIB) \ | ||
| 69 | /MANIFEST \ | ||
| 70 | /MANIFESTFILE:"intermediate.manifest" \ | ||
| 71 | /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | ||
| 72 | /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \ | ||
| 73 | /MACHINE:X86 ws2_32.lib lua5.1.lib /OUT: | ||
| 74 | LD_win32=cl | ||
| 75 | SOCKET_win32=wsocket.obj | ||
| 76 | |||
| 77 | .SUFFIXES: .obj | ||
| 78 | |||
| 79 | .c.obj: | ||
| 80 | $(CC) $(CFLAGS) /Fo"$@" /c $< | ||
| 81 | |||
| 82 | #------ | ||
| 83 | # Output file names | ||
| 84 | # | ||
| 85 | SO=$(SO_$(PLAT)) | ||
| 86 | O=$(O_$(PLAT)) | ||
| 87 | SOCKET_V=2.0.3 | ||
| 88 | MIME_V=1.0.3 | ||
| 89 | SOCKET_SO=socket.$(SO).$(SOCKET_V) | ||
| 90 | MIME_SO=mime.$(SO).$(MIME_V) | ||
| 91 | UNIX_SO=unix.$(SO) | ||
| 92 | SOCKET=$(SOCKET_$(PLAT)) | ||
| 52 | 93 | ||
| 53 | #------ | 94 | #------ |
| 54 | # Settings selected for platform | 95 | # Settings selected for platform |
| @@ -58,46 +99,48 @@ DEF=$(DEF_$(PLAT)) | |||
| 58 | CFLAGS=$(CFLAGS_$(PLAT)) | 99 | CFLAGS=$(CFLAGS_$(PLAT)) |
| 59 | LDFLAGS=$(LDFLAGS_$(PLAT)) | 100 | LDFLAGS=$(LDFLAGS_$(PLAT)) |
| 60 | LD=$(LD_$(PLAT)) | 101 | LD=$(LD_$(PLAT)) |
| 102 | LUAINC= $(LUAINC_$(PLAT)) | ||
| 103 | LUALIB= $(LUALIB_$(PLAT)) | ||
| 61 | 104 | ||
| 62 | #------ | 105 | #------ |
| 63 | # Modules belonging to socket-core | 106 | # Modules belonging to socket-core |
| 64 | # | 107 | # |
| 65 | SOCKET_OBJS= \ | 108 | SOCKET_OBJS= \ |
| 66 | luasocket.o \ | 109 | luasocket.$(O) \ |
| 67 | timeout.o \ | 110 | timeout.$(O) \ |
| 68 | buffer.o \ | 111 | buffer.$(O) \ |
| 69 | io.o \ | 112 | io.$(O) \ |
| 70 | auxiliar.o \ | 113 | auxiliar.$(O) \ |
| 71 | options.o \ | 114 | options.$(O) \ |
| 72 | inet.o \ | 115 | inet.$(O) \ |
| 73 | usocket.o \ | 116 | $(SOCKET) \ |
| 74 | except.o \ | 117 | except.$(O) \ |
| 75 | select.o \ | 118 | select.$(O) \ |
| 76 | tcp.o \ | 119 | tcp.$(O) \ |
| 77 | udp.o | 120 | udp.$(O) |
| 78 | 121 | ||
| 79 | #------ | 122 | #------ |
| 80 | # Modules belonging mime-core | 123 | # Modules belonging mime-core |
| 81 | # | 124 | # |
| 82 | MIME_OBJS= \ | 125 | MIME_OBJS= \ |
| 83 | mime.o | 126 | mime.$(O) |
| 84 | 127 | ||
| 85 | #------ | 128 | #------ |
| 86 | # Modules belonging unix (local domain sockets) | 129 | # Modules belonging unix (local domain sockets) |
| 87 | # | 130 | # |
| 88 | UNIX_OBJS:=\ | 131 | UNIX_OBJS=\ |
| 89 | buffer.o \ | 132 | buffer.$(O) \ |
| 90 | auxiliar.o \ | 133 | auxiliar.$(O) \ |
| 91 | options.o \ | 134 | options.$(O) \ |
| 92 | timeout.o \ | 135 | timeout.$(O) \ |
| 93 | io.o \ | 136 | io.$(O) \ |
| 94 | usocket.o \ | 137 | usocket.$(O) \ |
| 95 | unix.o | 138 | unix.$(O) |
| 96 | 139 | ||
| 97 | #------ | 140 | #------ |
| 98 | # Files to install | 141 | # Files to install |
| 99 | # | 142 | # |
| 100 | TO_SOCKET_SHARE:= \ | 143 | TO_SOCKET_SHARE= \ |
| 101 | http.lua \ | 144 | http.lua \ |
| 102 | url.lua \ | 145 | url.lua \ |
| 103 | tp.lua \ | 146 | tp.lua \ |
| @@ -105,33 +148,41 @@ TO_SOCKET_SHARE:= \ | |||
| 105 | headers.lua \ | 148 | headers.lua \ |
| 106 | smtp.lua | 149 | smtp.lua |
| 107 | 150 | ||
| 108 | TO_TOP_SHARE:= \ | 151 | TO_TOP_SHARE= \ |
| 109 | ltn12.lua \ | 152 | ltn12.lua \ |
| 110 | socket.lua \ | 153 | socket.lua \ |
| 111 | mime.lua | 154 | mime.lua |
| 112 | 155 | ||
| 156 | #------ | ||
| 157 | # Targets | ||
| 158 | # | ||
| 113 | default: $(PLAT) | 159 | default: $(PLAT) |
| 114 | 160 | ||
| 115 | macosx: | 161 | macosx: |
| 116 | $(MAKE) all PLAT=macosx | 162 | $(MAKE) all PLAT=macosx |
| 117 | 163 | ||
| 164 | win32: | ||
| 165 | $(MAKE) all PLAT=win32 | ||
| 166 | |||
| 118 | linux: | 167 | linux: |
| 119 | $(MAKE) all PLAT=linux | 168 | $(MAKE) all PLAT=linux |
| 120 | 169 | ||
| 121 | none: | 170 | none: |
| 122 | @echo "Please choose a platform:" | 171 | @echo "Please run" |
| 172 | @echo " make PLATFORM" | ||
| 173 | @echo "where PLATFORM is one of these:" | ||
| 123 | @echo " $(PLATS)" | 174 | @echo " $(PLATS)" |
| 124 | 175 | ||
| 125 | all: $(SOCKET_SO) $(MIME_SO) | 176 | all: $(SOCKET_SO) $(MIME_SO) |
| 126 | 177 | ||
| 127 | $(SOCKET_SO): $(SOCKET_OBJS) | 178 | $(SOCKET_SO): $(SOCKET_OBJS) |
| 128 | $(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS) | 179 | $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ |
| 129 | 180 | ||
| 130 | $(MIME_SO): $(MIME_OBJS) | 181 | $(MIME_SO): $(MIME_OBJS) |
| 131 | $(LD) $(LDFLAGS) -o $@ $(MIME_OBJS) | 182 | $(LD) $(MIME_OBJS) $(LDFLAGS)$@ |
| 132 | 183 | ||
| 133 | $(UNIX_SO): $(UNIX_OBJS) | 184 | $(UNIX_SO): $(UNIX_OBJS) |
| 134 | $(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS) | 185 | $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ |
| 135 | 186 | ||
| 136 | install: | 187 | install: |
| 137 | mkdir -p $(INSTALL_TOP_SHARE) | 188 | mkdir -p $(INSTALL_TOP_SHARE) |
| @@ -139,9 +190,9 @@ install: | |||
| 139 | mkdir -p $(INSTALL_SOCKET_SHARE) | 190 | mkdir -p $(INSTALL_SOCKET_SHARE) |
| 140 | $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE) | 191 | $(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE) |
| 141 | mkdir -p $(INSTALL_SOCKET_LIB) | 192 | mkdir -p $(INSTALL_SOCKET_LIB) |
| 142 | $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT) | 193 | $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(SO) |
| 143 | mkdir -p $(INSTALL_MIME_LIB) | 194 | mkdir -p $(INSTALL_MIME_LIB) |
| 144 | $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT) | 195 | $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO) |
| 145 | 196 | ||
| 146 | local: | 197 | local: |
| 147 | $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. | 198 | $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. |
| @@ -155,24 +206,24 @@ clean: | |||
| 155 | #------ | 206 | #------ |
| 156 | # List of dependencies | 207 | # List of dependencies |
| 157 | # | 208 | # |
| 158 | auxiliar.o: auxiliar.c auxiliar.h | 209 | auxiliar.$(O): auxiliar.c auxiliar.h |
| 159 | buffer.o: buffer.c buffer.h io.h timeout.h | 210 | buffer.$(O): buffer.c buffer.h io.h timeout.h |
| 160 | except.o: except.c except.h | 211 | except.$(O): except.c except.h |
| 161 | inet.o: inet.c inet.h socket.h io.h timeout.h usocket.h | 212 | inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h |
| 162 | io.o: io.c io.h timeout.h | 213 | io.$(O): io.c io.h timeout.h |
| 163 | luasocket.o: luasocket.c luasocket.h auxiliar.h except.h \ | 214 | luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \ |
| 164 | timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \ | 215 | timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \ |
| 165 | udp.h select.h | 216 | udp.h select.h |
| 166 | mime.o: mime.c mime.h | 217 | mime.$(O): mime.c mime.h |
| 167 | options.o: options.c auxiliar.h options.h socket.h io.h \ | 218 | options.$(O): options.c auxiliar.h options.h socket.h io.h \ |
| 168 | timeout.h usocket.h inet.h | 219 | timeout.h usocket.h inet.h |
| 169 | select.o: select.c socket.h io.h timeout.h usocket.h select.h | 220 | select.$(O): select.c socket.h io.h timeout.h usocket.h select.h |
| 170 | tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | 221 | tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ |
| 171 | inet.h options.h tcp.h buffer.h | 222 | inet.h options.h tcp.h buffer.h |
| 172 | timeout.o: timeout.c auxiliar.h timeout.h | 223 | timeout.$(O): timeout.c auxiliar.h timeout.h |
| 173 | udp.o: udp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | 224 | udp.$(O): udp.c auxiliar.h socket.h io.h timeout.h usocket.h \ |
| 174 | inet.h options.h udp.h | 225 | inet.h options.h udp.h |
| 175 | unix.o: unix.c auxiliar.h socket.h io.h timeout.h usocket.h \ | 226 | unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \ |
| 176 | options.h unix.h buffer.h | 227 | options.h unix.h buffer.h |
| 177 | usocket.o: usocket.c socket.h io.h timeout.h usocket.h | 228 | usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h |
| 178 | wsocket.o: wsocket.c socket.h io.h timeout.h usocket.h | 229 | wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h |
diff --git a/src/mbox.lua b/src/mbox.lua index ce6537c..b7d4a2a 100644 --- a/src/mbox.lua +++ b/src/mbox.lua | |||
| @@ -5,10 +5,10 @@ mbox = Public | |||
| 5 | function Public.split_message(message_s) | 5 | function Public.split_message(message_s) |
| 6 | local message = {} | 6 | local message = {} |
| 7 | message_s = string.gsub(message_s, "\r\n", "\n") | 7 | message_s = string.gsub(message_s, "\r\n", "\n") |
| 8 | string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end) | 8 | string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end) |
| 9 | string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end) | 9 | string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end) |
| 10 | if not message.body then | 10 | if not message.body then |
| 11 | string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) | 11 | string.gsub(message_s, "^\n(.*)", function (b) message.body = b end) |
| 12 | end | 12 | end |
| 13 | if not message.headers and not message.body then | 13 | if not message.headers and not message.body then |
| 14 | message.headers = message_s | 14 | message.headers = message_s |
| @@ -54,30 +54,30 @@ function Public.parse_from(from) | |||
| 54 | name = name or "" | 54 | name = name or "" |
| 55 | address = address or "" | 55 | address = address or "" |
| 56 | if name == "" then name = address end | 56 | if name == "" then name = address end |
| 57 | name = string.gsub(name, '"', "") | 57 | name = string.gsub(name, '"', "") |
| 58 | return name, address | 58 | return name, address |
| 59 | end | 59 | end |
| 60 | 60 | ||
| 61 | function Public.split_mbox(mbox_s) | 61 | function Public.split_mbox(mbox_s) |
| 62 | mbox = {} | 62 | mbox = {} |
| 63 | mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" | 63 | mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" |
| 64 | local nj, i, j = 1, 1, 1 | 64 | local nj, i, j = 1, 1, 1 |
| 65 | while 1 do | 65 | while 1 do |
| 66 | i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) | 66 | i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) |
| 67 | if not i then break end | 67 | if not i then break end |
| 68 | local message = string.sub(mbox_s, j, i-1) | 68 | local message = string.sub(mbox_s, j, i-1) |
| 69 | table.insert(mbox, message) | 69 | table.insert(mbox, message) |
| 70 | j = nj+1 | 70 | j = nj+1 |
| 71 | end | 71 | end |
| 72 | return mbox | 72 | return mbox |
| 73 | end | 73 | end |
| 74 | 74 | ||
| 75 | function Public.parse(mbox_s) | 75 | function Public.parse(mbox_s) |
| 76 | local mbox = Public.split_mbox(mbox_s) | 76 | local mbox = Public.split_mbox(mbox_s) |
| 77 | for i = 1, table.getn(mbox) do | 77 | for i = 1, table.getn(mbox) do |
| 78 | mbox[i] = Public.parse_message(mbox[i]) | 78 | mbox[i] = Public.parse_message(mbox[i]) |
| 79 | end | 79 | end |
| 80 | return mbox | 80 | return mbox |
| 81 | end | 81 | end |
| 82 | 82 | ||
| 83 | function Public.parse_message(message_s) | 83 | function Public.parse_message(message_s) |
| @@ -106,7 +106,7 @@ end | |||
| 106 | -- closes the underlying c | 106 | -- closes the underlying c |
| 107 | function metat.__index:close() | 107 | function metat.__index:close() |
| 108 | self.c:close() | 108 | self.c:close() |
| 109 | return 1 | 109 | return 1 |
| 110 | end | 110 | end |
| 111 | 111 | ||
| 112 | -- connect with server and return c object | 112 | -- connect with server and return c object |
diff --git a/src/url.lua b/src/url.lua index 18e5ab2..7623557 100644 --- a/src/url.lua +++ b/src/url.lua | |||
| @@ -40,25 +40,25 @@ end | |||
| 40 | -- escaped representation of string binary | 40 | -- escaped representation of string binary |
| 41 | ----------------------------------------------------------------------------- | 41 | ----------------------------------------------------------------------------- |
| 42 | local function make_set(t) | 42 | local function make_set(t) |
| 43 | local s = {} | 43 | local s = {} |
| 44 | for i,v in base.ipairs(t) do | 44 | for i,v in base.ipairs(t) do |
| 45 | s[t[i]] = 1 | 45 | s[t[i]] = 1 |
| 46 | end | 46 | end |
| 47 | return s | 47 | return s |
| 48 | end | 48 | end |
| 49 | 49 | ||
| 50 | -- these are allowed withing a path segment, along with alphanum | 50 | -- these are allowed withing a path segment, along with alphanum |
| 51 | -- other characters must be escaped | 51 | -- other characters must be escaped |
| 52 | local segment_set = make_set { | 52 | local segment_set = make_set { |
| 53 | "-", "_", ".", "!", "~", "*", "'", "(", | 53 | "-", "_", ".", "!", "~", "*", "'", "(", |
| 54 | ")", ":", "@", "&", "=", "+", "$", ",", | 54 | ")", ":", "@", "&", "=", "+", "$", ",", |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | local function protect_segment(s) | 57 | local function protect_segment(s) |
| 58 | return string.gsub(s, "([^A-Za-z0-9_])", function (c) | 58 | return string.gsub(s, "([^A-Za-z0-9_])", function (c) |
| 59 | if segment_set[c] then return c | 59 | if segment_set[c] then return c |
| 60 | else return string.format("%%%02x", string.byte(c)) end | 60 | else return string.format("%%%02x", string.byte(c)) end |
| 61 | end) | 61 | end) |
| 62 | end | 62 | end |
| 63 | 63 | ||
| 64 | ----------------------------------------------------------------------------- | 64 | ----------------------------------------------------------------------------- |
| @@ -182,20 +182,26 @@ function build(parsed) | |||
| 182 | local url = build_path(ppath) | 182 | local url = build_path(ppath) |
| 183 | if parsed.params then url = url .. ";" .. parsed.params end | 183 | if parsed.params then url = url .. ";" .. parsed.params end |
| 184 | if parsed.query then url = url .. "?" .. parsed.query end | 184 | if parsed.query then url = url .. "?" .. parsed.query end |
| 185 | local authority = parsed.authority | 185 | local authority = parsed.authority |
| 186 | if parsed.host then | 186 | if parsed.host then |
| 187 | authority = parsed.host | 187 | authority = parsed.host |
| 188 | if parsed.port then authority = authority .. ":" .. parsed.port end | 188 | if parsed.port then authority = authority .. ":" .. parsed.port end |
| 189 | local userinfo = parsed.userinfo | 189 | local userinfo = parsed.userinfo |
| 190 | if parsed.user then | 190 | if parsed.user then |
| 191 | userinfo = parsed.user | 191 | userinfo = parsed.user |
| 192 | if parsed.password then | 192 | if parsed.password then |
| 193 | userinfo = userinfo .. ":" .. parsed.password | 193 | userinfo = userinfo .. ":" .. parsed.password |
| 194 | end | 194 | end |
| 195 | end | 195 | end |
| 196 | if userinfo then authority = userinfo .. "@" .. authority end | 196 | if userinfo then authority = userinfo .. "@" .. authority end |
| 197 | end | 197 | end |
| 198 | if authority then url = "//" .. authority .. url end | 198 | if authority then |
| 199 | if string.sub(url, 1, 1) == "/" then | ||
| 200 | url = "//" .. authority .. url | ||
| 201 | else | ||
| 202 | url = "//" .. authority .. "/" .. url | ||
| 203 | end | ||
| 204 | end | ||
| 199 | if parsed.scheme then url = parsed.scheme .. ":" .. url end | 205 | if parsed.scheme then url = parsed.scheme .. ":" .. url end |
| 200 | if parsed.fragment then url = url .. "#" .. parsed.fragment end | 206 | if parsed.fragment then url = url .. "#" .. parsed.fragment end |
| 201 | -- url = string.gsub(url, "%s", "") | 207 | -- url = string.gsub(url, "%s", "") |
| @@ -211,8 +217,8 @@ end | |||
| 211 | -- corresponding absolute url | 217 | -- corresponding absolute url |
| 212 | ----------------------------------------------------------------------------- | 218 | ----------------------------------------------------------------------------- |
| 213 | function absolute(base_url, relative_url) | 219 | function absolute(base_url, relative_url) |
| 220 | local base_parsed = base_url | ||
| 214 | if base.type(base_url) == "table" then | 221 | if base.type(base_url) == "table" then |
| 215 | base_parsed = base_url | ||
| 216 | base_url = build(base_parsed) | 222 | base_url = build(base_parsed) |
| 217 | else | 223 | else |
| 218 | base_parsed = parse(base_url) | 224 | base_parsed = parse(base_url) |
| @@ -250,16 +256,16 @@ end | |||
| 250 | -- segment: a table with one entry per segment | 256 | -- segment: a table with one entry per segment |
| 251 | ----------------------------------------------------------------------------- | 257 | ----------------------------------------------------------------------------- |
| 252 | function parse_path(path) | 258 | function parse_path(path) |
| 253 | local parsed = {} | 259 | local parsed = {} |
| 254 | path = path or "" | 260 | path = path or "" |
| 255 | --path = string.gsub(path, "%s", "") | 261 | --path = string.gsub(path, "%s", "") |
| 256 | string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) | 262 | string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) |
| 257 | for i = 1, table.getn(parsed) do | 263 | for i = 1, table.getn(parsed) do |
| 258 | parsed[i] = unescape(parsed[i]) | 264 | parsed[i] = unescape(parsed[i]) |
| 259 | end | 265 | end |
| 260 | if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end | 266 | if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end |
| 261 | if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end | 267 | if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end |
| 262 | return parsed | 268 | return parsed |
| 263 | end | 269 | end |
| 264 | 270 | ||
| 265 | ----------------------------------------------------------------------------- | 271 | ----------------------------------------------------------------------------- |
| @@ -271,27 +277,27 @@ end | |||
| 271 | -- path: corresponding path stringing | 277 | -- path: corresponding path stringing |
| 272 | ----------------------------------------------------------------------------- | 278 | ----------------------------------------------------------------------------- |
| 273 | function build_path(parsed, unsafe) | 279 | function build_path(parsed, unsafe) |
| 274 | local path = "" | 280 | local path = "" |
| 275 | local n = table.getn(parsed) | 281 | local n = table.getn(parsed) |
| 276 | if unsafe then | 282 | if unsafe then |
| 277 | for i = 1, n-1 do | 283 | for i = 1, n-1 do |
| 278 | path = path .. parsed[i] | 284 | path = path .. parsed[i] |
| 279 | path = path .. "/" | 285 | path = path .. "/" |
| 280 | end | 286 | end |
| 281 | if n > 0 then | 287 | if n > 0 then |
| 282 | path = path .. parsed[n] | 288 | path = path .. parsed[n] |
| 283 | if parsed.is_directory then path = path .. "/" end | 289 | if parsed.is_directory then path = path .. "/" end |
| 284 | end | 290 | end |
| 285 | else | 291 | else |
| 286 | for i = 1, n-1 do | 292 | for i = 1, n-1 do |
| 287 | path = path .. protect_segment(parsed[i]) | 293 | path = path .. protect_segment(parsed[i]) |
| 288 | path = path .. "/" | 294 | path = path .. "/" |
| 289 | end | 295 | end |
| 290 | if n > 0 then | 296 | if n > 0 then |
| 291 | path = path .. protect_segment(parsed[n]) | 297 | path = path .. protect_segment(parsed[n]) |
| 292 | if parsed.is_directory then path = path .. "/" end | 298 | if parsed.is_directory then path = path .. "/" end |
| 293 | end | 299 | end |
| 294 | end | 300 | end |
| 295 | if parsed.is_absolute then path = "/" .. path end | 301 | if parsed.is_absolute then path = "/" .. path end |
| 296 | return path | 302 | return path |
| 297 | end | 303 | end |
diff --git a/src/usocket.c b/src/usocket.c index 2c30b9a..1ba1043 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
| @@ -30,9 +30,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
| 30 | pfd.revents = 0; | 30 | pfd.revents = 0; |
| 31 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | 31 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ |
| 32 | do { | 32 | do { |
| 33 | int t = (int)(timeout_getretry(tm)*1e3); | 33 | int t = (int)(timeout_getretry(tm)*1e3); |
| 34 | ret = poll(&pfd, 1, t >= 0? t: -1); | 34 | ret = poll(&pfd, 1, t >= 0? t: -1); |
| 35 | } while (ret == -1 && errno == EINTR); | 35 | } while (ret == -1 && errno == EINTR); |
| 36 | if (ret == -1) return errno; | 36 | if (ret == -1) return errno; |
| 37 | if (ret == 0) return IO_TIMEOUT; | 37 | if (ret == 0) return IO_TIMEOUT; |
| 38 | if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; | 38 | if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; |
diff --git a/src/wsocket.c b/src/wsocket.c index e247777..2d07904 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
| @@ -54,7 +54,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
| 54 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | 54 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ |
| 55 | if (sw & WAITFD_R) { | 55 | if (sw & WAITFD_R) { |
| 56 | FD_ZERO(&rfds); | 56 | FD_ZERO(&rfds); |
| 57 | FD_SET(*ps, &rfds); | 57 | FD_SET(*ps, &rfds); |
| 58 | rp = &rfds; | 58 | rp = &rfds; |
| 59 | } | 59 | } |
| 60 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | 60 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } |
| @@ -207,7 +207,7 @@ int socket_send(p_socket ps, const char *data, size_t count, | |||
| 207 | /* loop until we send something or we give up on error */ | 207 | /* loop until we send something or we give up on error */ |
| 208 | for ( ;; ) { | 208 | for ( ;; ) { |
| 209 | /* try to send something */ | 209 | /* try to send something */ |
| 210 | int put = send(*ps, data, (int) count, 0); | 210 | int put = send(*ps, data, (int) count, 0); |
| 211 | /* if we sent something, we are done */ | 211 | /* if we sent something, we are done */ |
| 212 | if (put > 0) { | 212 | if (put > 0) { |
| 213 | *sent = put; | 213 | *sent = put; |
| @@ -346,8 +346,8 @@ const char *socket_strerror(int err) { | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | const char *socket_ioerror(p_socket ps, int err) { | 348 | const char *socket_ioerror(p_socket ps, int err) { |
| 349 | (void) ps; | 349 | (void) ps; |
| 350 | return socket_strerror(err); | 350 | return socket_strerror(err); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | static const char *wstrerror(int err) { | 353 | static const char *wstrerror(int err) { |
diff --git a/test/ftptest.lua b/test/ftptest.lua index f35e16f..fb13326 100644 --- a/test/ftptest.lua +++ b/test/ftptest.lua | |||
| @@ -82,10 +82,10 @@ print("ok") | |||
| 82 | io.write("testing parameter overriding: ") | 82 | io.write("testing parameter overriding: ") |
| 83 | local back = {} | 83 | local back = {} |
| 84 | ret, err = ftp.get{ | 84 | ret, err = ftp.get{ |
| 85 | url = "//stupid:mistake@" .. host .. "/index.html", | 85 | url = "//stupid:mistake@" .. host .. "/index.html", |
| 86 | user = "luasocket", | 86 | user = "luasocket", |
| 87 | password = "pedrovian", | 87 | password = "pedrovian", |
| 88 | type = "i", | 88 | type = "i", |
| 89 | sink = ltn12.sink.table(back) | 89 | sink = ltn12.sink.table(back) |
| 90 | } | 90 | } |
| 91 | assert(ret and not err and table.concat(back) == index, err) | 91 | assert(ret and not err and table.concat(back) == index, err) |
diff --git a/test/httptest.lua b/test/httptest.lua index 9d50a14..614acf3 100644 --- a/test/httptest.lua +++ b/test/httptest.lua | |||
| @@ -34,28 +34,28 @@ index_file = "index.html" | |||
| 34 | index = readfile(index_file) | 34 | index = readfile(index_file) |
| 35 | 35 | ||
| 36 | local check_result = function(response, expect, ignore) | 36 | local check_result = function(response, expect, ignore) |
| 37 | for i,v in pairs(response) do | 37 | for i,v in pairs(response) do |
| 38 | if not ignore[i] then | 38 | if not ignore[i] then |
| 39 | if v ~= expect[i] then | 39 | if v ~= expect[i] then |
| 40 | local f = io.open("err", "w") | 40 | local f = io.open("err", "w") |
| 41 | f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i])) | 41 | f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i])) |
| 42 | f:close() | 42 | f:close() |
| 43 | fail(i .. " differs!") | 43 | fail(i .. " differs!") |
| 44 | end | 44 | end |
| 45 | end | 45 | end |
| 46 | end | 46 | end |
| 47 | for i,v in pairs(expect) do | 47 | for i,v in pairs(expect) do |
| 48 | if not ignore[i] then | 48 | if not ignore[i] then |
| 49 | if v ~= response[i] then | 49 | if v ~= response[i] then |
| 50 | local f = io.open("err", "w") | 50 | local f = io.open("err", "w") |
| 51 | f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v)) | 51 | f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v)) |
| 52 | v = string.sub(type(v) == "string" and v or "", 1, 70) | 52 | v = string.sub(type(v) == "string" and v or "", 1, 70) |
| 53 | f:close() | 53 | f:close() |
| 54 | fail(i .. " differs!") | 54 | fail(i .. " differs!") |
| 55 | end | 55 | end |
| 56 | end | 56 | end |
| 57 | end | 57 | end |
| 58 | print("ok") | 58 | print("ok") |
| 59 | end | 59 | end |
| 60 | 60 | ||
| 61 | local check_request = function(request, expect, ignore) | 61 | local check_request = function(request, expect, ignore) |
| @@ -63,7 +63,7 @@ local check_request = function(request, expect, ignore) | |||
| 63 | if not request.sink then request.sink, t = ltn12.sink.table() end | 63 | if not request.sink then request.sink, t = ltn12.sink.table() end |
| 64 | request.source = request.source or | 64 | request.source = request.source or |
| 65 | (request.body and ltn12.source.string(request.body)) | 65 | (request.body and ltn12.source.string(request.body)) |
| 66 | local response = {} | 66 | local response = {} |
| 67 | response.code, response.headers, response.status = | 67 | response.code, response.headers, response.status = |
| 68 | socket.skip(1, http.request(request)) | 68 | socket.skip(1, http.request(request)) |
| 69 | if t and table.getn(t) > 0 then response.body = table.concat(t) end | 69 | if t and table.getn(t) > 0 then response.body = table.concat(t) end |
| @@ -90,15 +90,15 @@ else fail("failed!") end | |||
| 90 | ------------------------------------------------------------------------ | 90 | ------------------------------------------------------------------------ |
| 91 | io.write("testing document retrieval: ") | 91 | io.write("testing document retrieval: ") |
| 92 | request = { | 92 | request = { |
| 93 | url = "http://" .. host .. prefix .. "/index.html" | 93 | url = "http://" .. host .. prefix .. "/index.html" |
| 94 | } | 94 | } |
| 95 | expect = { | 95 | expect = { |
| 96 | body = index, | 96 | body = index, |
| 97 | code = 200 | 97 | code = 200 |
| 98 | } | 98 | } |
| 99 | ignore = { | 99 | ignore = { |
| 100 | status = 1, | 100 | status = 1, |
| 101 | headers = 1 | 101 | headers = 1 |
| 102 | } | 102 | } |
| 103 | check_request(request, expect, ignore) | 103 | check_request(request, expect, ignore) |
| 104 | 104 | ||
| @@ -111,9 +111,9 @@ expect = { | |||
| 111 | code = 302 | 111 | code = 302 |
| 112 | } | 112 | } |
| 113 | ignore = { | 113 | ignore = { |
| 114 | status = 1, | 114 | status = 1, |
| 115 | headers = 1, | 115 | headers = 1, |
| 116 | body = 1 | 116 | body = 1 |
| 117 | } | 117 | } |
| 118 | check_request(request, expect, ignore) | 118 | check_request(request, expect, ignore) |
| 119 | 119 | ||
| @@ -144,19 +144,19 @@ check_request(request, expect, ignore) | |||
| 144 | io.write("testing post method: ") | 144 | io.write("testing post method: ") |
| 145 | -- wanted to test chunked post, but apache doesn't support it... | 145 | -- wanted to test chunked post, but apache doesn't support it... |
| 146 | request = { | 146 | request = { |
| 147 | url = "http://" .. host .. cgiprefix .. "/cat", | 147 | url = "http://" .. host .. cgiprefix .. "/cat", |
| 148 | method = "POST", | 148 | method = "POST", |
| 149 | body = index, | 149 | body = index, |
| 150 | -- remove content-length header to send chunked body | 150 | -- remove content-length header to send chunked body |
| 151 | headers = { ["content-length"] = string.len(index) } | 151 | headers = { ["content-length"] = string.len(index) } |
| 152 | } | 152 | } |
| 153 | expect = { | 153 | expect = { |
| 154 | body = index, | 154 | body = index, |
| 155 | code = 200 | 155 | code = 200 |
| 156 | } | 156 | } |
| 157 | ignore = { | 157 | ignore = { |
| 158 | status = 1, | 158 | status = 1, |
| 159 | headers = 1 | 159 | headers = 1 |
| 160 | } | 160 | } |
| 161 | check_request(request, expect, ignore) | 161 | check_request(request, expect, ignore) |
| 162 | 162 | ||
| @@ -164,19 +164,19 @@ check_request(request, expect, ignore) | |||
| 164 | --[[ | 164 | --[[ |
| 165 | io.write("testing proxy with post method: ") | 165 | io.write("testing proxy with post method: ") |
| 166 | request = { | 166 | request = { |
| 167 | url = "http://" .. host .. cgiprefix .. "/cat", | 167 | url = "http://" .. host .. cgiprefix .. "/cat", |
| 168 | method = "POST", | 168 | method = "POST", |
| 169 | body = index, | 169 | body = index, |
| 170 | headers = { ["content-length"] = string.len(index) }, | 170 | headers = { ["content-length"] = string.len(index) }, |
| 171 | proxy= proxy | 171 | proxy= proxy |
| 172 | } | 172 | } |
| 173 | expect = { | 173 | expect = { |
| 174 | body = index, | 174 | body = index, |
| 175 | code = 200 | 175 | code = 200 |
| 176 | } | 176 | } |
| 177 | ignore = { | 177 | ignore = { |
| 178 | status = 1, | 178 | status = 1, |
| 179 | headers = 1 | 179 | headers = 1 |
| 180 | } | 180 | } |
| 181 | check_request(request, expect, ignore) | 181 | check_request(request, expect, ignore) |
| 182 | ]] | 182 | ]] |
| @@ -190,18 +190,18 @@ print("ok") | |||
| 190 | ------------------------------------------------------------------------ | 190 | ------------------------------------------------------------------------ |
| 191 | io.write("testing ltn12.(sink|source).file: ") | 191 | io.write("testing ltn12.(sink|source).file: ") |
| 192 | request = { | 192 | request = { |
| 193 | url = "http://" .. host .. cgiprefix .. "/cat", | 193 | url = "http://" .. host .. cgiprefix .. "/cat", |
| 194 | method = "POST", | 194 | method = "POST", |
| 195 | source = ltn12.source.file(io.open(index_file, "rb")), | 195 | source = ltn12.source.file(io.open(index_file, "rb")), |
| 196 | sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")), | 196 | sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")), |
| 197 | headers = { ["content-length"] = string.len(index) } | 197 | headers = { ["content-length"] = string.len(index) } |
| 198 | } | 198 | } |
| 199 | expect = { | 199 | expect = { |
| 200 | code = 200 | 200 | code = 200 |
| 201 | } | 201 | } |
| 202 | ignore = { | 202 | ignore = { |
| 203 | status = 1, | 203 | status = 1, |
| 204 | headers = 1 | 204 | headers = 1 |
| 205 | } | 205 | } |
| 206 | check_request(request, expect, ignore) | 206 | check_request(request, expect, ignore) |
| 207 | back = readfile(index_file .. "-back") | 207 | back = readfile(index_file .. "-back") |
| @@ -231,19 +231,19 @@ local sink = ltn12.sink.chain( | |||
| 231 | ) | 231 | ) |
| 232 | 232 | ||
| 233 | request = { | 233 | request = { |
| 234 | url = "http://" .. host .. cgiprefix .. "/cat", | 234 | url = "http://" .. host .. cgiprefix .. "/cat", |
| 235 | method = "POST", | 235 | method = "POST", |
| 236 | source = source, | 236 | source = source, |
| 237 | sink = sink, | 237 | sink = sink, |
| 238 | headers = { ["content-length"] = b64length(string.len(index)) } | 238 | headers = { ["content-length"] = b64length(string.len(index)) } |
| 239 | } | 239 | } |
| 240 | expect = { | 240 | expect = { |
| 241 | code = 200 | 241 | code = 200 |
| 242 | } | 242 | } |
| 243 | ignore = { | 243 | ignore = { |
| 244 | body_cb = 1, | 244 | body_cb = 1, |
| 245 | status = 1, | 245 | status = 1, |
| 246 | headers = 1 | 246 | headers = 1 |
| 247 | } | 247 | } |
| 248 | check_request(request, expect, ignore) | 248 | check_request(request, expect, ignore) |
| 249 | back = readfile(index_file .. "-back") | 249 | back = readfile(index_file .. "-back") |
| @@ -253,15 +253,15 @@ os.remove(index_file .. "-back") | |||
| 253 | ------------------------------------------------------------------------ | 253 | ------------------------------------------------------------------------ |
| 254 | io.write("testing http redirection: ") | 254 | io.write("testing http redirection: ") |
| 255 | request = { | 255 | request = { |
| 256 | url = "http://" .. host .. prefix | 256 | url = "http://" .. host .. prefix |
| 257 | } | 257 | } |
| 258 | expect = { | 258 | expect = { |
| 259 | body = index, | 259 | body = index, |
| 260 | code = 200 | 260 | code = 200 |
| 261 | } | 261 | } |
| 262 | ignore = { | 262 | ignore = { |
| 263 | status = 1, | 263 | status = 1, |
| 264 | headers = 1 | 264 | headers = 1 |
| 265 | } | 265 | } |
| 266 | check_request(request, expect, ignore) | 266 | check_request(request, expect, ignore) |
| 267 | 267 | ||
| @@ -269,16 +269,16 @@ check_request(request, expect, ignore) | |||
| 269 | --[[ | 269 | --[[ |
| 270 | io.write("testing proxy with redirection: ") | 270 | io.write("testing proxy with redirection: ") |
| 271 | request = { | 271 | request = { |
| 272 | url = "http://" .. host .. prefix, | 272 | url = "http://" .. host .. prefix, |
| 273 | proxy = proxy | 273 | proxy = proxy |
| 274 | } | 274 | } |
| 275 | expect = { | 275 | expect = { |
| 276 | body = index, | 276 | body = index, |
| 277 | code = 200 | 277 | code = 200 |
| 278 | } | 278 | } |
| 279 | ignore = { | 279 | ignore = { |
| 280 | status = 1, | 280 | status = 1, |
| 281 | headers = 1 | 281 | headers = 1 |
| 282 | } | 282 | } |
| 283 | check_request(request, expect, ignore) | 283 | check_request(request, expect, ignore) |
| 284 | ]] | 284 | ]] |
| @@ -293,104 +293,104 @@ expect = { | |||
| 293 | } | 293 | } |
| 294 | ignore = { | 294 | ignore = { |
| 295 | body = 1, | 295 | body = 1, |
| 296 | status = 1, | 296 | status = 1, |
| 297 | headers = 1 | 297 | headers = 1 |
| 298 | } | 298 | } |
| 299 | check_request(request, expect, ignore) | 299 | check_request(request, expect, ignore) |
| 300 | 300 | ||
| 301 | ------------------------------------------------------------------------ | 301 | ------------------------------------------------------------------------ |
| 302 | io.write("testing http redirection failure: ") | 302 | io.write("testing http redirection failure: ") |
| 303 | request = { | 303 | request = { |
| 304 | url = "http://" .. host .. prefix, | 304 | url = "http://" .. host .. prefix, |
| 305 | redirect = false | 305 | redirect = false |
| 306 | } | 306 | } |
| 307 | expect = { | 307 | expect = { |
| 308 | code = 301 | 308 | code = 301 |
| 309 | } | 309 | } |
| 310 | ignore = { | 310 | ignore = { |
| 311 | body = 1, | 311 | body = 1, |
| 312 | status = 1, | 312 | status = 1, |
| 313 | headers = 1 | 313 | headers = 1 |
| 314 | } | 314 | } |
| 315 | check_request(request, expect, ignore) | 315 | check_request(request, expect, ignore) |
| 316 | 316 | ||
| 317 | ------------------------------------------------------------------------ | 317 | ------------------------------------------------------------------------ |
| 318 | io.write("testing document not found: ") | 318 | io.write("testing document not found: ") |
| 319 | request = { | 319 | request = { |
| 320 | url = "http://" .. host .. "/wrongdocument.html" | 320 | url = "http://" .. host .. "/wrongdocument.html" |
| 321 | } | 321 | } |
| 322 | expect = { | 322 | expect = { |
| 323 | code = 404 | 323 | code = 404 |
| 324 | } | 324 | } |
| 325 | ignore = { | 325 | ignore = { |
| 326 | body = 1, | 326 | body = 1, |
| 327 | status = 1, | 327 | status = 1, |
| 328 | headers = 1 | 328 | headers = 1 |
| 329 | } | 329 | } |
| 330 | check_request(request, expect, ignore) | 330 | check_request(request, expect, ignore) |
| 331 | 331 | ||
| 332 | ------------------------------------------------------------------------ | 332 | ------------------------------------------------------------------------ |
| 333 | io.write("testing auth failure: ") | 333 | io.write("testing auth failure: ") |
| 334 | request = { | 334 | request = { |
| 335 | url = "http://" .. host .. prefix .. "/auth/index.html" | 335 | url = "http://" .. host .. prefix .. "/auth/index.html" |
| 336 | } | 336 | } |
| 337 | expect = { | 337 | expect = { |
| 338 | code = 401 | 338 | code = 401 |
| 339 | } | 339 | } |
| 340 | ignore = { | 340 | ignore = { |
| 341 | body = 1, | 341 | body = 1, |
| 342 | status = 1, | 342 | status = 1, |
| 343 | headers = 1 | 343 | headers = 1 |
| 344 | } | 344 | } |
| 345 | check_request(request, expect, ignore) | 345 | check_request(request, expect, ignore) |
| 346 | 346 | ||
| 347 | ------------------------------------------------------------------------ | 347 | ------------------------------------------------------------------------ |
| 348 | io.write("testing manual basic auth: ") | 348 | io.write("testing manual basic auth: ") |
| 349 | request = { | 349 | request = { |
| 350 | url = "http://" .. host .. prefix .. "/auth/index.html", | 350 | url = "http://" .. host .. prefix .. "/auth/index.html", |
| 351 | headers = { | 351 | headers = { |
| 352 | authorization = "Basic " .. (mime.b64("luasocket:password")) | 352 | authorization = "Basic " .. (mime.b64("luasocket:password")) |
| 353 | } | 353 | } |
| 354 | } | 354 | } |
| 355 | expect = { | 355 | expect = { |
| 356 | code = 200, | 356 | code = 200, |
| 357 | body = index | 357 | body = index |
| 358 | } | 358 | } |
| 359 | ignore = { | 359 | ignore = { |
| 360 | status = 1, | 360 | status = 1, |
| 361 | headers = 1 | 361 | headers = 1 |
| 362 | } | 362 | } |
| 363 | check_request(request, expect, ignore) | 363 | check_request(request, expect, ignore) |
| 364 | 364 | ||
| 365 | ------------------------------------------------------------------------ | 365 | ------------------------------------------------------------------------ |
| 366 | io.write("testing automatic basic auth: ") | 366 | io.write("testing automatic basic auth: ") |
| 367 | request = { | 367 | request = { |
| 368 | url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html" | 368 | url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html" |
| 369 | } | 369 | } |
| 370 | expect = { | 370 | expect = { |
| 371 | code = 200, | 371 | code = 200, |
| 372 | body = index | 372 | body = index |
| 373 | } | 373 | } |
| 374 | ignore = { | 374 | ignore = { |
| 375 | status = 1, | 375 | status = 1, |
| 376 | headers = 1 | 376 | headers = 1 |
| 377 | } | 377 | } |
| 378 | check_request(request, expect, ignore) | 378 | check_request(request, expect, ignore) |
| 379 | 379 | ||
| 380 | ------------------------------------------------------------------------ | 380 | ------------------------------------------------------------------------ |
| 381 | io.write("testing auth info overriding: ") | 381 | io.write("testing auth info overriding: ") |
| 382 | request = { | 382 | request = { |
| 383 | url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html", | 383 | url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html", |
| 384 | user = "luasocket", | 384 | user = "luasocket", |
| 385 | password = "password" | 385 | password = "password" |
| 386 | } | 386 | } |
| 387 | expect = { | 387 | expect = { |
| 388 | code = 200, | 388 | code = 200, |
| 389 | body = index | 389 | body = index |
| 390 | } | 390 | } |
| 391 | ignore = { | 391 | ignore = { |
| 392 | status = 1, | 392 | status = 1, |
| 393 | headers = 1 | 393 | headers = 1 |
| 394 | } | 394 | } |
| 395 | check_request(request, expect, ignore) | 395 | check_request(request, expect, ignore) |
| 396 | 396 | ||
| @@ -400,12 +400,12 @@ request = { | |||
| 400 | url = "http://" .. host .. cgiprefix .. "/cat-index-html" | 400 | url = "http://" .. host .. cgiprefix .. "/cat-index-html" |
| 401 | } | 401 | } |
| 402 | expect = { | 402 | expect = { |
| 403 | body = index, | 403 | body = index, |
| 404 | code = 200 | 404 | code = 200 |
| 405 | } | 405 | } |
| 406 | ignore = { | 406 | ignore = { |
| 407 | status = 1, | 407 | status = 1, |
| 408 | headers = 1 | 408 | headers = 1 |
| 409 | } | 409 | } |
| 410 | check_request(request, expect, ignore) | 410 | check_request(request, expect, ignore) |
| 411 | 411 | ||
diff --git a/test/smtptest.lua b/test/smtptest.lua index d0c938c..5f0e0e5 100644 --- a/test/smtptest.lua +++ b/test/smtptest.lua | |||
| @@ -19,11 +19,11 @@ local parse = mbox.parse | |||
| 19 | dofile("testsupport.lua") | 19 | dofile("testsupport.lua") |
| 20 | 20 | ||
| 21 | local total = function() | 21 | local total = function() |
| 22 | local t = 0 | 22 | local t = 0 |
| 23 | for i = 1, table.getn(sent) do | 23 | for i = 1, table.getn(sent) do |
| 24 | t = t + sent[i].count | 24 | t = t + sent[i].count |
| 25 | end | 25 | end |
| 26 | return t | 26 | return t |
| 27 | end | 27 | end |
| 28 | 28 | ||
| 29 | local similar = function(s1, s2) | 29 | local similar = function(s1, s2) |
| @@ -39,14 +39,14 @@ local fail = function(s) | |||
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | local readfile = function(name) | 41 | local readfile = function(name) |
| 42 | local f = io.open(name, "r") | 42 | local f = io.open(name, "r") |
| 43 | if not f then | 43 | if not f then |
| 44 | fail("unable to open file!") | 44 | fail("unable to open file!") |
| 45 | return nil | 45 | return nil |
| 46 | end | 46 | end |
| 47 | local s = f:read("*a") | 47 | local s = f:read("*a") |
| 48 | f:close() | 48 | f:close() |
| 49 | return s | 49 | return s |
| 50 | end | 50 | end |
| 51 | 51 | ||
| 52 | local empty = function() | 52 | local empty = function() |
| @@ -62,7 +62,7 @@ end | |||
| 62 | local get = function() | 62 | local get = function() |
| 63 | local s = "" | 63 | local s = "" |
| 64 | for i,v in ipairs(files) do | 64 | for i,v in ipairs(files) do |
| 65 | s = s .. "\n" .. readfile(v) | 65 | s = s .. "\n" .. readfile(v) |
| 66 | end | 66 | end |
| 67 | return s | 67 | return s |
| 68 | end | 68 | end |
| @@ -82,40 +82,40 @@ local check_body = function(sent, got) | |||
| 82 | end | 82 | end |
| 83 | 83 | ||
| 84 | local check = function(sent, m) | 84 | local check = function(sent, m) |
| 85 | io.write("checking ", m.headers.title, ": ") | 85 | io.write("checking ", m.headers.title, ": ") |
| 86 | for i = 1, table.getn(sent) do | 86 | for i = 1, table.getn(sent) do |
| 87 | local s = sent[i] | 87 | local s = sent[i] |
| 88 | if s.title == m.headers.title and s.count > 0 then | 88 | if s.title == m.headers.title and s.count > 0 then |
| 89 | check_headers(s.headers, m.headers) | 89 | check_headers(s.headers, m.headers) |
| 90 | check_body(s.body, m.body) | 90 | check_body(s.body, m.body) |
| 91 | s.count = s.count - 1 | 91 | s.count = s.count - 1 |
| 92 | print("ok") | 92 | print("ok") |
| 93 | return | 93 | return |
| 94 | end | 94 | end |
| 95 | end | 95 | end |
| 96 | fail("not found") | 96 | fail("not found") |
| 97 | end | 97 | end |
| 98 | 98 | ||
| 99 | local insert = function(sent, message) | 99 | local insert = function(sent, message) |
| 100 | if type(message.rcpt) == "table" then | 100 | if type(message.rcpt) == "table" then |
| 101 | message.count = table.getn(message.rcpt) | 101 | message.count = table.getn(message.rcpt) |
| 102 | else message.count = 1 end | 102 | else message.count = 1 end |
| 103 | message.headers = message.headers or {} | 103 | message.headers = message.headers or {} |
| 104 | message.headers.title = message.title | 104 | message.headers.title = message.title |
| 105 | table.insert(sent, message) | 105 | table.insert(sent, message) |
| 106 | end | 106 | end |
| 107 | 107 | ||
| 108 | local mark = function() | 108 | local mark = function() |
| 109 | local time = socket.time() | 109 | local time = socket.time() |
| 110 | return { time = time } | 110 | return { time = time } |
| 111 | end | 111 | end |
| 112 | 112 | ||
| 113 | local wait = function(sentinel, n) | 113 | local wait = function(sentinel, n) |
| 114 | local to | 114 | local to |
| 115 | io.write("waiting for ", n, " messages: ") | 115 | io.write("waiting for ", n, " messages: ") |
| 116 | while 1 do | 116 | while 1 do |
| 117 | local mbox = parse(get()) | 117 | local mbox = parse(get()) |
| 118 | if n == table.getn(mbox) then break end | 118 | if n == table.getn(mbox) then break end |
| 119 | if socket.time() - sentinel.time > 50 then | 119 | if socket.time() - sentinel.time > 50 then |
| 120 | to = 1 | 120 | to = 1 |
| 121 | break | 121 | break |
| @@ -124,8 +124,8 @@ local wait = function(sentinel, n) | |||
| 124 | io.write(".") | 124 | io.write(".") |
| 125 | io.stdout:flush() | 125 | io.stdout:flush() |
| 126 | end | 126 | end |
| 127 | if to then fail("timeout") | 127 | if to then fail("timeout") |
| 128 | else print("ok") end | 128 | else print("ok") end |
| 129 | end | 129 | end |
| 130 | 130 | ||
| 131 | local stuffed_body = [[ | 131 | local stuffed_body = [[ |
| @@ -144,21 +144,21 @@ a lot of trouble. | |||
| 144 | insert(sent, { | 144 | insert(sent, { |
| 145 | from = from, | 145 | from = from, |
| 146 | rcpt = { | 146 | rcpt = { |
| 147 | "luasocket@localhost", | 147 | "luasocket@localhost", |
| 148 | "luasock3@dell-diego.cs.princeton.edu", | 148 | "luasock3@dell-diego.cs.princeton.edu", |
| 149 | "luasock1@dell-diego.cs.princeton.edu" | 149 | "luasock1@dell-diego.cs.princeton.edu" |
| 150 | }, | 150 | }, |
| 151 | body = "multiple rcpt body", | 151 | body = "multiple rcpt body", |
| 152 | title = "multiple rcpt", | 152 | title = "multiple rcpt", |
| 153 | }) | 153 | }) |
| 154 | 154 | ||
| 155 | insert(sent, { | 155 | insert(sent, { |
| 156 | from = from, | 156 | from = from, |
| 157 | rcpt = { | 157 | rcpt = { |
| 158 | "luasock2@localhost", | 158 | "luasock2@localhost", |
| 159 | "luasock3", | 159 | "luasock3", |
| 160 | "luasock1" | 160 | "luasock1" |
| 161 | }, | 161 | }, |
| 162 | headers = { | 162 | headers = { |
| 163 | header1 = "header 1", | 163 | header1 = "header 1", |
| 164 | header2 = "header 2", | 164 | header2 = "header 2", |
| @@ -210,24 +210,24 @@ insert(sent, { | |||
| 210 | io.write("testing host not found: ") | 210 | io.write("testing host not found: ") |
| 211 | local c, e = socket.connect("wrong.host", 25) | 211 | local c, e = socket.connect("wrong.host", 25) |
| 212 | local ret, err = socket.smtp.mail{ | 212 | local ret, err = socket.smtp.mail{ |
| 213 | from = from, | 213 | from = from, |
| 214 | rcpt = rcpt, | 214 | rcpt = rcpt, |
| 215 | server = "wrong.host" | 215 | server = "wrong.host" |
| 216 | } | 216 | } |
| 217 | if ret or e ~= err then fail("wrong error message") | 217 | if ret or e ~= err then fail("wrong error message") |
| 218 | else print("ok") end | 218 | else print("ok") end |
| 219 | 219 | ||
| 220 | io.write("testing invalid from: ") | 220 | io.write("testing invalid from: ") |
| 221 | local ret, err = socket.smtp.mail{ | 221 | local ret, err = socket.smtp.mail{ |
| 222 | from = ' " " (( _ * ', | 222 | from = ' " " (( _ * ', |
| 223 | rcpt = rcpt, | 223 | rcpt = rcpt, |
| 224 | } | 224 | } |
| 225 | if ret or not err then fail("wrong error message") | 225 | if ret or not err then fail("wrong error message") |
| 226 | else print(err) end | 226 | else print(err) end |
| 227 | 227 | ||
| 228 | io.write("testing no rcpt: ") | 228 | io.write("testing no rcpt: ") |
| 229 | local ret, err = socket.smtp.mail{ | 229 | local ret, err = socket.smtp.mail{ |
| 230 | from = from, | 230 | from = from, |
| 231 | } | 231 | } |
| 232 | if ret or not err then fail("wrong error message") | 232 | if ret or not err then fail("wrong error message") |
| 233 | else print(err) end | 233 | else print(err) end |
| @@ -252,7 +252,7 @@ local mbox = parse(get()) | |||
| 252 | print(table.getn(mbox) .. " messages found!") | 252 | print(table.getn(mbox) .. " messages found!") |
| 253 | 253 | ||
| 254 | for i = 1, table.getn(mbox) do | 254 | for i = 1, table.getn(mbox) do |
| 255 | check(sent, mbox[i]) | 255 | check(sent, mbox[i]) |
| 256 | end | 256 | end |
| 257 | 257 | ||
| 258 | print("passed all tests") | 258 | print("passed all tests") |
diff --git a/test/testclnt.lua b/test/testclnt.lua index 1f03b10..4c2f211 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua | |||
| @@ -3,15 +3,20 @@ local socket = require"socket" | |||
| 3 | host = host or "localhost" | 3 | host = host or "localhost" |
| 4 | port = port or "8383" | 4 | port = port or "8383" |
| 5 | 5 | ||
| 6 | function pass(...) | 6 | function printf(...) |
| 7 | local s = string.format(unpack(arg)) | 7 | local s = string.format(unpack(arg)) |
| 8 | io.stderr:write(s, "\n") | 8 | io.stderr:write(s) |
| 9 | end | ||
| 10 | |||
| 11 | function pass(...) | ||
| 12 | printf(...) | ||
| 13 | io.stderr:write("\n") | ||
| 9 | end | 14 | end |
| 10 | 15 | ||
| 11 | function fail(...) | 16 | function fail(...) |
| 12 | local s = string.format(unpack(arg)) | 17 | io.stderr:write("ERROR: ") |
| 13 | io.stderr:write("ERROR: ", s, "!\n") | 18 | printf(...) |
| 14 | socket.sleep(3) | 19 | io.stderr:write("!\n") |
| 15 | os.exit() | 20 | os.exit() |
| 16 | end | 21 | end |
| 17 | 22 | ||
| @@ -80,7 +85,6 @@ io.stderr:write("----------------------------------------------\n", | |||
| 80 | start = socket.gettime() | 85 | start = socket.gettime() |
| 81 | 86 | ||
| 82 | function reconnect() | 87 | function reconnect() |
| 83 | io.stderr:write("attempting data connection... ") | ||
| 84 | if data then data:close() end | 88 | if data then data:close() end |
| 85 | remote [[ | 89 | remote [[ |
| 86 | if data then data:close() data = nil end | 90 | if data then data:close() data = nil end |
| @@ -88,12 +92,11 @@ function reconnect() | |||
| 88 | data:setoption("tcp-nodelay", true) | 92 | data:setoption("tcp-nodelay", true) |
| 89 | ]] | 93 | ]] |
| 90 | data, err = socket.connect(host, port) | 94 | data, err = socket.connect(host, port) |
| 91 | if not data then fail(err) | 95 | if not data then fail(err) end |
| 92 | else pass("connected!") end | ||
| 93 | data:setoption("tcp-nodelay", true) | 96 | data:setoption("tcp-nodelay", true) |
| 94 | end | 97 | end |
| 95 | 98 | ||
| 96 | pass("attempting control connection...") | 99 | printf("attempting control connection...") |
| 97 | control, err = socket.connect(host, port) | 100 | control, err = socket.connect(host, port) |
| 98 | if err then fail(err) | 101 | if err then fail(err) |
| 99 | else pass("connected!") end | 102 | else pass("connected!") end |
| @@ -112,6 +115,7 @@ end | |||
| 112 | ------------------------------------------------------------------------ | 115 | ------------------------------------------------------------------------ |
| 113 | function test_mixed(len) | 116 | function test_mixed(len) |
| 114 | reconnect() | 117 | reconnect() |
| 118 | io.stderr:write("length " .. len .. ": ") | ||
| 115 | local inter = math.ceil(len/4) | 119 | local inter = math.ceil(len/4) |
| 116 | local p1 = "unix " .. string.rep("x", inter) .. "line\n" | 120 | local p1 = "unix " .. string.rep("x", inter) .. "line\n" |
| 117 | local p2 = "dos " .. string.rep("y", inter) .. "line\r\n" | 121 | local p2 = "dos " .. string.rep("y", inter) .. "line\r\n" |
| @@ -139,6 +143,7 @@ end | |||
| 139 | ------------------------------------------------------------------------ | 143 | ------------------------------------------------------------------------ |
| 140 | function test_asciiline(len) | 144 | function test_asciiline(len) |
| 141 | reconnect() | 145 | reconnect() |
| 146 | io.stderr:write("length " .. len .. ": ") | ||
| 142 | local str, str10, back, err | 147 | local str, str10, back, err |
| 143 | str = string.rep("x", math.mod(len, 10)) | 148 | str = string.rep("x", math.mod(len, 10)) |
| 144 | str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) | 149 | str10 = string.rep("aZb.c#dAe?", math.floor(len/10)) |
| @@ -156,6 +161,7 @@ end | |||
| 156 | ------------------------------------------------------------------------ | 161 | ------------------------------------------------------------------------ |
| 157 | function test_rawline(len) | 162 | function test_rawline(len) |
| 158 | reconnect() | 163 | reconnect() |
| 164 | io.stderr:write("length " .. len .. ": ") | ||
| 159 | local str, str10, back, err | 165 | local str, str10, back, err |
| 160 | str = string.rep(string.char(47), math.mod(len, 10)) | 166 | str = string.rep(string.char(47), math.mod(len, 10)) |
| 161 | str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), | 167 | str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100), |
| @@ -174,6 +180,7 @@ end | |||
| 174 | ------------------------------------------------------------------------ | 180 | ------------------------------------------------------------------------ |
| 175 | function test_raw(len) | 181 | function test_raw(len) |
| 176 | reconnect() | 182 | reconnect() |
| 183 | io.stderr:write("length " .. len .. ": ") | ||
| 177 | local half = math.floor(len/2) | 184 | local half = math.floor(len/2) |
| 178 | local s1, s2, back, err | 185 | local s1, s2, back, err |
| 179 | s1 = string.rep("x", half) | 186 | s1 = string.rep("x", half) |
| @@ -194,7 +201,7 @@ end | |||
| 194 | function test_totaltimeoutreceive(len, tm, sl) | 201 | function test_totaltimeoutreceive(len, tm, sl) |
| 195 | reconnect() | 202 | reconnect() |
| 196 | local str, err, partial | 203 | local str, err, partial |
| 197 | pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl) | 204 | printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl) |
| 198 | remote (string.format ([[ | 205 | remote (string.format ([[ |
| 199 | data:settimeout(%d) | 206 | data:settimeout(%d) |
| 200 | str = string.rep('a', %d) | 207 | str = string.rep('a', %d) |
| @@ -215,7 +222,7 @@ end | |||
| 215 | function test_totaltimeoutsend(len, tm, sl) | 222 | function test_totaltimeoutsend(len, tm, sl) |
| 216 | reconnect() | 223 | reconnect() |
| 217 | local str, err, total | 224 | local str, err, total |
| 218 | pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl) | 225 | printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl) |
| 219 | remote (string.format ([[ | 226 | remote (string.format ([[ |
| 220 | data:settimeout(%d) | 227 | data:settimeout(%d) |
| 221 | str = data:receive(%d) | 228 | str = data:receive(%d) |
| @@ -235,7 +242,7 @@ end | |||
| 235 | function test_blockingtimeoutreceive(len, tm, sl) | 242 | function test_blockingtimeoutreceive(len, tm, sl) |
| 236 | reconnect() | 243 | reconnect() |
| 237 | local str, err, partial | 244 | local str, err, partial |
| 238 | pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) | 245 | printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl) |
| 239 | remote (string.format ([[ | 246 | remote (string.format ([[ |
| 240 | data:settimeout(%d) | 247 | data:settimeout(%d) |
| 241 | str = string.rep('a', %d) | 248 | str = string.rep('a', %d) |
| @@ -255,7 +262,7 @@ end | |||
| 255 | function test_blockingtimeoutsend(len, tm, sl) | 262 | function test_blockingtimeoutsend(len, tm, sl) |
| 256 | reconnect() | 263 | reconnect() |
| 257 | local str, err, total | 264 | local str, err, total |
| 258 | pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) | 265 | printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl) |
| 259 | remote (string.format ([[ | 266 | remote (string.format ([[ |
| 260 | data:settimeout(%d) | 267 | data:settimeout(%d) |
| 261 | str = data:receive(%d) | 268 | str = data:receive(%d) |
| @@ -273,6 +280,7 @@ end | |||
| 273 | 280 | ||
| 274 | ------------------------------------------------------------------------ | 281 | ------------------------------------------------------------------------ |
| 275 | function empty_connect() | 282 | function empty_connect() |
| 283 | printf("empty connect: ") | ||
| 276 | reconnect() | 284 | reconnect() |
| 277 | if data then data:close() data = nil end | 285 | if data then data:close() data = nil end |
| 278 | remote [[ | 286 | remote [[ |
| @@ -284,7 +292,7 @@ function empty_connect() | |||
| 284 | pass("ok") | 292 | pass("ok") |
| 285 | data = socket.connect(host, port) | 293 | data = socket.connect(host, port) |
| 286 | else | 294 | else |
| 287 | pass("gethostbyname returns localhost on empty string...") | 295 | pass("gethostbyname returns localhost on empty string...") |
| 288 | end | 296 | end |
| 289 | end | 297 | end |
| 290 | 298 | ||
| @@ -311,7 +319,7 @@ function test_closed() | |||
| 311 | local back, partial, err | 319 | local back, partial, err |
| 312 | local str = 'little string' | 320 | local str = 'little string' |
| 313 | reconnect() | 321 | reconnect() |
| 314 | pass("trying read detection") | 322 | printf("trying read detection: ") |
| 315 | remote (string.format ([[ | 323 | remote (string.format ([[ |
| 316 | data:send('%s') | 324 | data:send('%s') |
| 317 | data:close() | 325 | data:close() |
| @@ -324,7 +332,7 @@ function test_closed() | |||
| 324 | elseif str ~= partial then fail("didn't receive partial result.") | 332 | elseif str ~= partial then fail("didn't receive partial result.") |
| 325 | else pass("graceful 'closed' received") end | 333 | else pass("graceful 'closed' received") end |
| 326 | reconnect() | 334 | reconnect() |
| 327 | pass("trying write detection") | 335 | printf("trying write detection: ") |
| 328 | remote [[ | 336 | remote [[ |
| 329 | data:close() | 337 | data:close() |
| 330 | data = nil | 338 | data = nil |
| @@ -342,7 +350,6 @@ end | |||
| 342 | ------------------------------------------------------------------------ | 350 | ------------------------------------------------------------------------ |
| 343 | function test_selectbugs() | 351 | function test_selectbugs() |
| 344 | local r, s, e = socket.select(nil, nil, 0.1) | 352 | local r, s, e = socket.select(nil, nil, 0.1) |
| 345 | print(r, s, e) | ||
| 346 | assert(type(r) == "table" and type(s) == "table" and | 353 | assert(type(r) == "table" and type(s) == "table" and |
| 347 | (e == "timeout" or e == "error")) | 354 | (e == "timeout" or e == "error")) |
| 348 | pass("both nil: ok") | 355 | pass("both nil: ok") |
| @@ -374,7 +381,7 @@ end | |||
| 374 | 381 | ||
| 375 | ------------------------------------------------------------------------ | 382 | ------------------------------------------------------------------------ |
| 376 | function accept_timeout() | 383 | function accept_timeout() |
| 377 | io.stderr:write("accept with timeout (if it hangs, it failed): ") | 384 | printf("accept with timeout (if it hangs, it failed): ") |
| 378 | local s, e = socket.bind("*", 0, 0) | 385 | local s, e = socket.bind("*", 0, 0) |
| 379 | assert(s, e) | 386 | assert(s, e) |
| 380 | local t = socket.gettime() | 387 | local t = socket.gettime() |
| @@ -390,23 +397,22 @@ end | |||
| 390 | 397 | ||
| 391 | ------------------------------------------------------------------------ | 398 | ------------------------------------------------------------------------ |
| 392 | function connect_timeout() | 399 | function connect_timeout() |
| 393 | io.stderr:write("connect with timeout (if it hangs, it failed!): ") | 400 | printf("connect with timeout (if it hangs, it failed!): ") |
| 394 | local t = socket.gettime() | 401 | local t = socket.gettime() |
| 395 | local c, e = socket.tcp() | 402 | local c, e = socket.tcp() |
| 396 | assert(c, e) | 403 | assert(c, e) |
| 397 | c:settimeout(0.1) | 404 | c:settimeout(0.1) |
| 398 | local t = socket.gettime() | 405 | local t = socket.gettime() |
| 399 | local r, e = c:connect("10.0.0.1", 81) | 406 | local r, e = c:connect("10.0.0.1", 81) |
| 400 | print(r, e) | ||
| 401 | assert(not r, "should not connect") | 407 | assert(not r, "should not connect") |
| 402 | assert(socket.gettime() - t < 2, "took too long to give up.") | 408 | assert(socket.gettime() - t < 2, "took too long to give up.") |
| 403 | c:close() | 409 | c:close() |
| 404 | print("ok") | 410 | pass("ok") |
| 405 | end | 411 | end |
| 406 | 412 | ||
| 407 | ------------------------------------------------------------------------ | 413 | ------------------------------------------------------------------------ |
| 408 | function accept_errors() | 414 | function accept_errors() |
| 409 | io.stderr:write("not listening: ") | 415 | printf("not listening: ") |
| 410 | local d, e = socket.bind("*", 0) | 416 | local d, e = socket.bind("*", 0) |
| 411 | assert(d, e); | 417 | assert(d, e); |
| 412 | local c, e = socket.tcp(); | 418 | local c, e = socket.tcp(); |
| @@ -415,26 +421,26 @@ function accept_errors() | |||
| 415 | d:settimeout(2) | 421 | d:settimeout(2) |
| 416 | local r, e = d:accept() | 422 | local r, e = d:accept() |
| 417 | assert(not r and e) | 423 | assert(not r and e) |
| 418 | print("ok: ", e) | 424 | pass("ok") |
| 419 | io.stderr:write("not supported: ") | 425 | printf("not supported: ") |
| 420 | local c, e = socket.udp() | 426 | local c, e = socket.udp() |
| 421 | assert(c, e); | 427 | assert(c, e); |
| 422 | d:setfd(c:getfd()) | 428 | d:setfd(c:getfd()) |
| 423 | local r, e = d:accept() | 429 | local r, e = d:accept() |
| 424 | assert(not r and e) | 430 | assert(not r and e) |
| 425 | print("ok: ", e) | 431 | pass("ok") |
| 426 | end | 432 | end |
| 427 | 433 | ||
| 428 | ------------------------------------------------------------------------ | 434 | ------------------------------------------------------------------------ |
| 429 | function connect_errors() | 435 | function connect_errors() |
| 430 | io.stderr:write("connection refused: ") | 436 | printf("connection refused: ") |
| 431 | local c, e = socket.connect("localhost", 1); | 437 | local c, e = socket.connect("localhost", 1); |
| 432 | assert(not c and e) | 438 | assert(not c and e) |
| 433 | print("ok: ", e) | 439 | pass("ok") |
| 434 | io.stderr:write("host not found: ") | 440 | printf("host not found: ") |
| 435 | local c, e = socket.connect("host.is.invalid", 1); | 441 | local c, e = socket.connect("host.is.invalid", 1); |
| 436 | assert(not c and e, e) | 442 | assert(not c and e, e) |
| 437 | print("ok: ", e) | 443 | pass("ok") |
| 438 | end | 444 | end |
| 439 | 445 | ||
| 440 | ------------------------------------------------------------------------ | 446 | ------------------------------------------------------------------------ |
| @@ -447,7 +453,7 @@ function rebind_test() | |||
| 447 | r, e = s:bind("localhost", p) | 453 | r, e = s:bind("localhost", p) |
| 448 | assert(not r, "managed to rebind!") | 454 | assert(not r, "managed to rebind!") |
| 449 | assert(e) | 455 | assert(e) |
| 450 | print("ok: ", e) | 456 | pass("ok") |
| 451 | end | 457 | end |
| 452 | 458 | ||
| 453 | ------------------------------------------------------------------------ | 459 | ------------------------------------------------------------------------ |
| @@ -469,14 +475,14 @@ function getstats_test() | |||
| 469 | assert(s == t, "sent count failed" .. tostring(s) | 475 | assert(s == t, "sent count failed" .. tostring(s) |
| 470 | .. "/" .. tostring(t)) | 476 | .. "/" .. tostring(t)) |
| 471 | end | 477 | end |
| 472 | print("ok") | 478 | pass("ok") |
| 473 | end | 479 | end |
| 474 | 480 | ||
| 475 | 481 | ||
| 476 | ------------------------------------------------------------------------ | 482 | ------------------------------------------------------------------------ |
| 477 | function test_nonblocking(size) | 483 | function test_nonblocking(size) |
| 478 | reconnect() | 484 | reconnect() |
| 479 | print("Testing " .. 2*size .. " bytes") | 485 | printf("testing " .. 2*size .. " bytes: ") |
| 480 | remote(string.format([[ | 486 | remote(string.format([[ |
| 481 | data:send(string.rep("a", %d)) | 487 | data:send(string.rep("a", %d)) |
| 482 | socket.sleep(0.5) | 488 | socket.sleep(0.5) |
| @@ -508,7 +514,7 @@ remote(string.format([[ | |||
| 508 | data:settimeout(-1) | 514 | data:settimeout(-1) |
| 509 | local back = data:receive(2*size) | 515 | local back = data:receive(2*size) |
| 510 | assert(back == str, "'" .. back .. "' vs '" .. str .. "'") | 516 | assert(back == str, "'" .. back .. "' vs '" .. str .. "'") |
| 511 | print("ok") | 517 | pass("ok") |
| 512 | end | 518 | end |
| 513 | 519 | ||
| 514 | ------------------------------------------------------------------------ | 520 | ------------------------------------------------------------------------ |
| @@ -516,7 +522,7 @@ function test_readafterclose() | |||
| 516 | local back, partial, err | 522 | local back, partial, err |
| 517 | local str = 'little string' | 523 | local str = 'little string' |
| 518 | reconnect() | 524 | reconnect() |
| 519 | pass("trying repeated '*a' pattern") | 525 | printf("trying repeated '*a' pattern") |
| 520 | remote (string.format ([[ | 526 | remote (string.format ([[ |
| 521 | data:send('%s') | 527 | data:send('%s') |
| 522 | data:close() | 528 | data:close() |
| @@ -526,9 +532,9 @@ function test_readafterclose() | |||
| 526 | assert(back == str, "unexpected data read") | 532 | assert(back == str, "unexpected data read") |
| 527 | back, err, partial = data:receive("*a") | 533 | back, err, partial = data:receive("*a") |
| 528 | assert(back == nil and err == "closed", "should have returned 'closed'") | 534 | assert(back == nil and err == "closed", "should have returned 'closed'") |
| 529 | print("ok") | 535 | pass("ok") |
| 530 | reconnect() | 536 | reconnect() |
| 531 | pass("trying active close before '*a'") | 537 | printf("trying active close before '*a'") |
| 532 | remote (string.format ([[ | 538 | remote (string.format ([[ |
| 533 | data:close() | 539 | data:close() |
| 534 | data = nil | 540 | data = nil |
| @@ -536,9 +542,9 @@ function test_readafterclose() | |||
| 536 | data:close() | 542 | data:close() |
| 537 | back, err, partial = data:receive("*a") | 543 | back, err, partial = data:receive("*a") |
| 538 | assert(back == nil and err == "closed", "should have returned 'closed'") | 544 | assert(back == nil and err == "closed", "should have returned 'closed'") |
| 539 | print("ok") | 545 | pass("ok") |
| 540 | reconnect() | 546 | reconnect() |
| 541 | pass("trying active close before '*l'") | 547 | printf("trying active close before '*l'") |
| 542 | remote (string.format ([[ | 548 | remote (string.format ([[ |
| 543 | data:close() | 549 | data:close() |
| 544 | data = nil | 550 | data = nil |
| @@ -546,9 +552,9 @@ function test_readafterclose() | |||
| 546 | data:close() | 552 | data:close() |
| 547 | back, err, partial = data:receive() | 553 | back, err, partial = data:receive() |
| 548 | assert(back == nil and err == "closed", "should have returned 'closed'") | 554 | assert(back == nil and err == "closed", "should have returned 'closed'") |
| 549 | print("ok") | 555 | pass("ok") |
| 550 | reconnect() | 556 | reconnect() |
| 551 | pass("trying active close before raw 1") | 557 | printf("trying active close before raw 1") |
| 552 | remote (string.format ([[ | 558 | remote (string.format ([[ |
| 553 | data:close() | 559 | data:close() |
| 554 | data = nil | 560 | data = nil |
| @@ -556,9 +562,9 @@ function test_readafterclose() | |||
| 556 | data:close() | 562 | data:close() |
| 557 | back, err, partial = data:receive(1) | 563 | back, err, partial = data:receive(1) |
| 558 | assert(back == nil and err == "closed", "should have returned 'closed'") | 564 | assert(back == nil and err == "closed", "should have returned 'closed'") |
| 559 | print("ok") | 565 | pass("ok") |
| 560 | reconnect() | 566 | reconnect() |
| 561 | pass("trying active close before raw 0") | 567 | printf("trying active close before raw 0") |
| 562 | remote (string.format ([[ | 568 | remote (string.format ([[ |
| 563 | data:close() | 569 | data:close() |
| 564 | data = nil | 570 | data = nil |
| @@ -566,7 +572,7 @@ function test_readafterclose() | |||
| 566 | data:close() | 572 | data:close() |
| 567 | back, err, partial = data:receive(0) | 573 | back, err, partial = data:receive(0) |
| 568 | assert(back == nil and err == "closed", "should have returned 'closed'") | 574 | assert(back == nil and err == "closed", "should have returned 'closed'") |
| 569 | print("ok") | 575 | pass("ok") |
| 570 | end | 576 | end |
| 571 | 577 | ||
| 572 | ------------------------------------------------------------------------ | 578 | ------------------------------------------------------------------------ |
| @@ -581,13 +587,29 @@ function test_writeafterclose() | |||
| 581 | while not err do | 587 | while not err do |
| 582 | sent, err, errsent, time = data:send(str) | 588 | sent, err, errsent, time = data:send(str) |
| 583 | end | 589 | end |
| 584 | print(sent, err, errsent, time) | 590 | assert(err == "closed", "should have returned 'closed'") |
| 585 | print("ok") | 591 | pass("ok") |
| 586 | end | 592 | end |
| 587 | 593 | ||
| 588 | ------------------------------------------------------------------------ | 594 | ------------------------------------------------------------------------ |
| 589 | --test_writeafterclose() | ||
| 590 | 595 | ||
| 596 | function test_partialrecv() | ||
| 597 | local str = 'little string' | ||
| 598 | reconnect() | ||
| 599 | remote([[ | ||
| 600 | data:send("7890") | ||
| 601 | ]]) | ||
| 602 | data:settimeout(1) | ||
| 603 | back, err = data:receive(10, "123456") | ||
| 604 | assert(back == "1234567890", "failed on exact mixed length") | ||
| 605 | back, err = data:receive(8, "87654321") | ||
| 606 | assert(back == "87654321", "failed on exact length") | ||
| 607 | back, err = data:receive(4, "87654321") | ||
| 608 | assert(back == "87654321", "failed on smaller length") | ||
| 609 | pass("ok") | ||
| 610 | end | ||
| 611 | |||
| 612 | ------------------------------------------------------------------------ | ||
| 591 | test("method registration") | 613 | test("method registration") |
| 592 | test_methods(socket.tcp(), { | 614 | test_methods(socket.tcp(), { |
| 593 | "accept", | 615 | "accept", |
| @@ -629,12 +651,18 @@ test_methods(socket.udp(), { | |||
| 629 | "settimeout" | 651 | "settimeout" |
| 630 | }) | 652 | }) |
| 631 | 653 | ||
| 654 | test("partial receive") | ||
| 655 | test_partialrecv() | ||
| 656 | |||
| 632 | test("select function") | 657 | test("select function") |
| 633 | test_selectbugs() | 658 | test_selectbugs() |
| 634 | 659 | ||
| 635 | test("testing read after close") | 660 | test("read after close") |
| 636 | test_readafterclose() | 661 | test_readafterclose() |
| 637 | 662 | ||
| 663 | test("write after close") | ||
| 664 | test_writeafterclose() | ||
| 665 | |||
| 638 | test("connect function") | 666 | test("connect function") |
| 639 | connect_timeout() | 667 | connect_timeout() |
| 640 | empty_connect() | 668 | empty_connect() |
diff --git a/test/testsupport.lua b/test/testsupport.lua index acad8f5..b986088 100644 --- a/test/testsupport.lua +++ b/test/testsupport.lua | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | function readfile(name) | 1 | function readfile(name) |
| 2 | local f = io.open(name, "rb") | 2 | local f = io.open(name, "rb") |
| 3 | if not f then return nil end | 3 | if not f then return nil end |
| 4 | local s = f:read("*a") | 4 | local s = f:read("*a") |
| 5 | f:close() | 5 | f:close() |
| 6 | return s | 6 | return s |
| 7 | end | 7 | end |
| 8 | 8 | ||
| 9 | function similar(s1, s2) | 9 | function similar(s1, s2) |
| 10 | return string.lower(string.gsub(s1 or "", "%s", "")) == | 10 | return string.lower(string.gsub(s1 or "", "%s", "")) == |
| 11 | string.lower(string.gsub(s2 or "", "%s", "")) | 11 | string.lower(string.gsub(s2 or "", "%s", "")) |
| 12 | end | 12 | end |
| 13 | 13 | ||
| @@ -28,7 +28,7 @@ local set = rawset | |||
| 28 | local warn = print | 28 | local warn = print |
| 29 | 29 | ||
| 30 | local setglobal = function(table, key, value) | 30 | local setglobal = function(table, key, value) |
| 31 | warn("changed " .. key) | 31 | warn("changed " .. key) |
| 32 | set(table, key, value) | 32 | set(table, key, value) |
| 33 | end | 33 | end |
| 34 | 34 | ||
diff --git a/test/urltest.lua b/test/urltest.lua index 8dc0c14..d46cb03 100644 --- a/test/urltest.lua +++ b/test/urltest.lua | |||
| @@ -3,439 +3,439 @@ socket.url = require("socket.url") | |||
| 3 | dofile("testsupport.lua") | 3 | dofile("testsupport.lua") |
| 4 | 4 | ||
| 5 | local check_build_url = function(parsed) | 5 | local check_build_url = function(parsed) |
| 6 | local built = socket.url.build(parsed) | 6 | local built = socket.url.build(parsed) |
| 7 | if built ~= parsed.url then | 7 | if built ~= parsed.url then |
| 8 | print("built is different from expected") | 8 | print("built is different from expected") |
| 9 | print(built) | 9 | print(built) |
| 10 | print(expected) | 10 | print(expected) |
| 11 | exit() | 11 | exit() |
| 12 | end | 12 | end |
| 13 | end | 13 | end |
| 14 | 14 | ||
| 15 | local check_protect = function(parsed, path, unsafe) | 15 | local check_protect = function(parsed, path, unsafe) |
| 16 | local built = socket.url.build_path(parsed, unsafe) | 16 | local built = socket.url.build_path(parsed, unsafe) |
| 17 | if built ~= path then | 17 | if built ~= path then |
| 18 | print(built, path) | 18 | print(built, path) |
| 19 | print("path composition failed.") | 19 | print("path composition failed.") |
| 20 | exit() | 20 | exit() |
| 21 | end | 21 | end |
| 22 | end | 22 | end |
| 23 | 23 | ||
| 24 | local check_invert = function(url) | 24 | local check_invert = function(url) |
| 25 | local parsed = socket.url.parse(url) | 25 | local parsed = socket.url.parse(url) |
| 26 | parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path)) | 26 | parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path)) |
| 27 | local rebuilt = socket.url.build(parsed) | 27 | local rebuilt = socket.url.build(parsed) |
| 28 | if rebuilt ~= url then | 28 | if rebuilt ~= url then |
| 29 | print(url, rebuilt) | 29 | print(url, rebuilt) |
| 30 | print("original and rebuilt are different") | 30 | print("original and rebuilt are different") |
| 31 | exit() | 31 | exit() |
| 32 | end | 32 | end |
| 33 | end | 33 | end |
| 34 | 34 | ||
| 35 | local check_parse_path = function(path, expect) | 35 | local check_parse_path = function(path, expect) |
| 36 | local parsed = socket.url.parse_path(path) | 36 | local parsed = socket.url.parse_path(path) |
| 37 | for i = 1, math.max(table.getn(parsed), table.getn(expect)) do | 37 | for i = 1, math.max(table.getn(parsed), table.getn(expect)) do |
| 38 | if parsed[i] ~= expect[i] then | 38 | if parsed[i] ~= expect[i] then |
| 39 | print(path) | 39 | print(path) |
| 40 | exit() | 40 | exit() |
| 41 | end | 41 | end |
| 42 | end | 42 | end |
| 43 | if expect.is_directory ~= parsed.is_directory then | 43 | if expect.is_directory ~= parsed.is_directory then |
| 44 | print(path) | 44 | print(path) |
| 45 | print("is_directory mismatch") | 45 | print("is_directory mismatch") |
| 46 | exit() | 46 | exit() |
| 47 | end | 47 | end |
| 48 | if expect.is_absolute ~= parsed.is_absolute then | 48 | if expect.is_absolute ~= parsed.is_absolute then |
| 49 | print(path) | 49 | print(path) |
| 50 | print("is_absolute mismatch") | 50 | print("is_absolute mismatch") |
| 51 | exit() | 51 | exit() |
| 52 | end | 52 | end |
| 53 | local built = socket.url.build_path(expect) | 53 | local built = socket.url.build_path(expect) |
| 54 | if built ~= path then | 54 | if built ~= path then |
| 55 | print(built, path) | 55 | print(built, path) |
| 56 | print("path composition failed.") | 56 | print("path composition failed.") |
| 57 | exit() | 57 | exit() |
| 58 | end | 58 | end |
| 59 | end | 59 | end |
| 60 | 60 | ||
| 61 | local check_absolute_url = function(base, relative, absolute) | 61 | local check_absolute_url = function(base, relative, absolute) |
| 62 | local res = socket.url.absolute(base, relative) | 62 | local res = socket.url.absolute(base, relative) |
| 63 | if res ~= absolute then | 63 | if res ~= absolute then |
| 64 | io.write("absolute: In test for '", relative, "' expected '", | 64 | io.write("absolute: In test for '", relative, "' expected '", |
| 65 | absolute, "' but got '", res, "'\n") | 65 | absolute, "' but got '", res, "'\n") |
| 66 | exit() | 66 | exit() |
| 67 | end | 67 | end |
| 68 | end | 68 | end |
| 69 | 69 | ||
| 70 | local check_parse_url = function(gaba) | 70 | local check_parse_url = function(gaba) |
| 71 | local url = gaba.url | 71 | local url = gaba.url |
| 72 | gaba.url = nil | 72 | gaba.url = nil |
| 73 | local parsed = socket.url.parse(url) | 73 | local parsed = socket.url.parse(url) |
| 74 | for i, v in pairs(gaba) do | 74 | for i, v in pairs(gaba) do |
| 75 | if v ~= parsed[i] then | 75 | if v ~= parsed[i] then |
| 76 | io.write("parse: In test for '", url, "' expected ", i, " = '", | 76 | io.write("parse: In test for '", url, "' expected ", i, " = '", |
| 77 | v, "' but got '", tostring(parsed[i]), "'\n") | 77 | v, "' but got '", tostring(parsed[i]), "'\n") |
| 78 | for i,v in pairs(parsed) do print(i,v) end | 78 | for i,v in pairs(parsed) do print(i,v) end |
| 79 | exit() | 79 | exit() |
| 80 | end | 80 | end |
| 81 | end | 81 | end |
| 82 | for i, v in pairs(parsed) do | 82 | for i, v in pairs(parsed) do |
| 83 | if v ~= gaba[i] then | 83 | if v ~= gaba[i] then |
| 84 | io.write("parse: In test for '", url, "' expected ", i, " = '", | 84 | io.write("parse: In test for '", url, "' expected ", i, " = '", |
| 85 | tostring(gaba[i]), "' but got '", v, "'\n") | 85 | tostring(gaba[i]), "' but got '", v, "'\n") |
| 86 | for i,v in pairs(parsed) do print(i,v) end | 86 | for i,v in pairs(parsed) do print(i,v) end |
| 87 | exit() | 87 | exit() |
| 88 | end | 88 | end |
| 89 | end | 89 | end |
| 90 | end | 90 | end |
| 91 | 91 | ||
| 92 | print("testing URL parsing") | 92 | print("testing URL parsing") |
| 93 | check_parse_url{ | 93 | check_parse_url{ |
| 94 | url = "scheme://userinfo@host:port/path;params?query#fragment", | 94 | url = "scheme://userinfo@host:port/path;params?query#fragment", |
| 95 | scheme = "scheme", | 95 | scheme = "scheme", |
| 96 | authority = "userinfo@host:port", | 96 | authority = "userinfo@host:port", |
| 97 | host = "host", | 97 | host = "host", |
| 98 | port = "port", | 98 | port = "port", |
| 99 | userinfo = "userinfo", | 99 | userinfo = "userinfo", |
| 100 | user = "userinfo", | 100 | user = "userinfo", |
| 101 | path = "/path", | 101 | path = "/path", |
| 102 | params = "params", | 102 | params = "params", |
| 103 | query = "query", | 103 | query = "query", |
| 104 | fragment = "fragment" | 104 | fragment = "fragment" |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | check_parse_url{ | 107 | check_parse_url{ |
| 108 | url = "scheme://user:password@host:port/path;params?query#fragment", | 108 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 109 | scheme = "scheme", | 109 | scheme = "scheme", |
| 110 | authority = "user:password@host:port", | 110 | authority = "user:password@host:port", |
| 111 | host = "host", | 111 | host = "host", |
| 112 | port = "port", | 112 | port = "port", |
| 113 | userinfo = "user:password", | 113 | userinfo = "user:password", |
| 114 | user = "user", | 114 | user = "user", |
| 115 | password = "password", | 115 | password = "password", |
| 116 | path = "/path", | 116 | path = "/path", |
| 117 | params = "params", | 117 | params = "params", |
| 118 | query = "query", | 118 | query = "query", |
| 119 | fragment = "fragment", | 119 | fragment = "fragment", |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | check_parse_url{ | 122 | check_parse_url{ |
| 123 | url = "scheme://userinfo@host:port/path;params?query#", | 123 | url = "scheme://userinfo@host:port/path;params?query#", |
| 124 | scheme = "scheme", | 124 | scheme = "scheme", |
| 125 | authority = "userinfo@host:port", | 125 | authority = "userinfo@host:port", |
| 126 | host = "host", | 126 | host = "host", |
| 127 | port = "port", | 127 | port = "port", |
| 128 | userinfo = "userinfo", | 128 | userinfo = "userinfo", |
| 129 | user = "userinfo", | 129 | user = "userinfo", |
| 130 | path = "/path", | 130 | path = "/path", |
| 131 | params = "params", | 131 | params = "params", |
| 132 | query = "query", | 132 | query = "query", |
| 133 | fragment = "" | 133 | fragment = "" |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | check_parse_url{ | 136 | check_parse_url{ |
| 137 | url = "scheme://userinfo@host:port/path;params?#fragment", | 137 | url = "scheme://userinfo@host:port/path;params?#fragment", |
| 138 | scheme = "scheme", | 138 | scheme = "scheme", |
| 139 | authority = "userinfo@host:port", | 139 | authority = "userinfo@host:port", |
| 140 | host = "host", | 140 | host = "host", |
| 141 | port = "port", | 141 | port = "port", |
| 142 | userinfo = "userinfo", | 142 | userinfo = "userinfo", |
| 143 | user = "userinfo", | 143 | user = "userinfo", |
| 144 | path = "/path", | 144 | path = "/path", |
| 145 | params = "params", | 145 | params = "params", |
| 146 | query = "", | 146 | query = "", |
| 147 | fragment = "fragment" | 147 | fragment = "fragment" |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | check_parse_url{ | 150 | check_parse_url{ |
| 151 | url = "scheme://userinfo@host:port/path;params#fragment", | 151 | url = "scheme://userinfo@host:port/path;params#fragment", |
| 152 | scheme = "scheme", | 152 | scheme = "scheme", |
| 153 | authority = "userinfo@host:port", | 153 | authority = "userinfo@host:port", |
| 154 | host = "host", | 154 | host = "host", |
| 155 | port = "port", | 155 | port = "port", |
| 156 | userinfo = "userinfo", | 156 | userinfo = "userinfo", |
| 157 | user = "userinfo", | 157 | user = "userinfo", |
| 158 | path = "/path", | 158 | path = "/path", |
| 159 | params = "params", | 159 | params = "params", |
| 160 | fragment = "fragment" | 160 | fragment = "fragment" |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | check_parse_url{ | 163 | check_parse_url{ |
| 164 | url = "scheme://userinfo@host:port/path;?query#fragment", | 164 | url = "scheme://userinfo@host:port/path;?query#fragment", |
| 165 | scheme = "scheme", | 165 | scheme = "scheme", |
| 166 | authority = "userinfo@host:port", | 166 | authority = "userinfo@host:port", |
| 167 | host = "host", | 167 | host = "host", |
| 168 | port = "port", | 168 | port = "port", |
| 169 | userinfo = "userinfo", | 169 | userinfo = "userinfo", |
| 170 | user = "userinfo", | 170 | user = "userinfo", |
| 171 | path = "/path", | 171 | path = "/path", |
| 172 | params = "", | 172 | params = "", |
| 173 | query = "query", | 173 | query = "query", |
| 174 | fragment = "fragment" | 174 | fragment = "fragment" |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | check_parse_url{ | 177 | check_parse_url{ |
| 178 | url = "scheme://userinfo@host:port/path?query#fragment", | 178 | url = "scheme://userinfo@host:port/path?query#fragment", |
| 179 | scheme = "scheme", | 179 | scheme = "scheme", |
| 180 | authority = "userinfo@host:port", | 180 | authority = "userinfo@host:port", |
| 181 | host = "host", | 181 | host = "host", |
| 182 | port = "port", | 182 | port = "port", |
| 183 | userinfo = "userinfo", | 183 | userinfo = "userinfo", |
| 184 | user = "userinfo", | 184 | user = "userinfo", |
| 185 | path = "/path", | 185 | path = "/path", |
| 186 | query = "query", | 186 | query = "query", |
| 187 | fragment = "fragment" | 187 | fragment = "fragment" |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | check_parse_url{ | 190 | check_parse_url{ |
| 191 | url = "scheme://userinfo@host:port/;params?query#fragment", | 191 | url = "scheme://userinfo@host:port/;params?query#fragment", |
| 192 | scheme = "scheme", | 192 | scheme = "scheme", |
| 193 | authority = "userinfo@host:port", | 193 | authority = "userinfo@host:port", |
| 194 | host = "host", | 194 | host = "host", |
| 195 | port = "port", | 195 | port = "port", |
| 196 | userinfo = "userinfo", | 196 | userinfo = "userinfo", |
| 197 | user = "userinfo", | 197 | user = "userinfo", |
| 198 | path = "/", | 198 | path = "/", |
| 199 | params = "params", | 199 | params = "params", |
| 200 | query = "query", | 200 | query = "query", |
| 201 | fragment = "fragment" | 201 | fragment = "fragment" |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | check_parse_url{ | 204 | check_parse_url{ |
| 205 | url = "scheme://userinfo@host:port", | 205 | url = "scheme://userinfo@host:port", |
| 206 | scheme = "scheme", | 206 | scheme = "scheme", |
| 207 | authority = "userinfo@host:port", | 207 | authority = "userinfo@host:port", |
| 208 | host = "host", | 208 | host = "host", |
| 209 | port = "port", | 209 | port = "port", |
| 210 | userinfo = "userinfo", | 210 | userinfo = "userinfo", |
| 211 | user = "userinfo", | 211 | user = "userinfo", |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | check_parse_url{ | 214 | check_parse_url{ |
| 215 | url = "//userinfo@host:port/path;params?query#fragment", | 215 | url = "//userinfo@host:port/path;params?query#fragment", |
| 216 | authority = "userinfo@host:port", | 216 | authority = "userinfo@host:port", |
| 217 | host = "host", | 217 | host = "host", |
| 218 | port = "port", | 218 | port = "port", |
| 219 | userinfo = "userinfo", | 219 | userinfo = "userinfo", |
| 220 | user = "userinfo", | 220 | user = "userinfo", |
| 221 | path = "/path", | 221 | path = "/path", |
| 222 | params = "params", | 222 | params = "params", |
| 223 | query = "query", | 223 | query = "query", |
| 224 | fragment = "fragment" | 224 | fragment = "fragment" |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | check_parse_url{ | 227 | check_parse_url{ |
| 228 | url = "//userinfo@host:port/path", | 228 | url = "//userinfo@host:port/path", |
| 229 | authority = "userinfo@host:port", | 229 | authority = "userinfo@host:port", |
| 230 | host = "host", | 230 | host = "host", |
| 231 | port = "port", | 231 | port = "port", |
| 232 | userinfo = "userinfo", | 232 | userinfo = "userinfo", |
| 233 | user = "userinfo", | 233 | user = "userinfo", |
| 234 | path = "/path", | 234 | path = "/path", |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | check_parse_url{ | 237 | check_parse_url{ |
| 238 | url = "//userinfo@host/path", | 238 | url = "//userinfo@host/path", |
| 239 | authority = "userinfo@host", | 239 | authority = "userinfo@host", |
| 240 | host = "host", | 240 | host = "host", |
| 241 | userinfo = "userinfo", | 241 | userinfo = "userinfo", |
| 242 | user = "userinfo", | 242 | user = "userinfo", |
| 243 | path = "/path", | 243 | path = "/path", |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | check_parse_url{ | 246 | check_parse_url{ |
| 247 | url = "//user:password@host/path", | 247 | url = "//user:password@host/path", |
| 248 | authority = "user:password@host", | 248 | authority = "user:password@host", |
| 249 | host = "host", | 249 | host = "host", |
| 250 | userinfo = "user:password", | 250 | userinfo = "user:password", |
| 251 | password = "password", | 251 | password = "password", |
| 252 | user = "user", | 252 | user = "user", |
| 253 | path = "/path", | 253 | path = "/path", |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | check_parse_url{ | 256 | check_parse_url{ |
| 257 | url = "//user:@host/path", | 257 | url = "//user:@host/path", |
| 258 | authority = "user:@host", | 258 | authority = "user:@host", |
| 259 | host = "host", | 259 | host = "host", |
| 260 | userinfo = "user:", | 260 | userinfo = "user:", |
| 261 | password = "", | 261 | password = "", |
| 262 | user = "user", | 262 | user = "user", |
| 263 | path = "/path", | 263 | path = "/path", |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | check_parse_url{ | 266 | check_parse_url{ |
| 267 | url = "//user@host:port/path", | 267 | url = "//user@host:port/path", |
| 268 | authority = "user@host:port", | 268 | authority = "user@host:port", |
| 269 | host = "host", | 269 | host = "host", |
| 270 | userinfo = "user", | 270 | userinfo = "user", |
| 271 | user = "user", | 271 | user = "user", |
| 272 | port = "port", | 272 | port = "port", |
| 273 | path = "/path", | 273 | path = "/path", |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | check_parse_url{ | 276 | check_parse_url{ |
| 277 | url = "//host:port/path", | 277 | url = "//host:port/path", |
| 278 | authority = "host:port", | 278 | authority = "host:port", |
| 279 | port = "port", | 279 | port = "port", |
| 280 | host = "host", | 280 | host = "host", |
| 281 | path = "/path", | 281 | path = "/path", |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | check_parse_url{ | 284 | check_parse_url{ |
| 285 | url = "//host/path", | 285 | url = "//host/path", |
| 286 | authority = "host", | 286 | authority = "host", |
| 287 | host = "host", | 287 | host = "host", |
| 288 | path = "/path", | 288 | path = "/path", |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | check_parse_url{ | 291 | check_parse_url{ |
| 292 | url = "//host", | 292 | url = "//host", |
| 293 | authority = "host", | 293 | authority = "host", |
| 294 | host = "host", | 294 | host = "host", |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | check_parse_url{ | 297 | check_parse_url{ |
| 298 | url = "/path", | 298 | url = "/path", |
| 299 | path = "/path", | 299 | path = "/path", |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | check_parse_url{ | 302 | check_parse_url{ |
| 303 | url = "path", | 303 | url = "path", |
| 304 | path = "path", | 304 | path = "path", |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | print("testing URL building") | 307 | print("testing URL building") |
| 308 | check_build_url { | 308 | check_build_url { |
| 309 | url = "scheme://user:password@host:port/path;params?query#fragment", | 309 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 310 | scheme = "scheme", | 310 | scheme = "scheme", |
| 311 | host = "host", | 311 | host = "host", |
| 312 | port = "port", | 312 | port = "port", |
| 313 | user = "user", | 313 | user = "user", |
| 314 | password = "password", | 314 | password = "password", |
| 315 | path = "/path", | 315 | path = "/path", |
| 316 | params = "params", | 316 | params = "params", |
| 317 | query = "query", | 317 | query = "query", |
| 318 | fragment = "fragment" | 318 | fragment = "fragment" |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | check_build_url { | 321 | check_build_url { |
| 322 | url = "scheme://user:password@host/path;params?query#fragment", | 322 | url = "scheme://user:password@host/path;params?query#fragment", |
| 323 | scheme = "scheme", | 323 | scheme = "scheme", |
| 324 | host = "host", | 324 | host = "host", |
| 325 | user = "user", | 325 | user = "user", |
| 326 | password = "password", | 326 | password = "password", |
| 327 | path = "/path", | 327 | path = "/path", |
| 328 | params = "params", | 328 | params = "params", |
| 329 | query = "query", | 329 | query = "query", |
| 330 | fragment = "fragment" | 330 | fragment = "fragment" |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | check_build_url { | 333 | check_build_url { |
| 334 | url = "scheme://user@host/path;params?query#fragment", | 334 | url = "scheme://user@host/path;params?query#fragment", |
| 335 | scheme = "scheme", | 335 | scheme = "scheme", |
| 336 | host = "host", | 336 | host = "host", |
| 337 | user = "user", | 337 | user = "user", |
| 338 | path = "/path", | 338 | path = "/path", |
| 339 | params = "params", | 339 | params = "params", |
| 340 | query = "query", | 340 | query = "query", |
| 341 | fragment = "fragment" | 341 | fragment = "fragment" |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | check_build_url { | 344 | check_build_url { |
| 345 | url = "scheme://host/path;params?query#fragment", | 345 | url = "scheme://host/path;params?query#fragment", |
| 346 | scheme = "scheme", | 346 | scheme = "scheme", |
| 347 | host = "host", | 347 | host = "host", |
| 348 | path = "/path", | 348 | path = "/path", |
| 349 | params = "params", | 349 | params = "params", |
| 350 | query = "query", | 350 | query = "query", |
| 351 | fragment = "fragment" | 351 | fragment = "fragment" |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | check_build_url { | 354 | check_build_url { |
| 355 | url = "scheme://host/path;params#fragment", | 355 | url = "scheme://host/path;params#fragment", |
| 356 | scheme = "scheme", | 356 | scheme = "scheme", |
| 357 | host = "host", | 357 | host = "host", |
| 358 | path = "/path", | 358 | path = "/path", |
| 359 | params = "params", | 359 | params = "params", |
| 360 | fragment = "fragment" | 360 | fragment = "fragment" |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | check_build_url { | 363 | check_build_url { |
| 364 | url = "scheme://host/path#fragment", | 364 | url = "scheme://host/path#fragment", |
| 365 | scheme = "scheme", | 365 | scheme = "scheme", |
| 366 | host = "host", | 366 | host = "host", |
| 367 | path = "/path", | 367 | path = "/path", |
| 368 | fragment = "fragment" | 368 | fragment = "fragment" |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | check_build_url { | 371 | check_build_url { |
| 372 | url = "scheme://host/path", | 372 | url = "scheme://host/path", |
| 373 | scheme = "scheme", | 373 | scheme = "scheme", |
| 374 | host = "host", | 374 | host = "host", |
| 375 | path = "/path", | 375 | path = "/path", |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | check_build_url { | 378 | check_build_url { |
| 379 | url = "//host/path", | 379 | url = "//host/path", |
| 380 | host = "host", | 380 | host = "host", |
| 381 | path = "/path", | 381 | path = "/path", |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | check_build_url { | 384 | check_build_url { |
| 385 | url = "/path", | 385 | url = "/path", |
| 386 | path = "/path", | 386 | path = "/path", |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | check_build_url { | 389 | check_build_url { |
| 390 | url = "scheme://user:password@host:port/path;params?query#fragment", | 390 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 391 | scheme = "scheme", | 391 | scheme = "scheme", |
| 392 | host = "host", | 392 | host = "host", |
| 393 | port = "port", | 393 | port = "port", |
| 394 | user = "user", | 394 | user = "user", |
| 395 | userinfo = "not used", | 395 | userinfo = "not used", |
| 396 | password = "password", | 396 | password = "password", |
| 397 | path = "/path", | 397 | path = "/path", |
| 398 | params = "params", | 398 | params = "params", |
| 399 | query = "query", | 399 | query = "query", |
| 400 | fragment = "fragment" | 400 | fragment = "fragment" |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | check_build_url { | 403 | check_build_url { |
| 404 | url = "scheme://user:password@host:port/path;params?query#fragment", | 404 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 405 | scheme = "scheme", | 405 | scheme = "scheme", |
| 406 | host = "host", | 406 | host = "host", |
| 407 | port = "port", | 407 | port = "port", |
| 408 | user = "user", | 408 | user = "user", |
| 409 | userinfo = "not used", | 409 | userinfo = "not used", |
| 410 | authority = "not used", | 410 | authority = "not used", |
| 411 | password = "password", | 411 | password = "password", |
| 412 | path = "/path", | 412 | path = "/path", |
| 413 | params = "params", | 413 | params = "params", |
| 414 | query = "query", | 414 | query = "query", |
| 415 | fragment = "fragment" | 415 | fragment = "fragment" |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | check_build_url { | 418 | check_build_url { |
| 419 | url = "scheme://user:password@host:port/path;params?query#fragment", | 419 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 420 | scheme = "scheme", | 420 | scheme = "scheme", |
| 421 | host = "host", | 421 | host = "host", |
| 422 | port = "port", | 422 | port = "port", |
| 423 | userinfo = "user:password", | 423 | userinfo = "user:password", |
| 424 | authority = "not used", | 424 | authority = "not used", |
| 425 | path = "/path", | 425 | path = "/path", |
| 426 | params = "params", | 426 | params = "params", |
| 427 | query = "query", | 427 | query = "query", |
| 428 | fragment = "fragment" | 428 | fragment = "fragment" |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | check_build_url { | 431 | check_build_url { |
| 432 | url = "scheme://user:password@host:port/path;params?query#fragment", | 432 | url = "scheme://user:password@host:port/path;params?query#fragment", |
| 433 | scheme = "scheme", | 433 | scheme = "scheme", |
| 434 | authority = "user:password@host:port", | 434 | authority = "user:password@host:port", |
| 435 | path = "/path", | 435 | path = "/path", |
| 436 | params = "params", | 436 | params = "params", |
| 437 | query = "query", | 437 | query = "query", |
| 438 | fragment = "fragment" | 438 | fragment = "fragment" |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | -- standard RFC tests | 441 | -- standard RFC tests |
| @@ -488,11 +488,11 @@ print("testing path parsing and composition") | |||
| 488 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) | 488 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) |
| 489 | check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 }) | 489 | check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 }) |
| 490 | check_parse_path("eu/tu/ele/nos/vos/eles/", | 490 | check_parse_path("eu/tu/ele/nos/vos/eles/", |
| 491 | { "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1}) | 491 | { "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1}) |
| 492 | check_parse_path("/", { is_absolute = 1, is_directory = 1}) | 492 | check_parse_path("/", { is_absolute = 1, is_directory = 1}) |
| 493 | check_parse_path("", { }) | 493 | check_parse_path("", { }) |
| 494 | check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/", | 494 | check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/", |
| 495 | { "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1}) | 495 | { "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1}) |
| 496 | check_parse_path("eu/tu", { "eu", "tu" }) | 496 | check_parse_path("eu/tu", { "eu", "tu" }) |
| 497 | 497 | ||
| 498 | print("testing path protection") | 498 | print("testing path protection") |
diff --git a/test/utestclnt.lua b/test/utestclnt.lua index f002c6e..eec6adc 100644 --- a/test/utestclnt.lua +++ b/test/utestclnt.lua | |||
| @@ -298,7 +298,7 @@ function empty_connect() | |||
| 298 | pass("ok") | 298 | pass("ok") |
| 299 | data = socket.connect(host, port) | 299 | data = socket.connect(host, port) |
| 300 | else | 300 | else |
| 301 | pass("gethostbyname returns localhost on empty string...") | 301 | pass("gethostbyname returns localhost on empty string...") |
| 302 | end | 302 | end |
| 303 | end | 303 | end |
| 304 | 304 | ||
