diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-02-11 03:31:53 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-02-11 03:31:53 +0000 |
commit | 390846b640ee7013d51a766b4b2472bdcfbbdfcc (patch) | |
tree | 3bedd023a0a84feb714615245b58eab5ffb4309b | |
parent | 0b2542d1a61fc5425ff65ab3dbf7ba7de174763f (diff) | |
download | luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.tar.gz luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.tar.bz2 luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.zip |
Added ltn12 module. Modified mime to be stand alone.
Still crashes on invalid input. Dunno why.
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | doc/reference.html | 2 | ||||
-rw-r--r-- | etc/eol.lua | 4 | ||||
-rw-r--r-- | etc/qp.lua | 4 | ||||
-rw-r--r-- | src/ltn12.lua | 171 | ||||
-rw-r--r-- | src/luasocket.c | 2 | ||||
-rw-r--r-- | src/mime.c | 84 | ||||
-rw-r--r-- | src/mime.lua | 74 | ||||
-rw-r--r-- | src/wsocket.c | 8 | ||||
-rw-r--r-- | src/wsocket.h | 1 | ||||
-rw-r--r-- | test/ltn12test.lua | 3 | ||||
-rw-r--r-- | test/mimetest.lua | 93 |
12 files changed, 291 insertions, 161 deletions
@@ -19,10 +19,16 @@ | |||
19 | * Separar as classes em arquivos | 19 | * Separar as classes em arquivos |
20 | * Retorno de sendto em datagram sockets pode ser refused | 20 | * Retorno de sendto em datagram sockets pode ser refused |
21 | 21 | ||
22 | unify filter and send/receive callback. new sink/source/pump idea. | ||
23 | get rid of aux_optlstring | ||
24 | wrap sink and sources with a function that performs the replacement | ||
25 | get rid of unpack in mime.lua | ||
22 | 26 | ||
23 | check garbage collection in test*.lua | 27 | check garbage collection in test*.lua |
24 | pop3??? | 28 | pop3??? |
25 | 29 | ||
30 | break chain into a simpler binary chain and a complex (recursive) one. | ||
31 | |||
26 | add socket.TIMEOUT to be default timeout? | 32 | add socket.TIMEOUT to be default timeout? |
27 | 33 | ||
28 | manual | 34 | manual |
diff --git a/doc/reference.html b/doc/reference.html index e6efb6e..6e14891 100644 --- a/doc/reference.html +++ b/doc/reference.html | |||
@@ -126,7 +126,7 @@ | |||
126 | <a href="mime.html">MIME (socket.mime) </a> | 126 | <a href="mime.html">MIME (socket.mime) </a> |
127 | <blockquote> | 127 | <blockquote> |
128 | <a href="mime.html#high">high-level</a>: | 128 | <a href="mime.html#high">high-level</a>: |
129 | <a href="mime.html#decode">canonic</a>, | 129 | <a href="mime.html#normalize">normalize</a>, |
130 | <a href="mime.html#chain">chain</a>, | 130 | <a href="mime.html#chain">chain</a>, |
131 | <a href="mime.html#decode">decode</a>, | 131 | <a href="mime.html#decode">decode</a>, |
132 | <a href="mime.html#encode">encode</a>, | 132 | <a href="mime.html#encode">encode</a>, |
diff --git a/etc/eol.lua b/etc/eol.lua index fea5da9..6b2a8a9 100644 --- a/etc/eol.lua +++ b/etc/eol.lua | |||
@@ -1,9 +1,9 @@ | |||
1 | marker = {['-u'] = '\10', ['-d'] = '\13\10'} | 1 | marker = {['-u'] = '\10', ['-d'] = '\13\10'} |
2 | arg = arg or {'-u'} | 2 | arg = arg or {'-u'} |
3 | marker = marker[arg[1]] or marker['-u'] | 3 | marker = marker[arg[1]] or marker['-u'] |
4 | local convert = socket.mime.canonic(marker) | 4 | local convert = socket.mime.normalize(marker) |
5 | while 1 do | 5 | while 1 do |
6 | local chunk = io.read(4096) | 6 | local chunk = io.read(1) |
7 | io.write(convert(chunk)) | 7 | io.write(convert(chunk)) |
8 | if not chunk then break end | 8 | if not chunk then break end |
9 | end | 9 | end |
@@ -2,10 +2,10 @@ local convert | |||
2 | arg = arg or {} | 2 | arg = arg or {} |
3 | local mode = arg and arg[1] or "-et" | 3 | local mode = arg and arg[1] or "-et" |
4 | if mode == "-et" then | 4 | if mode == "-et" then |
5 | local canonic = socket.mime.canonic() | 5 | local normalize = socket.mime.normalize() |
6 | local qp = socket.mime.encode("quoted-printable") | 6 | local qp = socket.mime.encode("quoted-printable") |
7 | local wrap = socket.mime.wrap("quoted-printable") | 7 | local wrap = socket.mime.wrap("quoted-printable") |
8 | convert = socket.mime.chain(canonic, qp, wrap) | 8 | convert = socket.mime.chain(normalize, qp, wrap) |
9 | elseif mode == "-eb" then | 9 | elseif mode == "-eb" then |
10 | local qp = socket.mime.encode("quoted-printable", "binary") | 10 | local qp = socket.mime.encode("quoted-printable", "binary") |
11 | local wrap = socket.mime.wrap("quoted-printable") | 11 | local wrap = socket.mime.wrap("quoted-printable") |
diff --git a/src/ltn12.lua b/src/ltn12.lua new file mode 100644 index 0000000..548588a --- /dev/null +++ b/src/ltn12.lua | |||
@@ -0,0 +1,171 @@ | |||
1 | -- create code namespace inside LuaSocket namespace | ||
2 | ltn12 = ltn12 or {} | ||
3 | -- make all module globals fall into mime namespace | ||
4 | setmetatable(ltn12, { __index = _G }) | ||
5 | setfenv(1, ltn12) | ||
6 | |||
7 | -- sub namespaces | ||
8 | filter = {} | ||
9 | source = {} | ||
10 | sink = {} | ||
11 | |||
12 | -- 2048 seems to be better in windows... | ||
13 | BLOCKSIZE = 2048 | ||
14 | |||
15 | -- returns a high level filter that cycles a cycles a low-level filter | ||
16 | function filter.cycle(low, ctx, extra) | ||
17 | return function(chunk) | ||
18 | local ret | ||
19 | ret, ctx = low(ctx, chunk, extra) | ||
20 | return ret | ||
21 | end | ||
22 | end | ||
23 | |||
24 | -- chains two filters together | ||
25 | local function chain2(f1, f2) | ||
26 | return function(chunk) | ||
27 | local ret = f2(f1(chunk)) | ||
28 | if chunk then return ret | ||
29 | else return ret .. f2() end | ||
30 | end | ||
31 | end | ||
32 | |||
33 | -- chains a bunch of filters together | ||
34 | function filter.chain(...) | ||
35 | local f = arg[1] | ||
36 | for i = 2, table.getn(arg) do | ||
37 | f = chain2(f, arg[i]) | ||
38 | end | ||
39 | return f | ||
40 | end | ||
41 | |||
42 | -- create an empty source | ||
43 | function source.empty(err) | ||
44 | return function() | ||
45 | return nil, err | ||
46 | end | ||
47 | end | ||
48 | |||
49 | -- creates a file source | ||
50 | function source.file(handle, io_err) | ||
51 | if handle then | ||
52 | return function() | ||
53 | local chunk = handle:read(BLOCKSIZE) | ||
54 | if not chunk then handle:close() end | ||
55 | return chunk | ||
56 | end | ||
57 | else source.empty(io_err or "unable to open file") end | ||
58 | end | ||
59 | |||
60 | -- turns a fancy source into a simple source | ||
61 | function source.simplify(src) | ||
62 | return function() | ||
63 | local chunk, err_or_new = src() | ||
64 | src = err_or_new or src | ||
65 | if not chunk then return nil, err_or_new | ||
66 | else return chunk end | ||
67 | end | ||
68 | end | ||
69 | |||
70 | -- creates string source | ||
71 | function source.string(s) | ||
72 | if s then | ||
73 | local i = 1 | ||
74 | return function() | ||
75 | local chunk = string.sub(s, i, i+BLOCKSIZE-1) | ||
76 | i = i + BLOCKSIZE | ||
77 | if chunk ~= "" then return chunk | ||
78 | else return nil end | ||
79 | end | ||
80 | else source.empty() end | ||
81 | end | ||
82 | |||
83 | -- creates rewindable source | ||
84 | function source.rewind(src) | ||
85 | local t = {} | ||
86 | src = source.simplify(src) | ||
87 | return function(chunk) | ||
88 | if not chunk then | ||
89 | chunk = table.remove(t) | ||
90 | if not chunk then return src() | ||
91 | else return chunk end | ||
92 | else | ||
93 | table.insert(t, chunk) | ||
94 | end | ||
95 | end | ||
96 | end | ||
97 | |||
98 | -- chains a source with a filter | ||
99 | function source.chain(src, f) | ||
100 | src = source.simplify(src) | ||
101 | local chain = function() | ||
102 | local chunk, err = src() | ||
103 | if not chunk then return f(nil), source.empty(err) | ||
104 | else return f(chunk) end | ||
105 | end | ||
106 | return source.simplify(chain) | ||
107 | end | ||
108 | |||
109 | -- creates a sink that stores into a table | ||
110 | function sink.table(t) | ||
111 | t = t or {} | ||
112 | local f = function(chunk, err) | ||
113 | if chunk then table.insert(t, chunk) end | ||
114 | return 1 | ||
115 | end | ||
116 | return f, t | ||
117 | end | ||
118 | |||
119 | -- turns a fancy sink into a simple sink | ||
120 | function sink.simplify(snk) | ||
121 | return function(chunk, err) | ||
122 | local ret, err_or_new = snk(chunk, err) | ||
123 | if not ret then return nil, err_or_new end | ||
124 | snk = err_or_new or snk | ||
125 | return 1 | ||
126 | end | ||
127 | end | ||
128 | |||
129 | -- creates a file sink | ||
130 | function sink.file(handle, io_err) | ||
131 | if handle then | ||
132 | return function(chunk, err) | ||
133 | if not chunk then | ||
134 | handle:close() | ||
135 | return nil, err | ||
136 | end | ||
137 | return handle:write(chunk) | ||
138 | end | ||
139 | else sink.null() end | ||
140 | end | ||
141 | |||
142 | -- creates a sink that discards data | ||
143 | local function null() | ||
144 | return 1 | ||
145 | end | ||
146 | |||
147 | function sink.null() | ||
148 | return null | ||
149 | end | ||
150 | |||
151 | -- chains a sink with a filter | ||
152 | function sink.chain(f, snk) | ||
153 | snk = sink.simplify(snk) | ||
154 | return function(chunk, err) | ||
155 | local r, e = snk(f(chunk)) | ||
156 | if not r then return nil, e end | ||
157 | if not chunk then return snk(nil, err) end | ||
158 | return 1 | ||
159 | end | ||
160 | end | ||
161 | |||
162 | -- pumps all data from a source to a sink | ||
163 | function pump(src, snk) | ||
164 | snk = sink.simplify(snk) | ||
165 | for chunk, src_err in source.simplify(src) do | ||
166 | local ret, snk_err = snk(chunk, src_err) | ||
167 | if not chunk or not ret then | ||
168 | return not src_err and not snk_err, src_err or snk_err | ||
169 | end | ||
170 | end | ||
171 | end | ||
diff --git a/src/luasocket.c b/src/luasocket.c index e99fcdf..47696cb 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
@@ -72,6 +72,7 @@ static int mod_open(lua_State *L, const luaL_reg *mod) | |||
72 | { | 72 | { |
73 | for (; mod->name; mod++) mod->func(L); | 73 | for (; mod->name; mod++) mod->func(L); |
74 | #ifdef LUASOCKET_COMPILED | 74 | #ifdef LUASOCKET_COMPILED |
75 | #include "ltn12.lch" | ||
75 | #include "auxiliar.lch" | 76 | #include "auxiliar.lch" |
76 | #include "concat.lch" | 77 | #include "concat.lch" |
77 | #include "url.lch" | 78 | #include "url.lch" |
@@ -81,6 +82,7 @@ static int mod_open(lua_State *L, const luaL_reg *mod) | |||
81 | #include "ftp.lch" | 82 | #include "ftp.lch" |
82 | #include "http.lch" | 83 | #include "http.lch" |
83 | #else | 84 | #else |
85 | lua_dofile(L, "ltn12.lua"); | ||
84 | lua_dofile(L, "auxiliar.lua"); | 86 | lua_dofile(L, "auxiliar.lua"); |
85 | lua_dofile(L, "concat.lua"); | 87 | lua_dofile(L, "concat.lua"); |
86 | lua_dofile(L, "url.lua"); | 88 | lua_dofile(L, "url.lua"); |
@@ -9,8 +9,6 @@ | |||
9 | #include <lua.h> | 9 | #include <lua.h> |
10 | #include <lauxlib.h> | 10 | #include <lauxlib.h> |
11 | 11 | ||
12 | #include "luasocket.h" | ||
13 | #include "auxiliar.h" | ||
14 | #include "mime.h" | 12 | #include "mime.h" |
15 | 13 | ||
16 | /*=========================================================================*\ | 14 | /*=========================================================================*\ |
@@ -83,12 +81,10 @@ static UC b64unbase[256]; | |||
83 | \*-------------------------------------------------------------------------*/ | 81 | \*-------------------------------------------------------------------------*/ |
84 | int mime_open(lua_State *L) | 82 | int mime_open(lua_State *L) |
85 | { | 83 | { |
86 | lua_pushstring(L, LUASOCKET_LIBNAME); | ||
87 | lua_gettable(L, LUA_GLOBALSINDEX); | ||
88 | lua_pushstring(L, "mime"); | 84 | lua_pushstring(L, "mime"); |
89 | lua_newtable(L); | 85 | lua_newtable(L); |
90 | luaL_openlib(L, NULL, func, 0); | 86 | luaL_openlib(L, NULL, func, 0); |
91 | lua_settable(L, -3); | 87 | lua_settable(L, LUA_GLOBALSINDEX); |
92 | lua_pop(L, 1); | 88 | lua_pop(L, 1); |
93 | /* initialize lookup tables */ | 89 | /* initialize lookup tables */ |
94 | qpsetup(qpclass, qpunbase); | 90 | qpsetup(qpclass, qpunbase); |
@@ -110,7 +106,7 @@ static int mime_global_wrp(lua_State *L) | |||
110 | { | 106 | { |
111 | size_t size = 0; | 107 | size_t size = 0; |
112 | int left = (int) luaL_checknumber(L, 1); | 108 | int left = (int) luaL_checknumber(L, 1); |
113 | const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size); | 109 | const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size); |
114 | const UC *last = input + size; | 110 | const UC *last = input + size; |
115 | int length = (int) luaL_optnumber(L, 3, 76); | 111 | int length = (int) luaL_optnumber(L, 3, 76); |
116 | luaL_Buffer buffer; | 112 | luaL_Buffer buffer; |
@@ -261,7 +257,7 @@ static int mime_global_b64(lua_State *L) | |||
261 | luaL_buffinit(L, &buffer); | 257 | luaL_buffinit(L, &buffer); |
262 | while (input < last) | 258 | while (input < last) |
263 | asize = b64encode(*input++, atom, asize, &buffer); | 259 | asize = b64encode(*input++, atom, asize, &buffer); |
264 | input = (UC *) aux_optlstring(L, 2, NULL, &isize); | 260 | input = (UC *) luaL_optlstring(L, 2, NULL, &isize); |
265 | if (input) { | 261 | if (input) { |
266 | last = input + isize; | 262 | last = input + isize; |
267 | while (input < last) | 263 | while (input < last) |
@@ -289,7 +285,7 @@ static int mime_global_unb64(lua_State *L) | |||
289 | luaL_buffinit(L, &buffer); | 285 | luaL_buffinit(L, &buffer); |
290 | while (input < last) | 286 | while (input < last) |
291 | asize = b64decode(*input++, atom, asize, &buffer); | 287 | asize = b64decode(*input++, atom, asize, &buffer); |
292 | input = (UC *) aux_optlstring(L, 2, NULL, &isize); | 288 | input = (UC *) luaL_optlstring(L, 2, NULL, &isize); |
293 | if (input) { | 289 | if (input) { |
294 | last = input + isize; | 290 | last = input + isize; |
295 | while (input < last) | 291 | while (input < last) |
@@ -426,14 +422,14 @@ static int mime_global_qp(lua_State *L) | |||
426 | 422 | ||
427 | size_t asize = 0, isize = 0; | 423 | size_t asize = 0, isize = 0; |
428 | UC atom[3]; | 424 | UC atom[3]; |
429 | const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize); | 425 | const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); |
430 | const UC *last = input + isize; | 426 | const UC *last = input + isize; |
431 | const char *marker = luaL_optstring(L, 3, CRLF); | 427 | const char *marker = luaL_optstring(L, 3, CRLF); |
432 | luaL_Buffer buffer; | 428 | luaL_Buffer buffer; |
433 | luaL_buffinit(L, &buffer); | 429 | luaL_buffinit(L, &buffer); |
434 | while (input < last) | 430 | while (input < last) |
435 | asize = qpencode(*input++, atom, asize, marker, &buffer); | 431 | asize = qpencode(*input++, atom, asize, marker, &buffer); |
436 | input = (UC *) aux_optlstring(L, 2, NULL, &isize); | 432 | input = (UC *) luaL_optlstring(L, 2, NULL, &isize); |
437 | if (input) { | 433 | if (input) { |
438 | last = input + isize; | 434 | last = input + isize; |
439 | while (input < last) | 435 | while (input < last) |
@@ -495,13 +491,13 @@ static int mime_global_unqp(lua_State *L) | |||
495 | 491 | ||
496 | size_t asize = 0, isize = 0; | 492 | size_t asize = 0, isize = 0; |
497 | UC atom[3]; | 493 | UC atom[3]; |
498 | const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize); | 494 | const UC *input = (UC *) luaL_optlstring(L, 1, NULL, &isize); |
499 | const UC *last = input + isize; | 495 | const UC *last = input + isize; |
500 | luaL_Buffer buffer; | 496 | luaL_Buffer buffer; |
501 | luaL_buffinit(L, &buffer); | 497 | luaL_buffinit(L, &buffer); |
502 | while (input < last) | 498 | while (input < last) |
503 | asize = qpdecode(*input++, atom, asize, &buffer); | 499 | asize = qpdecode(*input++, atom, asize, &buffer); |
504 | input = (UC *) aux_optlstring(L, 2, NULL, &isize); | 500 | input = (UC *) luaL_optlstring(L, 2, NULL, &isize); |
505 | if (input) { | 501 | if (input) { |
506 | last = input + isize; | 502 | last = input + isize; |
507 | while (input < last) | 503 | while (input < last) |
@@ -525,7 +521,7 @@ static int mime_global_qpwrp(lua_State *L) | |||
525 | { | 521 | { |
526 | size_t size = 0; | 522 | size_t size = 0; |
527 | int left = (int) luaL_checknumber(L, 1); | 523 | int left = (int) luaL_checknumber(L, 1); |
528 | const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size); | 524 | const UC *input = (UC *) luaL_optlstring(L, 2, NULL, &size); |
529 | const UC *last = input + size; | 525 | const UC *last = input + size; |
530 | int length = (int) luaL_optnumber(L, 3, 76); | 526 | int length = (int) luaL_optnumber(L, 3, 76); |
531 | luaL_Buffer buffer; | 527 | luaL_Buffer buffer; |
@@ -576,54 +572,52 @@ static int mime_global_qpwrp(lua_State *L) | |||
576 | * probably other more obscure conventions. | 572 | * probably other more obscure conventions. |
577 | \*-------------------------------------------------------------------------*/ | 573 | \*-------------------------------------------------------------------------*/ |
578 | #define eolcandidate(c) (c == CR || c == LF) | 574 | #define eolcandidate(c) (c == CR || c == LF) |
579 | static size_t eolconvert(UC c, UC *input, size_t size, | 575 | static size_t eolprocess(int c, int ctx, const char *marker, |
580 | const char *marker, luaL_Buffer *buffer) | 576 | luaL_Buffer *buffer) |
581 | { | 577 | { |
582 | input[size++] = c; | 578 | if (eolcandidate(ctx)) { |
583 | /* deal with all characters we can deal */ | ||
584 | if (eolcandidate(input[0])) { | ||
585 | if (size < 2) return size; | ||
586 | luaL_addstring(buffer, marker); | 579 | luaL_addstring(buffer, marker); |
587 | if (eolcandidate(input[1])) { | 580 | if (eolcandidate(c)) { |
588 | if (input[0] == input[1]) luaL_addstring(buffer, marker); | 581 | if (c == ctx) |
589 | } else luaL_putchar(buffer, input[1]); | 582 | luaL_addstring(buffer, marker); |
590 | return 0; | 583 | return 0; |
584 | } else { | ||
585 | luaL_putchar(buffer, c); | ||
586 | return 0; | ||
587 | } | ||
591 | } else { | 588 | } else { |
592 | luaL_putchar(buffer, input[0]); | 589 | if (!eolcandidate(c)) { |
593 | return 0; | 590 | luaL_putchar(buffer, c); |
591 | return 0; | ||
592 | } else | ||
593 | return c; | ||
594 | } | 594 | } |
595 | } | 595 | } |
596 | 596 | ||
597 | /*-------------------------------------------------------------------------*\ | 597 | /*-------------------------------------------------------------------------*\ |
598 | * Converts a string to uniform EOL convention. | 598 | * Converts a string to uniform EOL convention. |
599 | * A, B = eol(C, D, marker) | 599 | * A, n = eol(o, B, marker) |
600 | * A is the converted version of the largest prefix of C .. D that | 600 | * A is the converted version of the largest prefix of B that can be |
601 | * can be converted without doubts. | 601 | * converted unambiguously. 'o' is the context returned by the previous |
602 | * B has the remaining bytes of C .. D, *without* convertion. | 602 | * call. 'n' is the new context. |
603 | \*-------------------------------------------------------------------------*/ | 603 | \*-------------------------------------------------------------------------*/ |
604 | static int mime_global_eol(lua_State *L) | 604 | static int mime_global_eol(lua_State *L) |
605 | { | 605 | { |
606 | size_t asize = 0, isize = 0; | 606 | int ctx = luaL_checkint(L, 1); |
607 | UC atom[2]; | 607 | size_t isize = 0; |
608 | const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize); | 608 | const char *input = luaL_optlstring(L, 2, NULL, &isize); |
609 | const UC *last = input + isize; | 609 | const char *last = input + isize; |
610 | const char *marker = luaL_optstring(L, 3, CRLF); | 610 | const char *marker = luaL_optstring(L, 3, CRLF); |
611 | luaL_Buffer buffer; | 611 | luaL_Buffer buffer; |
612 | luaL_buffinit(L, &buffer); | 612 | luaL_buffinit(L, &buffer); |
613 | while (input < last) | 613 | while (input < last) |
614 | asize = eolconvert(*input++, atom, asize, marker, &buffer); | 614 | ctx = eolprocess(*input++, ctx, marker, &buffer); |
615 | input = (UC *) aux_optlstring(L, 2, NULL, &isize); | 615 | /* if the last character was a candidate, we output a new line */ |
616 | if (input) { | 616 | if (!input) { |
617 | last = input + isize; | 617 | if (eolcandidate(ctx)) luaL_addstring(&buffer, marker); |
618 | while (input < last) | 618 | ctx = 0; |
619 | asize = eolconvert(*input++, atom, asize, marker, &buffer); | ||
620 | /* if there is something in atom, it's one character, and it | ||
621 | * is a candidate. so we output a new line */ | ||
622 | } else if (asize > 0) { | ||
623 | luaL_addstring(&buffer, marker); | ||
624 | asize = 0; | ||
625 | } | 619 | } |
626 | luaL_pushresult(&buffer); | 620 | luaL_pushresult(&buffer); |
627 | lua_pushlstring(L, (char *) atom, asize); | 621 | lua_pushnumber(L, ctx); |
628 | return 2; | 622 | return 2; |
629 | } | 623 | } |
diff --git a/src/mime.lua b/src/mime.lua index 369567f..4df0388 100644 --- a/src/mime.lua +++ b/src/mime.lua | |||
@@ -1,11 +1,6 @@ | |||
1 | -- make sure LuaSocket is loaded | 1 | if not ltn12 then error('This module requires LTN12') end |
2 | if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end | 2 | -- create mime namespace |
3 | -- get LuaSocket namespace | 3 | mime = mime or {} |
4 | local socket = _G[LUASOCKET_LIBNAME] | ||
5 | if not socket then error('module requires LuaSocket') end | ||
6 | -- create code namespace inside LuaSocket namespace | ||
7 | local mime = socket.mime or {} | ||
8 | socket.mime = mime | ||
9 | -- make all module globals fall into mime namespace | 4 | -- make all module globals fall into mime namespace |
10 | setmetatable(mime, { __index = _G }) | 5 | setmetatable(mime, { __index = _G }) |
11 | setfenv(1, mime) | 6 | setfenv(1, mime) |
@@ -15,80 +10,61 @@ local et = {} | |||
15 | local dt = {} | 10 | local dt = {} |
16 | local wt = {} | 11 | local wt = {} |
17 | 12 | ||
18 | -- creates a function that chooses a filter from a given table | 13 | -- creates a function that chooses a filter by name from a given table |
19 | local function choose(table) | 14 | local function choose(table) |
20 | return function(filter, ...) | 15 | return function(name, opt) |
21 | local f = table[filter or "nil"] | 16 | local f = table[name or "nil"] |
22 | if not f then error("unknown filter (" .. tostring(filter) .. ")", 3) | 17 | if not f then error("unknown filter (" .. tostring(name) .. ")", 3) |
23 | else return f(unpack(arg)) end | 18 | else return f(opt) end |
24 | end | 19 | end |
25 | end | 20 | end |
26 | 21 | ||
27 | -- define the encoding filters | 22 | -- define the encoding filters |
28 | et['base64'] = function() | 23 | et['base64'] = function() |
29 | return socket.cicle(b64, "") | 24 | return ltn12.filter.cycle(b64, "") |
30 | end | 25 | end |
31 | 26 | ||
32 | et['quoted-printable'] = function(mode) | 27 | et['quoted-printable'] = function(mode) |
33 | return socket.cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10") | 28 | return ltn12.filter.cycle(qp, "", |
29 | (mode == "binary") and "=0D=0A" or "\13\10") | ||
34 | end | 30 | end |
35 | 31 | ||
36 | -- define the decoding filters | 32 | -- define the decoding filters |
37 | dt['base64'] = function() | 33 | dt['base64'] = function() |
38 | return socket.cicle(unb64, "") | 34 | return ltn12.filter.cycle(unb64, "") |
39 | end | 35 | end |
40 | 36 | ||
41 | dt['quoted-printable'] = function() | 37 | dt['quoted-printable'] = function() |
42 | return socket.cicle(unqp, "") | 38 | return ltn12.filter.cycle(unqp, "") |
43 | end | 39 | end |
44 | 40 | ||
45 | -- define the line-wrap filters | 41 | -- define the line-wrap filters |
46 | wt['text'] = function(length) | 42 | wt['text'] = function(length) |
47 | length = length or 76 | 43 | length = length or 76 |
48 | return socket.cicle(wrp, length, length) | 44 | return ltn12.filter.cycle(wrp, length, length) |
49 | end | 45 | end |
50 | wt['base64'] = wt['text'] | 46 | wt['base64'] = wt['text'] |
51 | 47 | ||
52 | wt['quoted-printable'] = function() | 48 | wt['quoted-printable'] = function() |
53 | return socket.cicle(qpwrp, 76, 76) | 49 | return ltn12.filter.cycle(qpwrp, 76, 76) |
54 | end | 50 | end |
55 | 51 | ||
56 | -- function that choose the encoding, decoding or wrap algorithm | 52 | -- function that choose the encoding, decoding or wrap algorithm |
57 | encode = choose(et) | 53 | encode = choose(et) |
58 | decode = choose(dt) | 54 | decode = choose(dt) |
59 | -- there is a default wrap filter | 55 | -- there is different because there is a default wrap filter |
60 | local cwt = choose(wt) | 56 | local cwt = choose(wt) |
61 | function wrap(...) | 57 | function wrap(mode_or_length, length) |
62 | if type(arg[1]) ~= "string" then table.insert(arg, 1, "text") end | 58 | if type(mode_or_length) ~= "string" then |
63 | return cwt(unpack(arg)) | 59 | length = mode_or_length |
64 | end | 60 | mode_or_length = "text" |
65 | 61 | end | |
66 | -- define the end-of-line translation filter | 62 | return cwt(mode_or_length, length) |
67 | function canonic(marker) | ||
68 | return socket.cicle(eol, "", marker) | ||
69 | end | 63 | end |
70 | 64 | ||
71 | -- chains several filters together | 65 | -- define the end-of-line normalization filter |
72 | function chain(...) | 66 | function normalize(marker) |
73 | local layers = table.getn(arg) | 67 | return ltn12.filter.cycle(eol, 0, marker) |
74 | return function (chunk) | ||
75 | if not chunk then | ||
76 | local parts = {} | ||
77 | for i = 1, layers do | ||
78 | for j = i, layers do | ||
79 | chunk = arg[j](chunk) | ||
80 | end | ||
81 | table.insert(parts, chunk) | ||
82 | chunk = nil | ||
83 | end | ||
84 | return table.concat(parts) | ||
85 | else | ||
86 | for j = 1, layers do | ||
87 | chunk = arg[j](chunk) | ||
88 | end | ||
89 | return chunk | ||
90 | end | ||
91 | end | ||
92 | end | 68 | end |
93 | 69 | ||
94 | return mime | 70 | return mime |
diff --git a/src/wsocket.c b/src/wsocket.c index fcd2fff..2993c35 100644 --- a/src/wsocket.c +++ b/src/wsocket.c | |||
@@ -191,7 +191,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, | |||
191 | int timeout) | 191 | int timeout) |
192 | { | 192 | { |
193 | t_sock sock = *ps; | 193 | t_sock sock = *ps; |
194 | ssize_t put; | 194 | int put; |
195 | int ret; | 195 | int ret; |
196 | /* avoid making system calls on closed sockets */ | 196 | /* avoid making system calls on closed sockets */ |
197 | if (sock == SOCK_INVALID) return IO_CLOSED; | 197 | if (sock == SOCK_INVALID) return IO_CLOSED; |
@@ -227,7 +227,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
227 | SA *addr, socklen_t addr_len, int timeout) | 227 | SA *addr, socklen_t addr_len, int timeout) |
228 | { | 228 | { |
229 | t_sock sock = *ps; | 229 | t_sock sock = *ps; |
230 | ssize_t put; | 230 | int put; |
231 | int ret; | 231 | int ret; |
232 | /* avoid making system calls on closed sockets */ | 232 | /* avoid making system calls on closed sockets */ |
233 | if (sock == SOCK_INVALID) return IO_CLOSED; | 233 | if (sock == SOCK_INVALID) return IO_CLOSED; |
@@ -262,7 +262,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, | |||
262 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) | 262 | int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) |
263 | { | 263 | { |
264 | t_sock sock = *ps; | 264 | t_sock sock = *ps; |
265 | ssize_t taken; | 265 | int taken; |
266 | if (sock == SOCK_INVALID) return IO_CLOSED; | 266 | if (sock == SOCK_INVALID) return IO_CLOSED; |
267 | taken = recv(sock, data, (int) count, 0); | 267 | taken = recv(sock, data, (int) count, 0); |
268 | if (taken <= 0) { | 268 | if (taken <= 0) { |
@@ -288,7 +288,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, | |||
288 | SA *addr, socklen_t *addr_len, int timeout) | 288 | SA *addr, socklen_t *addr_len, int timeout) |
289 | { | 289 | { |
290 | t_sock sock = *ps; | 290 | t_sock sock = *ps; |
291 | ssize_t taken; | 291 | int taken; |
292 | if (sock == SOCK_INVALID) return IO_CLOSED; | 292 | if (sock == SOCK_INVALID) return IO_CLOSED; |
293 | taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); | 293 | taken = recvfrom(sock, data, (int) count, 0, addr, addr_len); |
294 | if (taken <= 0) { | 294 | if (taken <= 0) { |
diff --git a/src/wsocket.h b/src/wsocket.h index d77841e..c048c58 100644 --- a/src/wsocket.h +++ b/src/wsocket.h | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <winsock.h> | 13 | #include <winsock.h> |
14 | 14 | ||
15 | typedef int socklen_t; | 15 | typedef int socklen_t; |
16 | typedef int ssize_t; | ||
17 | typedef SOCKET t_sock; | 16 | typedef SOCKET t_sock; |
18 | typedef t_sock *p_sock; | 17 | typedef t_sock *p_sock; |
19 | 18 | ||
diff --git a/test/ltn12test.lua b/test/ltn12test.lua new file mode 100644 index 0000000..1c1f3f2 --- /dev/null +++ b/test/ltn12test.lua | |||
@@ -0,0 +1,3 @@ | |||
1 | sink = ltn12.sink.file(io.open("lixo", "w")) | ||
2 | source = ltn12.source.file(io.open("luasocket", "r")) | ||
3 | ltn12.pump(source, sink) | ||
diff --git a/test/mimetest.lua b/test/mimetest.lua index 5a461fa..1a7e427 100644 --- a/test/mimetest.lua +++ b/test/mimetest.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | dofile("noglobals.lua") | 1 | dofile("testsupport.lua") |
2 | 2 | ||
3 | local qptest = "qptest.bin" | 3 | local qptest = "qptest.bin" |
4 | local eqptest = "qptest.bin2" | 4 | local eqptest = "qptest.bin2" |
@@ -31,26 +31,13 @@ local mao = [[ | |||
31 | assim, nem tudo o que dava exprimia grande confiança. | 31 | assim, nem tudo o que dava exprimia grande confiança. |
32 | ]] | 32 | ]] |
33 | 33 | ||
34 | local fail = function(s) | ||
35 | s = s or "failed" | ||
36 | assert(nil, s) | ||
37 | end | ||
38 | |||
39 | local readfile = function(name) | ||
40 | local f = io.open(name, "r") | ||
41 | if not f then return nil end | ||
42 | local s = f:read("*a") | ||
43 | f:close() | ||
44 | return s | ||
45 | end | ||
46 | |||
47 | local function transform(input, output, filter) | 34 | local function transform(input, output, filter) |
48 | local fi, err = io.open(input, "rb") | 35 | local fi, err = io.open(input, "rb") |
49 | if not fi then fail(err) end | 36 | if not fi then fail(err) end |
50 | local fo, err = io.open(output, "wb") | 37 | local fo, err = io.open(output, "wb") |
51 | if not fo then fail(err) end | 38 | if not fo then fail(err) end |
52 | while 1 do | 39 | while 1 do |
53 | local chunk = fi:read(math.random(0, 256)) | 40 | local chunk = fi:read(math.random(0, 1024)) |
54 | fo:write(filter(chunk)) | 41 | fo:write(filter(chunk)) |
55 | if not chunk then break end | 42 | if not chunk then break end |
56 | end | 43 | end |
@@ -58,17 +45,10 @@ local function transform(input, output, filter) | |||
58 | fo:close() | 45 | fo:close() |
59 | end | 46 | end |
60 | 47 | ||
61 | local function compare(input, output) | ||
62 | local original = readfile(input) | ||
63 | local recovered = readfile(output) | ||
64 | if original ~= recovered then fail("recovering failed") | ||
65 | else print("ok") end | ||
66 | end | ||
67 | |||
68 | local function encode_qptest(mode) | 48 | local function encode_qptest(mode) |
69 | local encode = socket.mime.encode("quoted-printable", mode) | 49 | local encode = mime.encode("quoted-printable", mode) |
70 | local split = socket.mime.wrap("quoted-printable") | 50 | local split = mime.wrap("quoted-printable") |
71 | local chain = socket.mime.chain(encode, split) | 51 | local chain = ltn12.filter.chain(encode, split) |
72 | transform(qptest, eqptest, chain) | 52 | transform(qptest, eqptest, chain) |
73 | end | 53 | end |
74 | 54 | ||
@@ -77,7 +57,7 @@ local function compare_qptest() | |||
77 | end | 57 | end |
78 | 58 | ||
79 | local function decode_qptest() | 59 | local function decode_qptest() |
80 | local decode = socket.mime.decode("quoted-printable") | 60 | local decode = mime.decode("quoted-printable") |
81 | transform(eqptest, dqptest, decode) | 61 | transform(eqptest, dqptest, decode) |
82 | end | 62 | end |
83 | 63 | ||
@@ -151,24 +131,24 @@ local function cleanup_qptest() | |||
151 | end | 131 | end |
152 | 132 | ||
153 | local function encode_b64test() | 133 | local function encode_b64test() |
154 | local e1 = socket.mime.encode("base64") | 134 | local e1 = mime.encode("base64") |
155 | local e2 = socket.mime.encode("base64") | 135 | local e2 = mime.encode("base64") |
156 | local e3 = socket.mime.encode("base64") | 136 | local e3 = mime.encode("base64") |
157 | local e4 = socket.mime.encode("base64") | 137 | local e4 = mime.encode("base64") |
158 | local sp4 = socket.mime.wrap() | 138 | local sp4 = mime.wrap() |
159 | local sp3 = socket.mime.wrap(59) | 139 | local sp3 = mime.wrap(59) |
160 | local sp2 = socket.mime.wrap("base64", 30) | 140 | local sp2 = mime.wrap("base64", 30) |
161 | local sp1 = socket.mime.wrap(27) | 141 | local sp1 = mime.wrap(27) |
162 | local chain = socket.mime.chain(e1, sp1, e2, sp2, e3, sp3, e4, sp4) | 142 | local chain = ltn12.filter.chain(e1, sp1, e2, sp2, e3, sp3, e4, sp4) |
163 | transform(b64test, eb64test, chain) | 143 | transform(b64test, eb64test, chain) |
164 | end | 144 | end |
165 | 145 | ||
166 | local function decode_b64test() | 146 | local function decode_b64test() |
167 | local d1 = socket.mime.decode("base64") | 147 | local d1 = mime.decode("base64") |
168 | local d2 = socket.mime.decode("base64") | 148 | local d2 = mime.decode("base64") |
169 | local d3 = socket.mime.decode("base64") | 149 | local d3 = mime.decode("base64") |
170 | local d4 = socket.mime.decode("base64") | 150 | local d4 = mime.decode("base64") |
171 | local chain = socket.mime.chain(d1, d2, d3, d4) | 151 | local chain = ltn12.filter.chain(d1, d2, d3, d4) |
172 | transform(eb64test, db64test, chain) | 152 | transform(eb64test, db64test, chain) |
173 | end | 153 | end |
174 | 154 | ||
@@ -182,11 +162,11 @@ local function compare_b64test() | |||
182 | end | 162 | end |
183 | 163 | ||
184 | local function identity_test() | 164 | local function identity_test() |
185 | local chain = socket.mime.chain( | 165 | local chain = ltn12.filter.chain( |
186 | socket.mime.encode("quoted-printable"), | 166 | mime.encode("quoted-printable"), |
187 | socket.mime.encode("base64"), | 167 | mime.encode("base64"), |
188 | socket.mime.decode("base64"), | 168 | mime.decode("base64"), |
189 | socket.mime.decode("quoted-printable") | 169 | mime.decode("quoted-printable") |
190 | ) | 170 | ) |
191 | transform(b64test, eb64test, chain) | 171 | transform(b64test, eb64test, chain) |
192 | compare(b64test, eb64test) | 172 | compare(b64test, eb64test) |
@@ -195,8 +175,8 @@ end | |||
195 | 175 | ||
196 | 176 | ||
197 | local function padcheck(original, encoded) | 177 | local function padcheck(original, encoded) |
198 | local e = (socket.mime.b64(original)) | 178 | local e = (mime.b64(original)) |
199 | local d = (socket.mime.unb64(encoded)) | 179 | local d = (mime.unb64(encoded)) |
200 | if e ~= encoded then fail("encoding failed") end | 180 | if e ~= encoded then fail("encoding failed") end |
201 | if d ~= original then fail("decoding failed") end | 181 | if d ~= original then fail("decoding failed") end |
202 | end | 182 | end |
@@ -206,8 +186,8 @@ local function chunkcheck(original, encoded) | |||
206 | for i = 0, len do | 186 | for i = 0, len do |
207 | local a = string.sub(original, 1, i) | 187 | local a = string.sub(original, 1, i) |
208 | local b = string.sub(original, i+1) | 188 | local b = string.sub(original, i+1) |
209 | local e, r = socket.mime.b64(a, b) | 189 | local e, r = mime.b64(a, b) |
210 | local f = (socket.mime.b64(r)) | 190 | local f = (mime.b64(r)) |
211 | if (e .. f ~= encoded) then fail(e .. f) end | 191 | if (e .. f ~= encoded) then fail(e .. f) end |
212 | end | 192 | end |
213 | end | 193 | end |
@@ -231,6 +211,13 @@ end | |||
231 | 211 | ||
232 | local t = socket.time() | 212 | local t = socket.time() |
233 | 213 | ||
214 | identity_test() | ||
215 | encode_b64test() | ||
216 | decode_b64test() | ||
217 | compare_b64test() | ||
218 | cleanup_b64test() | ||
219 | padding_b64test() | ||
220 | |||
234 | create_qptest() | 221 | create_qptest() |
235 | encode_qptest() | 222 | encode_qptest() |
236 | decode_qptest() | 223 | decode_qptest() |
@@ -240,12 +227,4 @@ decode_qptest() | |||
240 | compare_qptest() | 227 | compare_qptest() |
241 | cleanup_qptest() | 228 | cleanup_qptest() |
242 | 229 | ||
243 | encode_b64test() | ||
244 | decode_b64test() | ||
245 | compare_b64test() | ||
246 | cleanup_b64test() | ||
247 | padding_b64test() | ||
248 | |||
249 | identity_test() | ||
250 | |||
251 | print(string.format("done in %.2fs", socket.time() - t)) | 230 | print(string.format("done in %.2fs", socket.time() - t)) |