Worked on the manual.
Implemented stuffing (needs test) Added cddb and qp examples.
This commit is contained in:
parent
f67864f86c
commit
0b2542d1a6
37 changed files with 649 additions and 332 deletions
|
@ -37,9 +37,9 @@ error:
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes the module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void aux_open(lua_State *L)
|
||||
int aux_open(lua_State *L)
|
||||
{
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
@ -159,3 +159,13 @@ void *aux_getclassudata(lua_State *L, const char *classname, int objidx)
|
|||
return luaL_checkudata(L, objidx, classname);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Accept "false" as nil
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_optlstring(L, n, v, l);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#define MAX(x, y) ((x) > (y) ? x : y)
|
||||
#endif
|
||||
|
||||
void aux_open(lua_State *L);
|
||||
int aux_open(lua_State *L);
|
||||
void aux_newclass(lua_State *L, const char *classname, luaL_reg *func);
|
||||
void aux_add2group(lua_State *L, const char *classname, const char *group);
|
||||
void aux_setclass(lua_State *L, const char *classname, int objidx);
|
||||
|
@ -49,5 +49,6 @@ void *aux_checkgroup(lua_State *L, const char *groupname, int objidx);
|
|||
void *aux_getclassudata(lua_State *L, const char *groupname, int objidx);
|
||||
void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx);
|
||||
int aux_checkboolean(lua_State *L, int objidx);
|
||||
const char *aux_optlstring(lua_State *L, int n, const char *v, size_t *l);
|
||||
|
||||
#endif /* AUX_H */
|
||||
|
|
|
@ -26,9 +26,10 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent);
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void buf_open(lua_State *L)
|
||||
int buf_open(lua_State *L)
|
||||
{
|
||||
(void) L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef struct t_buf_ {
|
|||
} t_buf;
|
||||
typedef t_buf *p_buf;
|
||||
|
||||
void buf_open(lua_State *L);
|
||||
int buf_open(lua_State *L);
|
||||
void buf_init(p_buf buf, p_io io, p_tm tm);
|
||||
int buf_meth_send(lua_State *L, p_buf buf);
|
||||
int buf_meth_receive(lua_State *L, p_buf buf);
|
||||
|
|
|
@ -649,3 +649,5 @@ function Public.get(url_or_request)
|
|||
local err = Public.get_cb(request)
|
||||
return concat:getresult(), err
|
||||
end
|
||||
|
||||
return ftp
|
||||
|
|
|
@ -11,7 +11,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
|||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local http = {}
|
||||
local http = socket.http or {}
|
||||
socket.http = http
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(http, { __index = _G })
|
||||
|
|
|
@ -35,17 +35,10 @@ static luaL_reg func[] = {
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void inet_open(lua_State *L)
|
||||
int inet_open(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
lua_pushstring(L, "dns");
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, NULL, func, 0);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define INET_ATON
|
||||
#endif
|
||||
|
||||
void inet_open(lua_State *L);
|
||||
int inet_open(lua_State *L);
|
||||
|
||||
const char *inet_trycreate(p_sock ps, int type);
|
||||
const char *inet_tryconnect(p_sock ps, const char *address,
|
||||
|
|
|
@ -33,12 +33,14 @@
|
|||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "select.h"
|
||||
#include "smtp.h"
|
||||
#include "mime.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Declarations
|
||||
\*=========================================================================*/
|
||||
static int base_open(lua_State *L);
|
||||
static int mod_open(lua_State *L, const luaL_reg *mod);
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Setup basic stuff.
|
||||
|
@ -66,22 +68,9 @@ static int base_open(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes all library modules.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LUASOCKET_API int luaopen_socket(lua_State *L)
|
||||
static int mod_open(lua_State *L, const luaL_reg *mod)
|
||||
{
|
||||
if (!sock_open()) return 0;
|
||||
/* initialize all modules */
|
||||
base_open(L);
|
||||
aux_open(L);
|
||||
tm_open(L);
|
||||
buf_open(L);
|
||||
inet_open(L);
|
||||
tcp_open(L);
|
||||
udp_open(L);
|
||||
select_open(L);
|
||||
mime_open(L);
|
||||
for (; mod->name; mod++) mod->func(L);
|
||||
#ifdef LUASOCKET_COMPILED
|
||||
#include "auxiliar.lch"
|
||||
#include "concat.lch"
|
||||
|
@ -101,5 +90,36 @@ LUASOCKET_API int luaopen_socket(lua_State *L)
|
|||
lua_dofile(L, "ftp.lua");
|
||||
lua_dofile(L, "http.lua");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Modules
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static const luaL_reg mod[] = {
|
||||
{"base", base_open},
|
||||
{"aux", aux_open},
|
||||
{"tm", tm_open},
|
||||
{"buf", buf_open},
|
||||
{"inet", inet_open},
|
||||
{"tcp", tcp_open},
|
||||
{"udp", udp_open},
|
||||
{"select", select_open},
|
||||
{"mime", mime_open},
|
||||
{"smtp", smtp_open},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes all library modules.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LUASOCKET_API int luaopen_socket(lua_State *L)
|
||||
{
|
||||
if (!sock_open()) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "unable to initialize library");
|
||||
return 2;
|
||||
}
|
||||
mod_open(L, mod);
|
||||
return 1;
|
||||
}
|
||||
|
|
140
src/mime.c
140
src/mime.c
|
@ -10,6 +10,7 @@
|
|||
#include <lauxlib.h>
|
||||
|
||||
#include "luasocket.h"
|
||||
#include "auxiliar.h"
|
||||
#include "mime.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
|
@ -45,18 +46,16 @@ static void qpquote(UC c, luaL_Buffer *buffer);
|
|||
static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
|
||||
static size_t qpencode(UC c, UC *input, size_t size,
|
||||
const char *marker, luaL_Buffer *buffer);
|
||||
|
||||
static const char *checklstring(lua_State *L, int n, size_t *l);
|
||||
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l);
|
||||
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
|
||||
|
||||
/* code support functions */
|
||||
static luaL_reg func[] = {
|
||||
{ "b64", mime_global_b64 },
|
||||
{ "eol", mime_global_eol },
|
||||
{ "qp", mime_global_qp },
|
||||
{ "unqp", mime_global_unqp },
|
||||
{ "qpwrp", mime_global_qpwrp },
|
||||
{ "b64", mime_global_b64 },
|
||||
{ "unb64", mime_global_unb64 },
|
||||
{ "unqp", mime_global_unqp },
|
||||
{ "wrp", mime_global_wrp },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
@ -82,17 +81,10 @@ static UC b64unbase[256];
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void mime_open(lua_State *L)
|
||||
int mime_open(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_gettable(L, LUA_GLOBALSINDEX);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
lua_pushstring(L, "mime");
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, NULL, func, 0);
|
||||
|
@ -101,25 +93,7 @@ void mime_open(lua_State *L)
|
|||
/* initialize lookup tables */
|
||||
qpsetup(qpclass, qpunbase);
|
||||
b64setup(b64unbase);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Check if a string was provided. We accept false also.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static const char *checklstring(lua_State *L, int n, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_checklstring(L, n, l);
|
||||
}
|
||||
|
||||
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
|
||||
{
|
||||
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
|
||||
*l = 0;
|
||||
return NULL;
|
||||
} else return luaL_optlstring(L, n, v, l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
|
@ -127,31 +101,42 @@ static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
|
|||
\*=========================================================================*/
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Incrementaly breaks a string into lines
|
||||
* A, n = wrp(l, B, length, marker)
|
||||
* A, n = wrp(l, B, length)
|
||||
* A is a copy of B, broken into lines of at most 'length' bytes.
|
||||
* 'l' is how many bytes are left for the first line of B.
|
||||
* 'n' is the number of bytes left in the last line of A.
|
||||
* Marker is the end-of-line marker.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int mime_global_wrp(lua_State *L)
|
||||
{
|
||||
size_t size = 0;
|
||||
int left = (int) luaL_checknumber(L, 1);
|
||||
const UC *input = (UC *) checklstring(L, 2, &size);
|
||||
const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
|
||||
const UC *last = input + size;
|
||||
int length = (int) luaL_optnumber(L, 3, 76);
|
||||
const char *marker = luaL_optstring(L, 4, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last) {
|
||||
luaL_putchar(&buffer, *input++);
|
||||
if (--left <= 0) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
left = length;
|
||||
switch (*input) {
|
||||
case CR:
|
||||
break;
|
||||
case LF:
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
left = length;
|
||||
break;
|
||||
default:
|
||||
if (left <= 0) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
}
|
||||
input++;
|
||||
}
|
||||
/* if in last chunk and last line wasn't terminated, add a line-break */
|
||||
if (!input && left < length) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
left = length;
|
||||
}
|
||||
luaL_pushresult(&buffer);
|
||||
|
@ -235,7 +220,6 @@ static size_t b64pad(const UC *input, size_t size,
|
|||
static size_t b64decode(UC c, UC *input, size_t size,
|
||||
luaL_Buffer *buffer)
|
||||
{
|
||||
|
||||
/* ignore invalid characters */
|
||||
if (b64unbase[c] > 64) return size;
|
||||
input[size++] = c;
|
||||
|
@ -277,7 +261,7 @@ static int mime_global_b64(lua_State *L)
|
|||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = b64encode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
|
@ -305,12 +289,14 @@ static int mime_global_unb64(lua_State *L)
|
|||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = b64decode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = b64decode(*input++, atom, asize, &buffer);
|
||||
}
|
||||
/* if !input we are done. if atom > 0, the remaning is invalid. we just
|
||||
* return it undecoded. */
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
|
@ -416,7 +402,7 @@ static size_t qpencode(UC c, UC *input, size_t size,
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Deal with the final characters
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
||||
static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
|
@ -424,12 +410,13 @@ static void qppad(UC *input, size_t size, luaL_Buffer *buffer)
|
|||
else qpquote(input[i], buffer);
|
||||
}
|
||||
luaL_addstring(buffer, EQCRLF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Incrementally converts a string to quoted-printable
|
||||
* A, B = qp(C, D, marker)
|
||||
* Crlf is the text to be used to replace CRLF sequences found in A.
|
||||
* Marker is the text to be used to replace CRLF sequences found in A.
|
||||
* A is the encoded version of the largest prefix of C .. D that
|
||||
* can be encoded without doubts.
|
||||
* B has the remaining bytes of C .. D, *without* encoding.
|
||||
|
@ -439,19 +426,20 @@ static int mime_global_qp(lua_State *L)
|
|||
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[3];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
const char *marker = luaL_optstring(L, 3, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = qpencode(*input++, atom, asize, marker, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = qpencode(*input++, atom, asize, marker, &buffer);
|
||||
} else qppad(atom, asize, &buffer);
|
||||
} else
|
||||
asize = qppad(atom, asize, &buffer);
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
|
@ -507,13 +495,13 @@ static int mime_global_unqp(lua_State *L)
|
|||
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[3];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = qpdecode(*input++, atom, asize, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
|
@ -537,38 +525,39 @@ static int mime_global_qpwrp(lua_State *L)
|
|||
{
|
||||
size_t size = 0;
|
||||
int left = (int) luaL_checknumber(L, 1);
|
||||
const UC *input = (UC *) checklstring(L, 2, &size);
|
||||
const UC *input = (UC *) aux_optlstring(L, 2, NULL, &size);
|
||||
const UC *last = input + size;
|
||||
int length = (int) luaL_optnumber(L, 3, 76);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last) {
|
||||
left--;
|
||||
switch (*input) {
|
||||
case '=':
|
||||
/* if there's no room in this line for the quoted char,
|
||||
* output a soft line break now */
|
||||
if (left <= 3) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
left = length;
|
||||
}
|
||||
break;
|
||||
/* \r\n starts a new line */
|
||||
case CR:
|
||||
case CR:
|
||||
break;
|
||||
case LF:
|
||||
left = length;
|
||||
luaL_addstring(&buffer, CRLF);
|
||||
break;
|
||||
default:
|
||||
/* if in last column, output a soft line break */
|
||||
if (left <= 1) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
case '=':
|
||||
if (left <= 3) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
default:
|
||||
if (left <= 1) {
|
||||
left = length;
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
left--;
|
||||
break;
|
||||
}
|
||||
luaL_putchar(&buffer, *input);
|
||||
input++;
|
||||
}
|
||||
/* if in last chunk and last line wasn't terminated, add a soft-break */
|
||||
if (!input && left < length) {
|
||||
luaL_addstring(&buffer, EQCRLF);
|
||||
left = length;
|
||||
|
@ -579,10 +568,10 @@ static int mime_global_qpwrp(lua_State *L)
|
|||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Here is what we do: \n, \r and \f are considered candidates for line
|
||||
* Here is what we do: \n, and \r are considered candidates for line
|
||||
* break. We issue *one* new line marker if any of them is seen alone, or
|
||||
* followed by a different one. That is, \n\n, \r\r and \f\f will issue two
|
||||
* end of line markers each, but \r\n, \n\r, \r\f etc will only issue *one*
|
||||
* followed by a different one. That is, \n\n and \r\r will issue two
|
||||
* end of line markers each, but \r\n, \n\r etc will only issue *one*
|
||||
* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as
|
||||
* probably other more obscure conventions.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
|
@ -616,21 +605,24 @@ static int mime_global_eol(lua_State *L)
|
|||
{
|
||||
size_t asize = 0, isize = 0;
|
||||
UC atom[2];
|
||||
const UC *input = (UC *) checklstring(L, 1, &isize);
|
||||
const UC *input = (UC *) aux_optlstring(L, 1, NULL, &isize);
|
||||
const UC *last = input + isize;
|
||||
const char *marker = luaL_optstring(L, 3, CRLF);
|
||||
luaL_Buffer buffer;
|
||||
luaL_buffinit(L, &buffer);
|
||||
while (input < last)
|
||||
asize = eolconvert(*input++, atom, asize, marker, &buffer);
|
||||
input = (UC *) optlstring(L, 2, NULL, &isize);
|
||||
input = (UC *) aux_optlstring(L, 2, NULL, &isize);
|
||||
if (input) {
|
||||
last = input + isize;
|
||||
while (input < last)
|
||||
asize = eolconvert(*input++, atom, asize, marker, &buffer);
|
||||
/* if there is something in atom, it's one character, and it
|
||||
* is a candidate. so we output a new line */
|
||||
} else if (asize > 0) luaL_addstring(&buffer, marker);
|
||||
} else if (asize > 0) {
|
||||
luaL_addstring(&buffer, marker);
|
||||
asize = 0;
|
||||
}
|
||||
luaL_pushresult(&buffer);
|
||||
lua_pushlstring(L, (char *) atom, asize);
|
||||
return 2;
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
\*=========================================================================*/
|
||||
#include <lua.h>
|
||||
|
||||
void mime_open(lua_State *L);
|
||||
int mime_open(lua_State *L);
|
||||
|
||||
#endif /* MIME_H */
|
||||
|
|
85
src/mime.lua
85
src/mime.lua
|
@ -15,70 +15,57 @@ local et = {}
|
|||
local dt = {}
|
||||
local wt = {}
|
||||
|
||||
-- creates a function that chooses an algorithm from a given table
|
||||
-- creates a function that chooses a filter from a given table
|
||||
local function choose(table)
|
||||
return function(method, ...)
|
||||
local f = table[method or "nil"]
|
||||
if not f then error("unknown method (" .. tostring(method) .. ")", 3)
|
||||
return function(filter, ...)
|
||||
local f = table[filter or "nil"]
|
||||
if not f then error("unknown filter (" .. tostring(filter) .. ")", 3)
|
||||
else return f(unpack(arg)) end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a function that cicles a filter with a given initial
|
||||
-- context and extra arguments
|
||||
local function cicle(f, ctx, ...)
|
||||
return function(chunk)
|
||||
local ret
|
||||
ret, ctx = f(ctx, chunk, unpack(arg))
|
||||
return ret
|
||||
end
|
||||
-- define the encoding filters
|
||||
et['base64'] = function()
|
||||
return socket.cicle(b64, "")
|
||||
end
|
||||
|
||||
et['quoted-printable'] = function(mode)
|
||||
return socket.cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
|
||||
end
|
||||
|
||||
-- define the decoding filters
|
||||
dt['base64'] = function()
|
||||
return socket.cicle(unb64, "")
|
||||
end
|
||||
|
||||
dt['quoted-printable'] = function()
|
||||
return socket.cicle(unqp, "")
|
||||
end
|
||||
|
||||
-- define the line-wrap filters
|
||||
wt['text'] = function(length)
|
||||
length = length or 76
|
||||
return socket.cicle(wrp, length, length)
|
||||
end
|
||||
wt['base64'] = wt['text']
|
||||
|
||||
wt['quoted-printable'] = function()
|
||||
return socket.cicle(qpwrp, 76, 76)
|
||||
end
|
||||
|
||||
-- function that choose the encoding, decoding or wrap algorithm
|
||||
encode = choose(et)
|
||||
decode = choose(dt)
|
||||
|
||||
-- the wrap filter has default parameters
|
||||
-- there is a default wrap filter
|
||||
local cwt = choose(wt)
|
||||
function wrap(...)
|
||||
if not arg[1] or type(arg[1]) ~= "string" then
|
||||
table.insert(arg, 1, "base64")
|
||||
end
|
||||
if type(arg[1]) ~= "string" then table.insert(arg, 1, "text") end
|
||||
return cwt(unpack(arg))
|
||||
end
|
||||
|
||||
-- define the encoding algorithms
|
||||
et['base64'] = function()
|
||||
return cicle(b64, "")
|
||||
end
|
||||
|
||||
et['quoted-printable'] = function(mode)
|
||||
return cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
|
||||
end
|
||||
|
||||
-- define the decoding algorithms
|
||||
dt['base64'] = function()
|
||||
return cicle(unb64, "")
|
||||
end
|
||||
|
||||
dt['quoted-printable'] = function()
|
||||
return cicle(unqp, "")
|
||||
end
|
||||
|
||||
-- define the wrap algorithms
|
||||
wt['base64'] = function(length, marker)
|
||||
length = length or 76
|
||||
return cicle(wrp, length, length, marker)
|
||||
end
|
||||
|
||||
wt['quoted-printable'] = function(length)
|
||||
length = length or 76
|
||||
return cicle(qpwrp, length, length)
|
||||
end
|
||||
|
||||
-- define the end-of-line translation function
|
||||
-- define the end-of-line translation filter
|
||||
function canonic(marker)
|
||||
return cicle(eol, "", marker)
|
||||
return socket.cicle(eol, "", marker)
|
||||
end
|
||||
|
||||
-- chains several filters together
|
||||
|
@ -104,4 +91,4 @@ function chain(...)
|
|||
end
|
||||
end
|
||||
|
||||
return code
|
||||
return mime
|
||||
|
|
|
@ -42,7 +42,7 @@ static luaL_reg func[] = {
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void select_open(lua_State *L)
|
||||
int select_open(lua_State *L)
|
||||
{
|
||||
/* get select auxiliar lua function from lua code and register
|
||||
* pass it as an upvalue to global_select */
|
||||
|
@ -54,6 +54,7 @@ void select_open(lua_State *L)
|
|||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
|
||||
lua_pop(L, 1);
|
||||
aux_newclass(L, "select{fd_set}", set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
|
||||
void select_open(lua_State *L);
|
||||
int select_open(lua_State *L);
|
||||
|
||||
#endif /* SELECT_H */
|
||||
|
|
|
@ -4,7 +4,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
|||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local smtp = {}
|
||||
local smtp = socket.smtp or {}
|
||||
socket.smtp = smtp
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(smtp, { __index = _G })
|
||||
|
@ -18,6 +18,10 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
|||
-- default server used to send e-mails
|
||||
SERVER = "localhost"
|
||||
|
||||
function stuff()
|
||||
return socket.cicle(dot, 2)
|
||||
end
|
||||
|
||||
-- tries to get a pattern from the server and closes socket on error
|
||||
local function try_receiving(connection, pattern)
|
||||
local data, message = connection:receive(pattern)
|
||||
|
|
37
src/tcp.c
37
src/tcp.c
|
@ -39,25 +39,26 @@ static int meth_dirty(lua_State *L);
|
|||
|
||||
/* tcp object methods */
|
||||
static luaL_reg tcp[] = {
|
||||
{"connect", meth_connect},
|
||||
{"send", meth_send},
|
||||
{"receive", meth_receive},
|
||||
{"bind", meth_bind},
|
||||
{"listen", meth_listen},
|
||||
{"__gc", meth_close},
|
||||
{"accept", meth_accept},
|
||||
{"setpeername", meth_connect},
|
||||
{"setsockname", meth_bind},
|
||||
{"bind", meth_bind},
|
||||
{"close", meth_close},
|
||||
{"connect", meth_connect},
|
||||
{"dirty", meth_dirty},
|
||||
{"getfd", meth_getfd},
|
||||
{"getpeername", meth_getpeername},
|
||||
{"getsockname", meth_getsockname},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"close", meth_close},
|
||||
{"shutdown", meth_shutdown},
|
||||
{"setoption", meth_setoption},
|
||||
{"__gc", meth_close},
|
||||
{"getfd", meth_getfd},
|
||||
{"listen", meth_listen},
|
||||
{"receive", meth_receive},
|
||||
{"send", meth_send},
|
||||
{"setfd", meth_setfd},
|
||||
{"dirty", meth_dirty},
|
||||
{"setoption", meth_setoption},
|
||||
{"setpeername", meth_connect},
|
||||
{"setsockname", meth_bind},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"shutdown", meth_shutdown},
|
||||
{NULL, NULL}
|
||||
|
||||
};
|
||||
|
||||
/* socket option handlers */
|
||||
|
@ -78,7 +79,7 @@ static luaL_reg func[] = {
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void tcp_open(lua_State *L)
|
||||
int tcp_open(lua_State *L)
|
||||
{
|
||||
/* create classes */
|
||||
aux_newclass(L, "tcp{master}", tcp);
|
||||
|
@ -96,6 +97,7 @@ void tcp_open(lua_State *L)
|
|||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
|
@ -250,7 +252,7 @@ static int meth_listen(lua_State *L)
|
|||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_shutdown(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client}", 1);
|
||||
const char *how = luaL_optstring(L, 2, "both");
|
||||
switch (how[0]) {
|
||||
case 'b':
|
||||
|
@ -266,7 +268,8 @@ static int meth_shutdown(lua_State *L)
|
|||
sock_shutdown(&tcp->sock, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
lua_pushnumber(L, 1);
|
||||
return 1;
|
||||
error:
|
||||
luaL_argerror(L, 2, "invalid shutdown method");
|
||||
return 0;
|
||||
|
|
|
@ -31,6 +31,6 @@ typedef struct t_tcp_ {
|
|||
|
||||
typedef t_tcp *p_tcp;
|
||||
|
||||
void tcp_open(lua_State *L);
|
||||
int tcp_open(lua_State *L);
|
||||
|
||||
#endif /* TCP_H */
|
||||
|
|
|
@ -141,10 +141,11 @@ int tm_gettime(void)
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void tm_open(lua_State *L)
|
||||
int tm_open(lua_State *L)
|
||||
{
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
|
|
@ -16,7 +16,7 @@ typedef struct t_tm_ {
|
|||
} t_tm;
|
||||
typedef t_tm *p_tm;
|
||||
|
||||
void tm_open(lua_State *L);
|
||||
int tm_open(lua_State *L);
|
||||
void tm_init(p_tm tm, int block, int total);
|
||||
int tm_get(p_tm tm);
|
||||
int tm_getretry(p_tm tm);
|
||||
|
|
32
src/udp.c
32
src/udp.c
|
@ -30,7 +30,6 @@ static int meth_getpeername(lua_State *L);
|
|||
static int meth_setsockname(lua_State *L);
|
||||
static int meth_setpeername(lua_State *L);
|
||||
static int meth_close(lua_State *L);
|
||||
static int meth_shutdown(lua_State *L);
|
||||
static int meth_setoption(lua_State *L);
|
||||
static int meth_settimeout(lua_State *L);
|
||||
static int meth_getfd(lua_State *L);
|
||||
|
@ -49,7 +48,6 @@ static luaL_reg udp[] = {
|
|||
{"receivefrom", meth_receivefrom},
|
||||
{"settimeout", meth_settimeout},
|
||||
{"close", meth_close},
|
||||
{"shutdown", meth_shutdown},
|
||||
{"setoption", meth_setoption},
|
||||
{"__gc", meth_close},
|
||||
{"getfd", meth_getfd},
|
||||
|
@ -79,7 +77,7 @@ static luaL_reg func[] = {
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Initializes module
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void udp_open(lua_State *L)
|
||||
int udp_open(lua_State *L)
|
||||
{
|
||||
/* create classes */
|
||||
aux_newclass(L, "udp{connected}", udp);
|
||||
|
@ -92,6 +90,7 @@ void udp_open(lua_State *L)
|
|||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
|
@ -287,33 +286,6 @@ static int meth_close(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Shuts the connection down partially
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_shutdown(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
const char *how = luaL_optstring(L, 2, "both");
|
||||
switch (how[0]) {
|
||||
case 'b':
|
||||
if (strcmp(how, "both")) goto error;
|
||||
sock_shutdown(&udp->sock, 2);
|
||||
break;
|
||||
case 's':
|
||||
if (strcmp(how, "send")) goto error;
|
||||
sock_shutdown(&udp->sock, 1);
|
||||
break;
|
||||
case 'r':
|
||||
if (strcmp(how, "receive")) goto error;
|
||||
sock_shutdown(&udp->sock, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
luaL_argerror(L, 2, "invalid shutdown method");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master object into a server object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
|
|
|
@ -27,6 +27,6 @@ typedef struct t_udp_ {
|
|||
} t_udp;
|
||||
typedef t_udp *p_udp;
|
||||
|
||||
void udp_open(lua_State *L);
|
||||
int udp_open(lua_State *L);
|
||||
|
||||
#endif /* UDP_H */
|
||||
|
|
|
@ -12,7 +12,7 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
|
|||
local socket = _G[LUASOCKET_LIBNAME]
|
||||
if not socket then error('module requires LuaSocket') end
|
||||
-- create smtp namespace inside LuaSocket namespace
|
||||
local url = {}
|
||||
local url = socket.url or {}
|
||||
socket.url = url
|
||||
-- make all module globals fall into smtp namespace
|
||||
setmetatable(url, { __index = _G })
|
||||
|
|
|
@ -70,12 +70,10 @@ int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout)
|
|||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_create(p_sock ps, int domain, int type, int protocol)
|
||||
{
|
||||
int val = 1;
|
||||
t_sock sock = socket(domain, type, protocol);
|
||||
if (sock == SOCK_INVALID) return sock_createstrerror(errno);
|
||||
*ps = sock;
|
||||
sock_setnonblocking(ps);
|
||||
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -167,13 +165,14 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
|
|||
for (;;) {
|
||||
int err;
|
||||
fd_set fds;
|
||||
/* try to accept */
|
||||
*pa = accept(sock, addr, addr_len);
|
||||
/* if result is valid, we are done */
|
||||
if (*pa != SOCK_INVALID) return NULL;
|
||||
/* find out if we failed for a fatal reason */
|
||||
if (errno != EWOULDBLOCK && errno != ECONNABORTED)
|
||||
return sock_acceptstrerror(errno);
|
||||
/* call select just to avoid busy-wait. */
|
||||
/* call select to avoid busy-wait. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm));
|
||||
|
|
|
@ -75,12 +75,10 @@ void sock_shutdown(p_sock ps, int how)
|
|||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_create(p_sock ps, int domain, int type, int protocol)
|
||||
{
|
||||
int val = 1;
|
||||
t_sock sock = socket(domain, type, protocol);
|
||||
if (sock == SOCK_INVALID)
|
||||
return sock_createstrerror(WSAGetLastError());
|
||||
*ps = sock;
|
||||
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
|
||||
sock_setnonblocking(ps);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -112,8 +110,12 @@ const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm)
|
|||
/* if was in efds, we failed */
|
||||
if (FD_ISSET(sock, &efds)) {
|
||||
int why, len = sizeof(why);
|
||||
/* give windows time to set the error (disgusting) */
|
||||
Sleep(0);
|
||||
/* find out why we failed */
|
||||
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&why, &len);
|
||||
/* we KNOW there was an error. if why is 0, we will return
|
||||
* "unknown error", but it's not really our fault */
|
||||
return sock_connectstrerror(why);
|
||||
/* otherwise it must be in wfds, so we succeeded */
|
||||
} else return NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue