aboutsummaryrefslogtreecommitdiff
path: root/src/mime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mime.c')
-rw-r--r--src/mime.c138
1 files changed, 65 insertions, 73 deletions
diff --git a/src/mime.c b/src/mime.c
index 95cd400..9fc4f51 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -10,6 +10,7 @@
10#include <lauxlib.h> 10#include <lauxlib.h>
11 11
12#include "luasocket.h" 12#include "luasocket.h"
13#include "auxiliar.h"
13#include "mime.h" 14#include "mime.h"
14 15
15/*=========================================================================*\ 16/*=========================================================================*\
@@ -45,18 +46,16 @@ static void qpquote(UC c, luaL_Buffer *buffer);
45static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer); 46static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
46static size_t qpencode(UC c, UC *input, size_t size, 47static size_t qpencode(UC c, UC *input, size_t size,
47 const char *marker, luaL_Buffer *buffer); 48 const char *marker, luaL_Buffer *buffer);
48 49static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
49static const char *checklstring(lua_State *L, int n, size_t *l);
50static const char *optlstring(lua_State *L, int n, const char *v, size_t *l);
51 50
52/* code support functions */ 51/* code support functions */
53static luaL_reg func[] = { 52static luaL_reg func[] = {
53 { "b64", mime_global_b64 },
54 { "eol", mime_global_eol }, 54 { "eol", mime_global_eol },
55 { "qp", mime_global_qp }, 55 { "qp", mime_global_qp },
56 { "unqp", mime_global_unqp },
57 { "qpwrp", mime_global_qpwrp }, 56 { "qpwrp", mime_global_qpwrp },
58 { "b64", mime_global_b64 },
59 { "unb64", mime_global_unb64 }, 57 { "unb64", mime_global_unb64 },
58 { "unqp", mime_global_unqp },
60 { "wrp", mime_global_wrp }, 59 { "wrp", mime_global_wrp },
61 { NULL, NULL } 60 { NULL, NULL }
62}; 61};
@@ -82,17 +81,10 @@ static UC b64unbase[256];
82/*-------------------------------------------------------------------------*\ 81/*-------------------------------------------------------------------------*\
83* Initializes module 82* Initializes module
84\*-------------------------------------------------------------------------*/ 83\*-------------------------------------------------------------------------*/
85void mime_open(lua_State *L) 84int mime_open(lua_State *L)
86{ 85{
87 lua_pushstring(L, LUASOCKET_LIBNAME); 86 lua_pushstring(L, LUASOCKET_LIBNAME);
88 lua_gettable(L, LUA_GLOBALSINDEX); 87 lua_gettable(L, LUA_GLOBALSINDEX);
89 if (lua_isnil(L, -1)) {
90 lua_pop(L, 1);
91 lua_newtable(L);
92 lua_pushstring(L, LUASOCKET_LIBNAME);
93 lua_pushvalue(L, -2);
94 lua_settable(L, LUA_GLOBALSINDEX);
95 }
96 lua_pushstring(L, "mime"); 88 lua_pushstring(L, "mime");
97 lua_newtable(L); 89 lua_newtable(L);
98 luaL_openlib(L, NULL, func, 0); 90 luaL_openlib(L, NULL, func, 0);
@@ -101,25 +93,7 @@ void mime_open(lua_State *L)
101 /* initialize lookup tables */ 93 /* initialize lookup tables */
102 qpsetup(qpclass, qpunbase); 94 qpsetup(qpclass, qpunbase);
103 b64setup(b64unbase); 95 b64setup(b64unbase);
104} 96 return 0;
105
106/*-------------------------------------------------------------------------*\
107* Check if a string was provided. We accept false also.
108\*-------------------------------------------------------------------------*/
109static const char *checklstring(lua_State *L, int n, size_t *l)
110{
111 if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
112 *l = 0;
113 return NULL;
114 } else return luaL_checklstring(L, n, l);
115}
116
117static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
118{
119 if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
120 *l = 0;
121 return NULL;
122 } else return luaL_optlstring(L, n, v, l);
123} 97}
124 98
125/*=========================================================================*\ 99/*=========================================================================*\
@@ -127,31 +101,42 @@ static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
127\*=========================================================================*/ 101\*=========================================================================*/
128/*-------------------------------------------------------------------------*\ 102/*-------------------------------------------------------------------------*\
129* Incrementaly breaks a string into lines 103* Incrementaly breaks a string into lines
130* A, n = wrp(l, B, length, marker) 104* A, n = wrp(l, B, length)
131* A is a copy of B, broken into lines of at most 'length' bytes. 105* A is a copy of B, broken into lines of at most 'length' bytes.
132* 'l' is how many bytes are left for the first line of B. 106* 'l' is how many bytes are left for the first line of B.
133* 'n' is the number of bytes left in the last line of A. 107* 'n' is the number of bytes left in the last line of A.
134* Marker is the end-of-line marker.
135\*-------------------------------------------------------------------------*/ 108\*-------------------------------------------------------------------------*/
136static int mime_global_wrp(lua_State *L) 109static int mime_global_wrp(lua_State *L)
137{ 110{
138 size_t size = 0; 111 size_t size = 0;
139 int left = (int) luaL_checknumber(L, 1); 112 int left = (int) luaL_checknumber(L, 1);
140 const UC *input = (UC *) checklstring(L, 2, &size); 113 const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
141 const UC *last = input + size; 114 const UC *last = input + size;
142 int length = (int) luaL_optnumber(L, 3, 76); 115 int length = (int) luaL_optnumber(L, 3, 76);
143 const char *marker = luaL_optstring(L, 4, CRLF);
144 luaL_Buffer buffer; 116 luaL_Buffer buffer;
145 luaL_buffinit(L, &buffer); 117 luaL_buffinit(L, &buffer);
146 while (input < last) { 118 while (input < last) {
147 luaL_putchar(&buffer, *input++); 119 switch (*input) {
148 if (--left <= 0) { 120 case CR:
149 luaL_addstring(&buffer, marker); 121 break;
150 left = length; 122 case LF:
123 luaL_addstring(&buffer, CRLF);
124 left = length;
125 break;
126 default:
127 if (left <= 0) {
128 left = length;
129 luaL_addstring(&buffer, CRLF);
130 }
131 luaL_putchar(&buffer, *input);
132 left--;
133 break;
151 } 134 }
135 input++;
152 } 136 }
137 /* if in last chunk and last line wasn't terminated, add a line-break */
153 if (!input && left < length) { 138 if (!input && left < length) {
154 luaL_addstring(&buffer, marker); 139 luaL_addstring(&buffer, CRLF);
155 left = length; 140 left = length;
156 } 141 }
157 luaL_pushresult(&buffer); 142 luaL_pushresult(&buffer);
@@ -235,7 +220,6 @@ static size_t b64pad(const UC *input, size_t size,
235static size_t b64decode(UC c, UC *input, size_t size, 220static size_t b64decode(UC c, UC *input, size_t size,
236 luaL_Buffer *buffer) 221 luaL_Buffer *buffer)
237{ 222{
238
239 /* ignore invalid characters */ 223 /* ignore invalid characters */
240 if (b64unbase[c] > 64) return size; 224 if (b64unbase[c] > 64) return size;
241 input[size++] = c; 225 input[size++] = c;
@@ -277,7 +261,7 @@ static int mime_global_b64(lua_State *L)
277 luaL_buffinit(L, &buffer); 261 luaL_buffinit(L, &buffer);
278 while (input < last) 262 while (input < last)
279 asize = b64encode(*input++, atom, asize, &buffer); 263 asize = b64encode(*input++, atom, asize, &buffer);
280 input = (UC *) optlstring(L, 2, NULL, &isize); 264 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
281 if (input) { 265 if (input) {
282 last = input + isize; 266 last = input + isize;
283 while (input < last) 267 while (input < last)
@@ -305,12 +289,14 @@ static int mime_global_unb64(lua_State *L)
305 luaL_buffinit(L, &buffer); 289 luaL_buffinit(L, &buffer);
306 while (input < last) 290 while (input < last)
307 asize = b64decode(*input++, atom, asize, &buffer); 291 asize = b64decode(*input++, atom, asize, &buffer);
308 input = (UC *) optlstring(L, 2, NULL, &isize); 292 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
309 if (input) { 293 if (input) {
310 last = input + isize; 294 last = input + isize;
311 while (input < last) 295 while (input < last)
312 asize = b64decode(*input++, atom, asize, &buffer); 296 asize = b64decode(*input++, atom, asize, &buffer);
313 } 297 }
298 /* if !input we are done. if atom > 0, the remaning is invalid. we just
299 * return it undecoded. */
314 luaL_pushresult(&buffer); 300 luaL_pushresult(&buffer);
315 lua_pushlstring(L, (char *) atom, asize); 301 lua_pushlstring(L, (char *) atom, asize);
316 return 2; 302 return 2;
@@ -416,7 +402,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
416/*-------------------------------------------------------------------------*\ 402/*-------------------------------------------------------------------------*\
417* Deal with the final characters 403* Deal with the final characters
418\*-------------------------------------------------------------------------*/ 404\*-------------------------------------------------------------------------*/
419static void qppad(UC *input, size_t size, luaL_Buffer *buffer) 405static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
420{ 406{
421 size_t i; 407 size_t i;
422 for (i = 0; i < size; i++) { 408 for (i = 0; i < size; i++) {
@@ -424,12 +410,13 @@ static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
424 else qpquote(input[i], buffer); 410 else qpquote(input[i], buffer);
425 } 411 }
426 luaL_addstring(buffer, EQCRLF); 412 luaL_addstring(buffer, EQCRLF);
413 return 0;
427} 414}
428 415
429/*-------------------------------------------------------------------------*\ 416/*-------------------------------------------------------------------------*\
430* Incrementally converts a string to quoted-printable 417* Incrementally converts a string to quoted-printable
431* A, B = qp(C, D, marker) 418* A, B = qp(C, D, marker)
432* Crlf is the text to be used to replace CRLF sequences found in A. 419* Marker is the text to be used to replace CRLF sequences found in A.
433* A is the encoded version of the largest prefix of C .. D that 420* A is the encoded version of the largest prefix of C .. D that
434* can be encoded without doubts. 421* can be encoded without doubts.
435* B has the remaining bytes of C .. D, *without* encoding. 422* B has the remaining bytes of C .. D, *without* encoding.
@@ -439,19 +426,20 @@ static int mime_global_qp(lua_State *L)
439 426
440 size_t asize = 0, isize = 0; 427 size_t asize = 0, isize = 0;
441 UC atom[3]; 428 UC atom[3];
442 const UC *input = (UC *) checklstring(L, 1, &isize); 429 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
443 const UC *last = input + isize; 430 const UC *last = input + isize;
444 const char *marker = luaL_optstring(L, 3, CRLF); 431 const char *marker = luaL_optstring(L, 3, CRLF);
445 luaL_Buffer buffer; 432 luaL_Buffer buffer;
446 luaL_buffinit(L, &buffer); 433 luaL_buffinit(L, &buffer);
447 while (input < last) 434 while (input < last)
448 asize = qpencode(*input++, atom, asize, marker, &buffer); 435 asize = qpencode(*input++, atom, asize, marker, &buffer);
449 input = (UC *) optlstring(L, 2, NULL, &isize); 436 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
450 if (input) { 437 if (input) {
451 last = input + isize; 438 last = input + isize;
452 while (input < last) 439 while (input < last)
453 asize = qpencode(*input++, atom, asize, marker, &buffer); 440 asize = qpencode(*input++, atom, asize, marker, &buffer);
454 } else qppad(atom, asize, &buffer); 441 } else
442 asize = qppad(atom, asize, &buffer);
455 luaL_pushresult(&buffer); 443 luaL_pushresult(&buffer);
456 lua_pushlstring(L, (char *) atom, asize); 444 lua_pushlstring(L, (char *) atom, asize);
457 return 2; 445 return 2;
@@ -507,13 +495,13 @@ static int mime_global_unqp(lua_State *L)
507 495
508 size_t asize = 0, isize = 0; 496 size_t asize = 0, isize = 0;
509 UC atom[3]; 497 UC atom[3];
510 const UC *input = (UC *) checklstring(L, 1, &isize); 498 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
511 const UC *last = input + isize; 499 const UC *last = input + isize;
512 luaL_Buffer buffer; 500 luaL_Buffer buffer;
513 luaL_buffinit(L, &buffer); 501 luaL_buffinit(L, &buffer);
514 while (input < last) 502 while (input < last)
515 asize = qpdecode(*input++, atom, asize, &buffer); 503 asize = qpdecode(*input++, atom, asize, &buffer);
516 input = (UC *) optlstring(L, 2, NULL, &isize); 504 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
517 if (input) { 505 if (input) {
518 last = input + isize; 506 last = input + isize;
519 while (input < last) 507 while (input < last)
@@ -537,38 +525,39 @@ static int mime_global_qpwrp(lua_State *L)
537{ 525{
538 size_t size = 0; 526 size_t size = 0;
539 int left = (int) luaL_checknumber(L, 1); 527 int left = (int) luaL_checknumber(L, 1);
540 const UC *input = (UC *) checklstring(L, 2, &size); 528 const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
541 const UC *last = input + size; 529 const UC *last = input + size;
542 int length = (int) luaL_optnumber(L, 3, 76); 530 int length = (int) luaL_optnumber(L, 3, 76);
543 luaL_Buffer buffer; 531 luaL_Buffer buffer;
544 luaL_buffinit(L, &buffer); 532 luaL_buffinit(L, &buffer);
545 while (input < last) { 533 while (input < last) {
546 left--;
547 switch (*input) { 534 switch (*input) {
548 case '=': 535 case CR:
549 /* if there's no room in this line for the quoted char,
550 * output a soft line break now */
551 if (left <= 3) {
552 luaL_addstring(&buffer, EQCRLF);
553 left = length;
554 }
555 break;
556 /* \r\n starts a new line */
557 case CR:
558 break; 536 break;
559 case LF: 537 case LF:
560 left = length; 538 left = length;
539 luaL_addstring(&buffer, CRLF);
561 break; 540 break;
562 default: 541 case '=':
563 /* if in last column, output a soft line break */ 542 if (left <= 3) {
564 if (left <= 1) { 543 left = length;
565 luaL_addstring(&buffer, EQCRLF); 544 luaL_addstring(&buffer, EQCRLF);
545 }
546 luaL_putchar(&buffer, *input);
547 left--;
548 break;
549 default:
550 if (left <= 1) {
566 left = length; 551 left = length;
552 luaL_addstring(&buffer, EQCRLF);
567 } 553 }
554 luaL_putchar(&buffer, *input);
555 left--;
556 break;
568 } 557 }
569 luaL_putchar(&buffer, *input);
570 input++; 558 input++;
571 } 559 }
560 /* if in last chunk and last line wasn't terminated, add a soft-break */
572 if (!input && left < length) { 561 if (!input && left < length) {
573 luaL_addstring(&buffer, EQCRLF); 562 luaL_addstring(&buffer, EQCRLF);
574 left = length; 563 left = length;
@@ -579,10 +568,10 @@ static int mime_global_qpwrp(lua_State *L)
579} 568}
580 569
581/*-------------------------------------------------------------------------*\ 570/*-------------------------------------------------------------------------*\
582* Here is what we do: \n, \r and \f are considered candidates for line 571* Here is what we do: \n, and \r are considered candidates for line
583* break. We issue *one* new line marker if any of them is seen alone, or 572* break. We issue *one* new line marker if any of them is seen alone, or
584* followed by a different one. That is, \n\n, \r\r and \f\f will issue two 573* followed by a different one. That is, \n\n and \r\r will issue two
585* end of line markers each, but \r\n, \n\r, \r\f etc will only issue *one* 574* end of line markers each, but \r\n, \n\r etc will only issue *one*
586* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as 575* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as
587* probably other more obscure conventions. 576* probably other more obscure conventions.
588\*-------------------------------------------------------------------------*/ 577\*-------------------------------------------------------------------------*/
@@ -616,21 +605,24 @@ static int mime_global_eol(lua_State *L)
616{ 605{
617 size_t asize = 0, isize = 0; 606 size_t asize = 0, isize = 0;
618 UC atom[2]; 607 UC atom[2];
619 const UC *input = (UC *) checklstring(L, 1, &isize); 608 const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
620 const UC *last = input + isize; 609 const UC *last = input + isize;
621 const char *marker = luaL_optstring(L, 3, CRLF); 610 const char *marker = luaL_optstring(L, 3, CRLF);
622 luaL_Buffer buffer; 611 luaL_Buffer buffer;
623 luaL_buffinit(L, &buffer); 612 luaL_buffinit(L, &buffer);
624 while (input < last) 613 while (input < last)
625 asize = eolconvert(*input++, atom, asize, marker, &buffer); 614 asize = eolconvert(*input++, atom, asize, marker, &buffer);
626 input = (UC *) optlstring(L, 2, NULL, &isize); 615 input = (UC *) aux_optlstring(L, 2, NULL, &isize);
627 if (input) { 616 if (input) {
628 last = input + isize; 617 last = input + isize;
629 while (input < last) 618 while (input < last)
630 asize = eolconvert(*input++, atom, asize, marker, &buffer); 619 asize = eolconvert(*input++, atom, asize, marker, &buffer);
631 /* if there is something in atom, it's one character, and it 620 /* if there is something in atom, it's one character, and it
632 * is a candidate. so we output a new line */ 621 * is a candidate. so we output a new line */
633 } else if (asize > 0) luaL_addstring(&buffer, marker); 622 } else if (asize > 0) {
623 luaL_addstring(&buffer, marker);
624 asize = 0;
625 }
634 luaL_pushresult(&buffer); 626 luaL_pushresult(&buffer);
635 lua_pushlstring(L, (char *) atom, asize); 627 lua_pushlstring(L, (char *) atom, asize);
636 return 2; 628 return 2;