add more wrapper APIs to the module
This commit is contained in:
parent
115a068ac0
commit
af3a063299
804
limap.c
804
limap.c
@ -5,8 +5,18 @@
|
||||
#include "imap4r1.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
extern int errno; /* just in case */
|
||||
|
||||
#define IMAP_MT "limap"
|
||||
|
||||
#define IMAP_ADDRESS_SIZE_BUF 10
|
||||
|
||||
#ifndef SENDBUFLEN
|
||||
#define SENDBUFLEN 16385
|
||||
#endif
|
||||
|
||||
#define M_LOG(a,...) syslog (LOG_NOTICE,"limap@[%s: %d]: " a "\n", __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__)
|
||||
#define M_WARN(a,...) syslog (LOG_WARNING, "limap@[%s: %d]: " a "\n", __FILE__, \
|
||||
@ -24,6 +34,10 @@ extern int errno; /* just in case */
|
||||
lua_pushnumber(L,v); \
|
||||
lua_settable(L,-3);
|
||||
|
||||
|
||||
static pthread_mutex_t _limap_lock;
|
||||
static lua_State* __L__;
|
||||
|
||||
unsigned long find_rightmost_bit(unsigned long *valptr);
|
||||
|
||||
static size_t strlcat(char *dst, const char *src, size_t n) {
|
||||
@ -76,9 +90,9 @@ void mm_searched (MAILSTREAM *stream,unsigned long msgno)
|
||||
void mm_exists (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
M_LOG("New emails found in %s: %d", stream->mailbox, number);
|
||||
int * n = stream->sparep;
|
||||
if(!n) return;
|
||||
*n = number;
|
||||
lua_State * L = stream->sparep;
|
||||
if(!L) return;
|
||||
lua_pushnumber(L, number);
|
||||
}
|
||||
|
||||
|
||||
@ -162,7 +176,7 @@ void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
|
||||
void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
/* dummy routine */
|
||||
mm_list(stream,delimiter, name,attributes);
|
||||
}
|
||||
|
||||
|
||||
@ -187,18 +201,33 @@ void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
||||
|
||||
void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
{
|
||||
if (!errflg && (string[0] == '[') &&
|
||||
((string[1] == 'T') || (string[1] == 't')) &&
|
||||
((string[2] == 'R') || (string[2] == 'r')) &&
|
||||
((string[3] == 'Y') || (string[3] == 'y')) &&
|
||||
((string[4] == 'C') || (string[4] == 'c')) &&
|
||||
((string[5] == 'R') || (string[5] == 'r')) &&
|
||||
((string[6] == 'E') || (string[6] == 'e')) &&
|
||||
((string[7] == 'A') || (string[7] == 'a')) &&
|
||||
((string[8] == 'T') || (string[8] == 't')) &&
|
||||
((string[9] == 'E') || (string[9] == 'e')) &&
|
||||
(string[10] == ']'))
|
||||
mm_log (string,errflg); /* just do mm_log action */
|
||||
lua_State* L = stream->sparep;
|
||||
if (!errflg && (string[0] == '[') &&
|
||||
((string[1] == 'T') || (string[1] == 't')) &&
|
||||
((string[2] == 'R') || (string[2] == 'r')) &&
|
||||
((string[3] == 'Y') || (string[3] == 'y')) &&
|
||||
((string[4] == 'C') || (string[4] == 'c')) &&
|
||||
((string[5] == 'R') || (string[5] == 'r')) &&
|
||||
((string[6] == 'E') || (string[6] == 'e')) &&
|
||||
((string[7] == 'A') || (string[7] == 'a')) &&
|
||||
((string[8] == 'T') || (string[8] == 't')) &&
|
||||
((string[9] == 'E') || (string[9] == 'e')) &&
|
||||
(string[10] == ']'))
|
||||
{
|
||||
switch (errflg) {
|
||||
case BYE:
|
||||
case NIL: /* no error */
|
||||
break;
|
||||
default:
|
||||
lua_getglobal(L, "limap_errors");
|
||||
size_t len = lua_rawlen(L,-1);
|
||||
lua_pushnumber(L,len+1);
|
||||
lua_pushstring(L,string);
|
||||
lua_settable(L,-3);
|
||||
break;
|
||||
}
|
||||
mm_log (string,errflg); /* just do mm_log action */
|
||||
}
|
||||
}
|
||||
|
||||
/* Log an event for the user to see
|
||||
@ -208,20 +237,20 @@ void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
|
||||
void mm_log (char *string,long errflg)
|
||||
{
|
||||
switch (errflg) {
|
||||
case BYE:
|
||||
case NIL: /* no error */
|
||||
M_LOG ("[%s]",string);
|
||||
break;
|
||||
case PARSE: /* parsing problem */
|
||||
case WARN: /* warning */
|
||||
M_WARN("warning: %s",string);
|
||||
break;
|
||||
case ERROR: /* error */
|
||||
default:
|
||||
M_ERROR ("%s",string);
|
||||
break;
|
||||
}
|
||||
switch (errflg) {
|
||||
case BYE:
|
||||
case NIL: /* no error */
|
||||
M_LOG ("[%s]",string);
|
||||
break;
|
||||
case PARSE: /* parsing problem */
|
||||
case WARN: /* warning */
|
||||
M_WARN("warning: %s",string);
|
||||
break;
|
||||
case ERROR: /* error */
|
||||
default:
|
||||
M_ERROR ("%s",string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -242,23 +271,56 @@ void mm_dlog (char *string)
|
||||
|
||||
void mm_login (NETMBX *mb,char *username,char *password,long trial)
|
||||
{
|
||||
if(mb->user)
|
||||
// user name
|
||||
if(!lua_isstring(__L__,2))
|
||||
{
|
||||
char * tmp = mb->user;
|
||||
(void)strsep(&tmp, ";");
|
||||
strncpy(username, mb->user, NETMAXUSER);
|
||||
if(tmp)
|
||||
{
|
||||
strncpy (password,tmp,MAILTMPLEN);
|
||||
}
|
||||
M_LOG("host: %s", mb->host);
|
||||
M_LOG("orighost: %s", mb->orighost);
|
||||
M_LOG("user: %s", mb->user);
|
||||
M_LOG("mailbox: %s", mb->mailbox);
|
||||
M_LOG("service: %s", mb->service);
|
||||
return;
|
||||
}
|
||||
// password
|
||||
if(!lua_isstring(__L__,3))
|
||||
{
|
||||
return;
|
||||
}
|
||||
char * tmp = (char*)lua_tostring(__L__,2);
|
||||
strncpy(username, tmp, NETMAXUSER);
|
||||
tmp = (char*)lua_tostring(__L__,3);
|
||||
strncpy (password,tmp,MAILTMPLEN);
|
||||
|
||||
M_LOG("host: %s", mb->host);
|
||||
M_LOG("orighost: %s", mb->orighost);
|
||||
M_LOG("user: %s", username);
|
||||
M_LOG("mailbox: %s", mb->mailbox);
|
||||
M_LOG("service: %s", mb->service);
|
||||
}
|
||||
|
||||
void mm_getacl(MAILSTREAM *stream, char *mailbox, ACLLIST *alist)
|
||||
{
|
||||
|
||||
/* walk through the ACLLIST */
|
||||
lua_State* L = stream->sparep;
|
||||
lua_newtable(L);
|
||||
for(; alist; alist = alist->next) {
|
||||
add_property_string(L,alist->identifier, alist->rights);
|
||||
}
|
||||
}
|
||||
|
||||
void mm_getquota(MAILSTREAM *stream, char *qroot, QUOTALIST *qlist)
|
||||
{
|
||||
/* put parsing code here */
|
||||
lua_State* L = stream->sparep;
|
||||
M_LOG("querying quota:");
|
||||
lua_newtable(L);
|
||||
for(; qlist; qlist = qlist->next) {
|
||||
lua_pushstring(L, qlist->name);
|
||||
lua_newtable(L);
|
||||
add_property_long(L, "usage", qlist->usage);
|
||||
add_property_long(L, "limit", qlist->limit);
|
||||
lua_settable(L,-3);
|
||||
M_LOG("Quota name %s: ", qlist->name);
|
||||
M_LOG("Usage: %d", qlist->usage);
|
||||
M_LOG("Limit: %d",qlist->limit);
|
||||
}
|
||||
}
|
||||
|
||||
/* About to enter critical code
|
||||
* Accepts: stream
|
||||
@ -308,28 +370,33 @@ static int l_mail_open(lua_State *L)
|
||||
{
|
||||
const char* mailbox = luaL_checkstring(L,1);
|
||||
long flag = 0;
|
||||
if( lua_toboolean(L,2))
|
||||
if( lua_toboolean(L,4))
|
||||
{
|
||||
/*half open*/
|
||||
flag = flag | OP_HALFOPEN;
|
||||
}
|
||||
if( lua_toboolean(L,3))
|
||||
if( lua_toboolean(L,5))
|
||||
{
|
||||
/*debug*/
|
||||
flag = flag | OP_DEBUG;
|
||||
}
|
||||
pthread_mutex_lock(&_limap_lock);
|
||||
__L__ = L;
|
||||
MAILSTREAM *stream = mail_open (NIL,(char*)mailbox,flag);
|
||||
__L__ = NULL;
|
||||
pthread_mutex_unlock(&_limap_lock);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
//strncpy(stream->original_mailbox, stream->mailbox, strlen(stream->mailbox));
|
||||
if(stream->original_mailbox)
|
||||
/*if(stream->original_mailbox)
|
||||
{
|
||||
free(stream->original_mailbox);
|
||||
}
|
||||
stream->original_mailbox = strdup(stream->mailbox);
|
||||
stream->original_mailbox = strdup(stream->mailbox);*/
|
||||
stream->sparep = (void*)L;
|
||||
M_LOG("mailbox: %s", stream->mailbox);
|
||||
M_LOG("original_mailbox: %s", stream->original_mailbox);
|
||||
lua_pushlightuserdata(L, stream);
|
||||
@ -362,7 +429,6 @@ static int l_get_mailboxes(lua_State *L)
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
stream->sparep = (void*)L;
|
||||
lua_newtable(L);
|
||||
mail_list(stream,(char*)reference, (char*)pattern);
|
||||
return 1;
|
||||
@ -371,8 +437,6 @@ static int l_get_mailboxes(lua_State *L)
|
||||
static int l_mail_ping(lua_State *L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
int new_mail = 0;
|
||||
stream->sparep = (void*)&new_mail;
|
||||
if(!stream || mail_ping(stream) == NIL)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
@ -381,7 +445,6 @@ static int l_mail_ping(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L,1);
|
||||
}
|
||||
lua_pushnumber(L, new_mail);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@ -390,10 +453,30 @@ static int l_mail_check(lua_State *L)
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
return 0;
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char date[100];
|
||||
|
||||
if (mail_ping (stream) == NIL) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stream->mailbox) {
|
||||
rfc822_date(date);
|
||||
lua_newtable(L);
|
||||
add_property_string(L, "Date", date);
|
||||
add_property_string(L, "Driver", stream->dtb->name);
|
||||
add_property_string(L, "Mailbox", stream->mailbox);
|
||||
add_property_long(L, "Nmsgs", stream->nmsgs);
|
||||
add_property_long(L, "Recent", stream->recent);
|
||||
return 1;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
mail_check(stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_mail_get_raw_header(lua_State* L)
|
||||
@ -575,11 +658,12 @@ static int l_reopen(lua_State *L)
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
if(stream->original_mailbox)
|
||||
stream->sparep = (void*) L;
|
||||
/*if(stream->original_mailbox)
|
||||
{
|
||||
free(stream->original_mailbox);
|
||||
}
|
||||
stream->original_mailbox = strdup(stream->mailbox);
|
||||
stream->original_mailbox = strdup(stream->mailbox);*/
|
||||
M_LOG("mailbox: %s", stream->mailbox);
|
||||
M_LOG("original_mailbox: %s", stream->original_mailbox);
|
||||
lua_pushboolean(L,1);
|
||||
@ -924,27 +1008,621 @@ static int l_get_body_part(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_append(lua_State* L)
|
||||
{
|
||||
STRING s;
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
char* folder = (char*)luaL_checkstring(L,2);
|
||||
char* message = (char*)luaL_checkstring(L,3);
|
||||
INIT (&s, mail_string, message,strlen(message));
|
||||
if (mail_append(stream, folder, &s)) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_setflag_full(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
|
||||
char *sequence = (char*)luaL_checkstring(L,2);
|
||||
char *flag = (char*)luaL_checkstring(L,3);
|
||||
|
||||
unsigned int flags = 0;
|
||||
if(lua_toboolean(L,4))
|
||||
{
|
||||
flags |= ST_UID;
|
||||
}
|
||||
|
||||
mail_setflag_full(stream, sequence, flag, flags);
|
||||
lua_pushboolean(L,1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_create_mailbox(lua_State * L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
char *folder = (char*)luaL_checkstring(L,2);
|
||||
|
||||
if (mail_create(stream, folder) == T) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_delete_mailbox(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
char *folder = (char*)luaL_checkstring(L,2);
|
||||
|
||||
if (mail_delete(stream, folder) == T) {
|
||||
lua_pushboolean(L, 1);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_8bit(lua_State* L)
|
||||
{
|
||||
char* text = (char*) luaL_checkstring(L,1);
|
||||
char *decode;
|
||||
unsigned long newlength;
|
||||
|
||||
decode = (char *) rfc822_8bit((unsigned char *) text, strlen(text), &newlength);
|
||||
|
||||
if (decode == NULL) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
decode[newlength] = '\0';
|
||||
lua_pushstring(L, decode);
|
||||
fs_give((void**) &decode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_binary(lua_State* L)
|
||||
{
|
||||
char* text = (char*) luaL_checkstring(L,1);
|
||||
char *decode;
|
||||
unsigned long newlength;
|
||||
|
||||
decode = (char*)rfc822_binary(text, strlen(text), &newlength);
|
||||
|
||||
if (decode == NULL) {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
decode[newlength] = '\0';
|
||||
lua_pushstring(L, decode);
|
||||
fs_give((void**) &decode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_clearflag_full(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
|
||||
char *sequence = (char*)luaL_checkstring(L,2);
|
||||
char *flag = (char*)luaL_checkstring(L,3);
|
||||
|
||||
unsigned int flags = 0;
|
||||
if(lua_toboolean(L,4))
|
||||
{
|
||||
flags |= ST_UID;
|
||||
}
|
||||
|
||||
mail_clearflag_full(stream, sequence, flag, flags);
|
||||
lua_pushboolean(L,1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_body_struct(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
unsigned int msgno = luaL_checknumber(L, 2);
|
||||
char* section = (char*)luaL_checkstring(L,3);
|
||||
|
||||
PARAMETER *par, *dpar;
|
||||
BODY *body;
|
||||
|
||||
body=mail_body(stream, msgno, (unsigned char*)section);
|
||||
if (body == NULL) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
if (body->type <= TYPEMAX) {
|
||||
add_property_long(L, "type", body->type);
|
||||
}
|
||||
if (body->encoding <= ENCMAX) {
|
||||
add_property_long(L, "encoding", body->encoding);
|
||||
}
|
||||
|
||||
if (body->subtype) {
|
||||
add_property_long(L, "ifsubtype", 1);
|
||||
add_property_string(L, "subtype", body->subtype);
|
||||
} else {
|
||||
add_property_long(L, "ifsubtype", 0);
|
||||
}
|
||||
|
||||
if (body->description) {
|
||||
add_property_long(L, "ifdescription", 1);
|
||||
add_property_string(L, "description", body->description);
|
||||
} else {
|
||||
add_property_long(L, "ifdescription", 0);
|
||||
}
|
||||
if (body->id) {
|
||||
add_property_long(L, "ifid", 1);
|
||||
add_property_string(L, "id", body->id);
|
||||
} else {
|
||||
add_property_long(L, "ifid", 0);
|
||||
}
|
||||
|
||||
if (body->size.lines) {
|
||||
add_property_long(L, "lines", body->size.lines);
|
||||
}
|
||||
if (body->size.bytes) {
|
||||
add_property_long(L, "bytes", body->size.bytes);
|
||||
}
|
||||
#ifdef IMAP41
|
||||
if (body->disposition.type) {
|
||||
add_property_long(L, "ifdisposition", 1);
|
||||
add_property_string(L, "disposition", body->disposition.type);
|
||||
} else {
|
||||
add_property_long(L, "ifdisposition", 0);
|
||||
}
|
||||
|
||||
if (body->disposition.parameter) {
|
||||
dpar = body->disposition.parameter;
|
||||
add_property_long(L, "ifdparameters", 1);
|
||||
lua_pushstring(L,"dparameters");
|
||||
lua_newtable(L);
|
||||
int count = 1;
|
||||
do {
|
||||
lua_pushnumber(L,count);
|
||||
lua_newtable(L);
|
||||
add_property_string(L, "attribute", dpar->attribute);
|
||||
add_property_string(L, "value", dpar->value);
|
||||
lua_settable(L,-3);
|
||||
count++;
|
||||
} while ((dpar = dpar->next));
|
||||
lua_settable(L,-3);
|
||||
} else {
|
||||
add_property_long(L, "ifdparameters", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((par = body->parameter)) {
|
||||
add_property_long(L, "ifparameters", 1);
|
||||
lua_pushstring(L,"parameters");
|
||||
lua_newtable(L);
|
||||
int count = 1;
|
||||
do {
|
||||
lua_pushnumber(L,count);
|
||||
lua_newtable(L);
|
||||
if (par->attribute) {
|
||||
add_property_string(L, "attribute", par->attribute);
|
||||
}
|
||||
if (par->value) {
|
||||
add_property_string(L, "value", par->value);
|
||||
}
|
||||
count++;
|
||||
lua_settable(L,-3);
|
||||
} while ((par = par->next));
|
||||
lua_settable(L,-3);
|
||||
} else {
|
||||
add_property_long(L, "ifparameters", 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_expunge(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
|
||||
mail_expunge (stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* {{{ _rfc822_len
|
||||
* Calculate string length based on imap's rfc822_cat function.
|
||||
*/
|
||||
static int _rfc822_len(char *str)
|
||||
{
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
if (!str || !*str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strings with special characters will need to be quoted, as a safety measure we
|
||||
* add 2 bytes for the quotes just in case.
|
||||
*/
|
||||
len = strlen(str) + 2;
|
||||
p = str;
|
||||
/* rfc822_cat() will escape all " and \ characters, therefore we need to increase
|
||||
* our buffer length to account for these characters.
|
||||
*/
|
||||
while ((p = strpbrk(p, "\\\""))) {
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _imap_get_address_size */
|
||||
static int _imap_address_size (ADDRESS *addresslist)
|
||||
{
|
||||
ADDRESS *tmp;
|
||||
int ret=0, num_ent=0;
|
||||
|
||||
tmp = addresslist;
|
||||
|
||||
if (tmp) do {
|
||||
ret += _rfc822_len(tmp->personal);
|
||||
ret += _rfc822_len(tmp->adl);
|
||||
ret += _rfc822_len(tmp->mailbox);
|
||||
ret += _rfc822_len(tmp->host);
|
||||
num_ent++;
|
||||
} while ((tmp = tmp->next));
|
||||
|
||||
/*
|
||||
* rfc822_write_address_full() needs some extra space for '<>,', etc.
|
||||
* for this perpouse we allocate additional IMAP_ADDRESS_SIZE_BUF bytes
|
||||
* by default this buffer is 10 bytes long
|
||||
*/
|
||||
ret += (ret) ? num_ent*IMAP_ADDRESS_SIZE_BUF : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rfc822_write_address */
|
||||
static void _rfc822_write_address(lua_State* L,const char* key, ADDRESS *addresslist)
|
||||
{
|
||||
char address[SENDBUFLEN];
|
||||
|
||||
if (_imap_address_size(addresslist) >= SENDBUFLEN) {
|
||||
//throw_error(NULL, "Address buffer overflow");
|
||||
return;
|
||||
}
|
||||
address[0] = 0;
|
||||
rfc822_write_address(address, addresslist);
|
||||
add_property_string(L, key, address);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int l_get_overview(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
unsigned int status, flags = 0L;
|
||||
|
||||
char *sequence = (char*)luaL_checkstring(L,2);
|
||||
|
||||
if(lua_toboolean(L,3))
|
||||
{
|
||||
flags |= ST_UID;
|
||||
}
|
||||
|
||||
|
||||
status = (flags & FT_UID)
|
||||
? mail_uid_sequence(stream, (unsigned char*)sequence)
|
||||
: mail_sequence(stream, (unsigned char*)sequence);
|
||||
|
||||
if (status) {
|
||||
MESSAGECACHE *elt;
|
||||
ENVELOPE *env;
|
||||
unsigned long i;
|
||||
lua_newtable(L);
|
||||
for (i = 1; i <= stream->nmsgs; i++) {
|
||||
if (((elt = mail_elt (stream, i))->sequence) &&
|
||||
(env = mail_fetch_structure (stream, i, NIL, NIL))) {
|
||||
lua_pushnumber(L,i);
|
||||
lua_newtable(L);
|
||||
if (env->subject) {
|
||||
add_property_string(L, "subject", env->subject);
|
||||
}
|
||||
if (env->from) {
|
||||
env->from->next=NULL;
|
||||
_rfc822_write_address(L,"from",env->from);
|
||||
}
|
||||
if (env->to) {
|
||||
env->to->next = NULL;
|
||||
_rfc822_write_address(L,"to",env->to);
|
||||
}
|
||||
if (env->date) {
|
||||
add_property_string(L, "date", (char*)env->date);
|
||||
}
|
||||
if (env->message_id) {
|
||||
add_property_string(L, "message_id", env->message_id);
|
||||
}
|
||||
if (env->references) {
|
||||
add_property_string(L, "references", env->references);
|
||||
}
|
||||
if (env->in_reply_to) {
|
||||
add_property_string(L, "in_reply_to", env->in_reply_to);
|
||||
}
|
||||
add_property_long(L, "size", elt->rfc822_size);
|
||||
add_property_long(L, "uid", mail_uid(stream, i));
|
||||
add_property_long(L, "msgno", i);
|
||||
add_property_long(L, "recent", elt->recent);
|
||||
add_property_long(L, "flagged", elt->flagged);
|
||||
add_property_long(L, "answered", elt->answered);
|
||||
add_property_long(L, "deleted", elt->deleted);
|
||||
add_property_long(L, "seen", elt->seen);
|
||||
add_property_long(L, "draft", elt->draft);
|
||||
add_property_long(L, "udate", mail_longdate(elt));
|
||||
lua_settable(L,-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_mime(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
unsigned int flags = 0;
|
||||
const int msgno = luaL_checknumber(L,2);
|
||||
char* section = (char*)luaL_checkstring(L,3);
|
||||
|
||||
if(lua_toboolean(L,4))
|
||||
{
|
||||
flags |= FT_PEEK;
|
||||
}
|
||||
|
||||
char *body;
|
||||
unsigned long len;
|
||||
|
||||
body = mail_fetch_mime(stream, msgno, section, &len, flags);
|
||||
|
||||
if (!body) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_pushstring(L,body);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_gc(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
unsigned int flags = GC_TEXTS | GC_ELT | GC_ENV;
|
||||
|
||||
mail_gc(stream, flags);
|
||||
|
||||
lua_pushboolean(L,1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_quota(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
char * qroot = (char*) luaL_checkstring(L,2);
|
||||
|
||||
// set the callback for the GET_QUOTA function
|
||||
mail_parameters(NIL, SET_QUOTA, (void *) mm_getquota);
|
||||
if (!imap_getquota(stream,qroot)) {
|
||||
M_ERROR("C-client imap_getquota failed");
|
||||
}
|
||||
if(lua_isstring(L,-1))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_quotaroot(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
char * qroot = (char*) luaL_checkstring(L,2);
|
||||
|
||||
// set the callback for the GET_QUOTA function
|
||||
mail_parameters(NIL, SET_QUOTA, (void *) mm_getquota);
|
||||
if (!imap_getquotaroot(stream,qroot)) {
|
||||
M_ERROR("C-client imap_getquotaroot failed");
|
||||
}
|
||||
if(lua_isstring(L,-1))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_getacl(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
char * mailbox = (char*) luaL_checkstring(L,2);
|
||||
|
||||
/* set the callback for the GET_ACL function */
|
||||
mail_parameters(NIL, SET_ACL, (void *) mm_getacl);
|
||||
if (!imap_getacl(stream, mailbox))
|
||||
{
|
||||
M_ERROR("c-client imap_getacl failed");
|
||||
}
|
||||
if(lua_isstring(L,-1))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_subscribed(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
const char* reference = luaL_checkstring(L,2);
|
||||
const char* pattern = luaL_checkstring(L,3);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
lua_newtable(L);
|
||||
mail_lsub(stream,(char*)reference, (char*)pattern);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_scan_mailboxes(lua_State* L)
|
||||
{
|
||||
MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1);
|
||||
const char* reference = luaL_checkstring(L,2);
|
||||
const char* pattern = luaL_checkstring(L,3);
|
||||
const char* content = luaL_checkstring(L,4);
|
||||
if(!stream)
|
||||
{
|
||||
lua_pushboolean(L,0);
|
||||
return 1;
|
||||
}
|
||||
lua_newtable(L);
|
||||
mail_scan(stream, (char*)reference, (char*)pattern, (char*)content);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_mail_compose(lua_State* L)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int l_lua_gc(lua_State* L)
|
||||
{
|
||||
M_LOG("Imap module unloaded");
|
||||
pthread_mutex_destroy(&_limap_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg _lib [] = {
|
||||
{"open", l_mail_open},
|
||||
{"close", l_mail_close},
|
||||
{"get_mail_boxes", l_get_mailboxes},
|
||||
{"get_mail_boxes", l_get_mailboxes},// = PHP imap_getmailboxes, imap_list
|
||||
{"reopen", l_reopen},
|
||||
{"ping", l_mail_ping},
|
||||
{"check", l_mail_check},
|
||||
{"get_raw_header", l_mail_get_raw_header},
|
||||
{"check", l_mail_check}, // PHP imap_check
|
||||
{"get_raw_header", l_mail_get_raw_header}, // = PHP imap_fetchheader()
|
||||
{"get_nmail", l_mail_getnumber},
|
||||
{"get_headers", l_mail_get_headers},
|
||||
{"get_header", l_mail_get_header},
|
||||
{"get_header", l_mail_get_header}, // = php imap_header()
|
||||
{"rfc822_parse_header", l_rfc822_parse_header},
|
||||
{"get_raw_body", l_get_raw_body},
|
||||
{"get_structure", l_get_structure},
|
||||
{"get_body_part", l_get_body_part},
|
||||
{"get_raw_body", l_get_raw_body}, // = PHP imap_body
|
||||
{"get_structure", l_get_structure}, // = PHP imap_fetchstructure()
|
||||
{"get_body_part", l_get_body_part}, // = PHP imap_fetchbody()
|
||||
{"append", l_append},
|
||||
{"setflag_full", l_setflag_full}, // = PHP imap_setflag_full
|
||||
{"clearflag_full", l_clearflag_full}, // = PHP clearflag_full
|
||||
{"create_mailbox", l_create_mailbox}, // = PHP imap_createmailbox
|
||||
{"delete_mailbox", l_delete_mailbox}, // = PHP imap_deletemailbox
|
||||
{"_8bit", l_8bit}, // = PHP imap_8bit
|
||||
{"binary", l_binary}, // = PHP imap_binary
|
||||
{"get_body_struct", l_get_body_struct }, // = PHP imap_bodystruct
|
||||
{"expunge" , l_expunge}, // = PHP imap_expunge
|
||||
{"get_overview", l_get_overview}, // = PHP imap_fetch_overview
|
||||
{"get_mime", l_get_mime}, // = PHP imap_fetchmime
|
||||
{"gc", l_gc}, // = PHP imap_gc
|
||||
{"get_quota", l_get_quota}, // = PHP imap_get_quota
|
||||
{"get_quotaroot", l_get_quotaroot}, // = PHP imap_get_quotaroot
|
||||
{"get_acl", l_getacl}, // = PHP imap_getacl,
|
||||
{"get_subscribed", l_get_subscribed}, // = PHP imap_getsubscribed, imap_listsubscribed, imap_lsub
|
||||
{"scan_mailboxes", l_scan_mailboxes}, // = PHP imap_listscan,
|
||||
// {"mail_compose", l_mail_compose}, TODO
|
||||
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
cleanup in a c module
|
||||
|
||||
https://lua-l.lua.narkive.com/09DuVpEl/cleanup-in-a-c-module
|
||||
The sentinel userdata above will call the cleanup code as soon as it is collected;
|
||||
to prevent collection until the module is destroyed, we need to add a reference that links the module to the sentinel.
|
||||
We're using the LUA_REGISTRYINDEX to store this in a way that is hidden from Lua scripts.
|
||||
We create a weak-valued table in the registry called "__gc_sentinels" (if it doesn't already exist),
|
||||
and use weak-referencing so that existence of the module in this table will not stop it from being collected.
|
||||
For most uses of Lua, this won't matter since modules usually only get unloaded when the lua_State is closed;
|
||||
but we had a situation where we needed to manually unload modules sometimes.
|
||||
*/
|
||||
static void gc_sentinel(lua_State * L, int idx, lua_CFunction callback) {
|
||||
|
||||
lua_pushvalue(L, idx); // value @idx
|
||||
lua_newuserdata(L, sizeof(void *)); // sentinel userdata
|
||||
lua_newtable(L); // userdata metatable with __gc = callback
|
||||
lua_pushcfunction(L, callback);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
/* check for (weak-valued) sentinel table; create if needed */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__gc_limap_sentinels");
|
||||
if (lua_isnoneornil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
// make weak-keyed
|
||||
lua_pushstring(L, "v");
|
||||
lua_setfield(L, -2, "__mode");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__gc_limap_sentinels");
|
||||
}
|
||||
lua_insert(L, -3);
|
||||
lua_insert(L, -2);
|
||||
lua_settable(L, -3); // lua::sentinel[value @idx] = sentinel userdata
|
||||
lua_pop(L, 1); // lua::sentinel
|
||||
}
|
||||
|
||||
int luaopen_limap(lua_State *L)
|
||||
{
|
||||
M_LOG("Imap module loaded");
|
||||
#include "linkage.c"
|
||||
pthread_mutex_init(&_limap_lock, NULL);
|
||||
__L__ = NULL;
|
||||
// create error stack
|
||||
lua_newtable( L );
|
||||
lua_setglobal( L, "limap_errors" );
|
||||
luaL_newlib(L, _lib);
|
||||
gc_sentinel(L, -1, l_lua_gc);
|
||||
return 1;
|
||||
}
|
66
test.lua
66
test.lua
@ -10,13 +10,15 @@ local OP_EXPUNGE= 0x80 --/* silently expunge recycle stream */
|
||||
|
||||
local imap = require("limap")
|
||||
local passwd = os.getenv("IMAP_PWD")
|
||||
local url = string.format("{iohub.dev:143/imap/tls-sslv23/novalidate-cert/user=mrsang;%s}",passwd);
|
||||
local handle, box = imap.open(url,true, true) -- half open and debug on
|
||||
local url = "{iohub.dev:993/imap/ssl/novalidate-cert}"
|
||||
--local url = string.format("{iohub.dev:993/imap/ssl/novalidate-cert/user=dany@iohub.dev;%s}",passwd);
|
||||
local handle, box = imap.open(url,"dany@iohub.dev", passwd, true, true) -- half open and debug on
|
||||
|
||||
local r,v = false,nil;
|
||||
|
||||
function dump(obj)
|
||||
if(type(obj) == "table") then
|
||||
print("dump", obj, " size: ", #obj)
|
||||
for k,v in pairs(obj) do
|
||||
print(k)
|
||||
dump(v)
|
||||
@ -38,21 +40,24 @@ if(handle) then
|
||||
end
|
||||
end
|
||||
r, box = imap.reopen(handle,box:gsub("[^}]*$","INBOX"), false, true) -- half open off, debug on
|
||||
print(box)
|
||||
if r then
|
||||
print("new box opened", box)
|
||||
else
|
||||
print("reopen failed")
|
||||
end
|
||||
r,v = imap.ping(handle)
|
||||
v,r = imap.ping(handle)
|
||||
if r then
|
||||
print("Alive", v)
|
||||
else
|
||||
print("Unable to ping")
|
||||
end
|
||||
imap.check(handle);
|
||||
|
||||
local mbdata = imap.check(handle)
|
||||
dump(mbdata)
|
||||
-- get nmail
|
||||
local nmail = imap.get_nmail(handle);
|
||||
print("umber of mail", nmail);
|
||||
local nmail = imap.get_nmail(handle)
|
||||
print("umber of mail", nmail)
|
||||
|
||||
if nmail > 0 then
|
||||
local headers = imap.get_headers(handle)
|
||||
@ -68,5 +73,54 @@ if(handle) then
|
||||
local structure = imap.get_structure(handle, nmail)
|
||||
dump(structure)
|
||||
|
||||
-- append message to a mail box
|
||||
--if imap.append(handle, box:gsub("[^}]*$","Drafts"),
|
||||
-- "From: dany@iohub.dev\r\n"
|
||||
-- .. "To: xsang.le@gmail.com\r\n"
|
||||
-- .. "Subject: test\r\n"
|
||||
-- .. "\r\n"
|
||||
-- .. "this is a test message, please ignore\r\n") then
|
||||
-- print("Message appended")
|
||||
--else
|
||||
-- print("Error append message")
|
||||
--end
|
||||
|
||||
-- get body structure
|
||||
print("########## Get body section 1 structure")
|
||||
local bstruct = imap.get_body_struct(handle, nmail,"1" )
|
||||
dump(bstruct)
|
||||
|
||||
print("########## fetch overview messages")
|
||||
local ov = imap.get_overview(handle,string.format("1:%d", nmail), false)
|
||||
dump(ov)
|
||||
|
||||
print("########## fetch mime")
|
||||
local mime = imap.get_mime(handle,nmail,"1", true) -- peak the message without set it to seen
|
||||
dump(mime)
|
||||
|
||||
--print("########## get quota")
|
||||
--local quota = imap.get_quota(handle,"user.dany")
|
||||
--dump(quota)
|
||||
|
||||
--print("########## get quota root")
|
||||
--local quota = imap.get_quotaroot(handle,"INBOX")
|
||||
--dump(quota)
|
||||
|
||||
--print("########## get ACL")
|
||||
--local acl = imap.get_acl(handle,box)
|
||||
--dump(acl)
|
||||
|
||||
print("#mail subscriber")
|
||||
local sub = imap.get_subscribed(handle, box:gsub("[^}]*$",""), "*")
|
||||
dump(sub)
|
||||
|
||||
--print("#mailbox scan")
|
||||
--local sub = imap.scan_mailboxes(handle, box:gsub("[^}]*$",""), "*", "Junk")
|
||||
--dump(sub)
|
||||
|
||||
print("######### ERROR stack")
|
||||
dump(limap_errors)
|
||||
|
||||
print("Close handle")
|
||||
imap.close(handle)
|
||||
end
|
Loading…
Reference in New Issue
Block a user