#include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "c-client.h" #include "imap4r1.h" #include #include extern int errno; /* just in case */ #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__, \ __LINE__, ##__VA_ARGS__) #define M_ERROR(a,...) syslog (LOG_ERR, "limap@[%s: %d]: " a "\n", __FILE__, \ __LINE__, ##__VA_ARGS__) /* Co-routines from MAIL library */ /* Message matches a search * Accepts: MAIL stream * message number */ void mm_searched (MAILSTREAM *stream,unsigned long msgno) { /* dummy routine */ } /* Message exists (i.e. there are that many messages in the mailbox) * Accepts: MAIL stream * message number */ 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; } /* Message expunged * Accepts: MAIL stream * message number */ void mm_expunged (MAILSTREAM *stream,unsigned long number) { /* dummy routine */ } /* Message flags update seen * Accepts: MAIL stream * message number */ void mm_flags (MAILSTREAM *stream,unsigned long number) { /* dummy routine */ } /* Mailbox found * Accepts: MAIL stream * hierarchy delimiter * mailbox name * mailbox attributes */ void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes) { lua_State *L = stream->sparep; if(!L) return; if(attributes & LATT_NOSELECT) { return; } size_t cnt = lua_rawlen(L,-1) + 1; lua_pushnumber(L,cnt); lua_newtable(L); char delim[2]; delim[0] = (char) delimiter; delim[1] = '\0'; if(!name) return; lua_pushstring(L, "delimiter"); lua_pushstring(L, delim); lua_settable(L, -3); lua_pushstring(L, "name"); lua_pushstring(L, name); lua_settable(L, -3); lua_pushstring(L, "LATT_NOINFERIORS"); lua_pushboolean(L, attributes & LATT_NOINFERIORS); lua_settable(L, -3); lua_pushstring(L, "LATT_NOSELECT"); lua_pushboolean(L, attributes & LATT_NOSELECT); lua_settable(L, -3); lua_pushstring(L, "LATT_MARKED"); lua_pushboolean(L, attributes & LATT_MARKED); lua_settable(L, -3); lua_pushstring(L, "LATT_UNMARKED"); lua_pushboolean(L, attributes & LATT_UNMARKED); lua_settable(L, -3); lua_settable(L, -3); } /* Subscribe mailbox found * Accepts: MAIL stream * hierarchy delimiter * mailbox name * mailbox attributes */ void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes) { /* dummy routine */ } /* Mailbox status * Accepts: MAIL stream * mailbox name * mailbox status */ void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) { if (status->recent || status->unseen) printf ("%lu new message(s) (%lu unseen),",status->recent,status->unseen); else fputs ("No new messages,",stdout); printf (" %lu total in %s\n",status->messages,mailbox); } /* Notification event * Accepts: MAIL stream * string to log * error flag */ 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 */ } /* Log an event for the user to see * Accepts: string to log * error flag */ 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; } } /* Log an event to debugging telemetry * Accepts: string to log */ void mm_dlog (char *string) { M_LOG ("%s",string); } /* Get user name and password for this host * Accepts: parse of network mailbox name * where to return user name * where to return password * trial count */ void mm_login (NETMBX *mb,char *username,char *password,long trial) { if(mb->user) { 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); } } /* About to enter critical code * Accepts: stream */ void mm_critical (MAILSTREAM *stream) { /* note in critical code */ } /* About to exit critical code * Accepts: stream */ void mm_nocritical (MAILSTREAM *stream) { /* note not in critical code */ } /* Disk error found * Accepts: stream * system error code * flag indicating that mailbox may be clobbered * Returns: T if user wants to abort */ long mm_diskerror (MAILSTREAM *stream,long errcode,long serious) { return T; } /* Log a fatal error event * Accepts: string to log */ void mm_fatal (char *string) { M_ERROR ("FATAL: %s",string); } static int l_mail_open(lua_State *L) { const char* mailbox = luaL_checkstring(L,1); long flag = 0; if( lua_isnumber(L,2)) { flag = flag | (long)luaL_checknumber(L,2); } MAILSTREAM *stream = mail_open (NIL,(char*)mailbox,flag); if(!stream) { lua_pushnil(L); return 1; } //strncpy(stream->original_mailbox, stream->mailbox, strlen(stream->mailbox)); if(stream->original_mailbox) { free(stream->original_mailbox); } stream->original_mailbox = strdup(stream->mailbox); M_LOG("mailbox: %s", stream->mailbox); M_LOG("original_mailbox: %s", stream->original_mailbox); lua_pushlightuserdata(L, stream); lua_pushstring(L,stream->mailbox); return 2; } static int l_mail_close(lua_State *L) { MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); if(!stream) { lua_pushboolean(L,0); } else { (void) mail_close(stream); lua_pushboolean(L,1); } return 1; } static int l_get_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); if(!stream) { lua_pushboolean(L,0); return 1; } stream->sparep = (void*)L; lua_newtable(L); mail_list(stream,(char*)reference, (char*)pattern); return 1; } 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); } else { lua_pushboolean(L,1); } lua_pushnumber(L, new_mail); return 2; } static int l_mail_check(lua_State *L) { MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); if(!stream) { return 0; } mail_check(stream); return 0; } static int l_reopen(lua_State *L) { MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); const char* mailbox = luaL_checkstring(L,2); long flag = 0; if( lua_isnumber(L,3)) { flag = flag | (long)luaL_checknumber(L,3); } if(!stream) { lua_pushboolean(L,0); return 1; } stream = mail_open (stream,(char*)mailbox,flag); if(!stream) { lua_pushboolean(L,0); return 1; } if(stream->original_mailbox) { free(stream->original_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); lua_pushstring(L,stream->mailbox); return 2; } static const struct luaL_Reg _lib [] = { {"open", l_mail_open}, {"close", l_mail_close}, {"get_mail_boxes", l_get_mailboxes}, {"reopen", l_reopen}, {"ping", l_mail_ping}, {"check", l_mail_check}, {NULL,NULL} }; int luaopen_limap(lua_State *L) { #include "linkage.c" luaL_newlib(L, _lib); return 1; }