#include #include #include #include #include "tlmpmail.h" #include "tlmpmail.m" #include class FOLDER_FACTORY_SQL: public FOLDER_FACTORY{ FOLDER_VIEW *build(const char *path) { FOLDER_VIEW *ret = NULL; if (strncmp(path,"SQL/",4)==0){ ret = new FOLDER_SQL (path+4); } return ret; } bool exist(const char *path) { bool ret = false; if (strncmp(path,"SQL/",4)==0){ ret = folder_sql_exist (path+4); } return ret; } int list(SSTRINGS &tb) { return folder_sql_list (tb); } }; static FOLDER_FACTORY_SQL ff; static void folder_sql_init() { static bool is_init=false; if (!is_init){ query_setdefaultdb ("localhost","usermail"); is_init = true; } } /* Return the ID of an SQL folder */ int folder_sql_getid (const char *folder) { int id; glocal.id = -1; folder_sql_init(); NSQL_ENCODE enc; ("select id from folders" " where foldername='%s'",enc.enc(folder)); glocal.id = atoi(row[0]); return glocal.id; } /* Create a new SQL folder and assign an ID. Return the ID. */ int folder_sql_create (const char *folder) { NSQL_ENCODE enc; sql_action ("insert into folders (foldername) values ('%s')" ,enc.enc(folder)); return folder_sql_getid (folder); } PUBLIC FOLDER_SQL::FOLDER_SQL(const char *folder) { name.setfrom (folder); id = folder_sql_getid (folder); revision = -1; } /* Forget all message in tb[], but put in the garbage collector message still in use. */ PRIVATE void FOLDER_SQL::forget( bool deleted) // Forget deleted message or all { for (int i=tb.getnb()-1; i>=0; i--){ MAIL_MESSAGE *m = tb.getitem(i); if (!deleted || m->deleted){ if (m->getusage()>0){ m->assign (NULL); folders_register(m); tb.remove (i); }else{ tb.remove_del(i); } } } } PUBLIC int FOLDER_SQL::loadindex (MAIL_MESSAGES &idx, int &callerrev) { int ret = -1; idx.neverdelete(); int newrev = getrevision(); if (newrev != revision){ fprintf (stderr,"loading sql %d %d\n",newrev,revision); revision = newrev; forget(false); glocal MAIL_MESSAGES *tb = &tb; glocal MAIL_MESSAGE *m = NULL; glocal FOLDER_VIEW *folder = this; ("select messages.id,subject,msgid,replyid,deleted,replied,viewed,tagged,addrs.name,addr,type,comment,unix_timestamp(datesent),size" " from messages,addrs" " where folderid=%d and messages.id=addrs.id order by daterec,messages.id" ,id); // glocal.one.set (fields,row); int id = atoi(row[0]); if (glocal.m == NULL || glocal.m->fid != id){ glocal.m = new MAIL_MESSAGE; glocal.m->assign (glocal.folder); glocal.tb->add (glocal.m); glocal.m->fid = id; glocal.m->subject.setfrom(row[1]); glocal.m->id.setfrom(row[2]); glocal.m->replyid.setfrom (row[3]); glocal.m->deleted = row[4][0] == 'Y'; glocal.m->replied = row[5][0] == 'Y'; glocal.m->viewed = row[6][0] == 'Y'; glocal.m->tagged = row[7][0] == 'Y'; glocal.m->comment.setfrom (row[11]); glocal.m->date = atoi(row[12]); glocal.m->size = atoi(row[13]); } char type = row[10][0]; if (type == 'f'){ glocal.m->from.set (row[8],row[9]); }else if (type == 'c'){ glocal.m->cc.set (row[8],row[9]); }else if (type == 'r'){ glocal.m->reply.set (row[8],row[9]); }else if (type == 't'){ glocal.m->to.set (row[8],row[9]); }else if (type == 'd'){ glocal.m->flags.set_str (row[8],row[9]); }else{ fprintf (stderr,"folder_sql::loadindex: Invalid type %c\n",type); } fprintf (stderr,"end\n"); ret = 0; } if (revision != callerrev){ callerrev = revision; idx.remove_all(); for (int i=0; i /* Insert a message flags in the addrs table */ static void folder_sql_insertflags (int id, const DICTIONARY &flags) { NSQL_ENCODE enc; for (int i=0; ideleted){ int fid = m->fid; sql_action ("delete from addrs where id=%d",fid); sql_action ("delete from parts where id=%d",fid); } } forget(true); wakeup(); } } return 0; } PUBLIC const char *FOLDER_SQL::gettitle () { return name.get(); } PUBLIC int FOLDER_SQL::loadmsg (const MAIL_MESSAGE &msg, MAIL_MESSAGE_FULL &full) { glocal MAIL_MESSAGE_FULL *full = &full; glocal int ret = -1; msg.copy (full); ("select message,header from parts where id=%d",msg.fid); glocal.full->text.setfrom (row[0]); glocal.full->header.setfrom (row[1]); glocal.ret = 0; full.parse_header(); return glocal.ret; } PUBLIC bool FOLDER_SQL::is_postponed() { return false; } PUBLIC bool FOLDER_SQL::is_shared() { return false; } PUBLIC int FOLDER_SQL::getid(SSTRING &id) { id.setfromf ("SQL/%s",name.get()); return 0; } /* Return the update revision of the folder */ PUBLIC int FOLDER_SQL::getrevision() { glocal int ret = -1; ("select revision from folders where id=%d",id); glocal.ret = atoi(row[0]); return glocal.ret; } static void folder_sql_insertadr ( int fid, // Message ID EMAILADDRS &adrs, char type) { NSQL_ENCODE enc; for (int i=0; i PUBLIC int FOLDER_SQL::appendmsg (MAIL_MESSAGE_FULL &full) { int ret = -1; if (id == -1) folder_sql_create (name.get()); if (id != -1){ NSQL_ENCODE enc; char datesent[20]; struct tm *t = localtime (&full.date); snprintf (datesent,sizeof(datesent)-1,"%4d/%02d/%02d %02d:%02d:%02d" ,t->tm_year+1900,t->tm_mon+1,t->tm_mday ,t->tm_hour,t->tm_min,t->tm_sec); ret = sql_action ("insert into messages" " (folderid,subject,msgid,replyid,datesent" ",deleted,replied,viewed,tagged,daterec,comment,size)" " values " " (%d,'%s','%s','%s','%s','%c','%c','%c','%c',now(),'%s',%d)" ,id,enc.enc(full.subject),enc.enc(full.id),enc.enc(full.replyid) ,datesent ,full.deleted ? 'Y' : 'N' ,full.replied ? 'Y' : 'N' ,full.viewed ? 'Y' : 'N' ,full.tagged ? 'Y' : 'N' ,enc.enc(full.comment) ,full.text.getlen() ); if(ret != -1){ int fid = sql_getlastid(); sql_action ("insert into parts (id,message,header) values (%d,'%s','%s')" ,fid,enc.enc(full.text),enc.enc(full.header)); folder_sql_insertadr (fid,full.from,'f'); folder_sql_insertadr (fid,full.to,'t'); folder_sql_insertadr (fid,full.reply,'r'); folder_sql_insertadr (fid,full.cc,'c'); folder_sql_insertflags (fid,full.flags); incrrevision(); } } return ret; } int folder_sql_list (SSTRINGS &tb) { SSTRINGS *tb; glocal.tb = &tb; folder_sql_init(); int ret = ("select foldername from folders"); SSTRING *s = new SSTRING; s->setfromf ("SQL/%s",row[0]); glocal.tb->add (s); return ret; } bool folder_sql_exist (const char *name) { folder_sql_init(); NSQL_ENCODE enc; int nb = ("select foldername from folders" " where foldername='%s'",enc.enc(name)); return nb == 1; } PUBLIC bool FOLDER_SQL::msgexist (MAIL_MESSAGE &msg) { glocal bool ret = false; NSQL_ENCODE enc; ("select count(*) from messages" " where folderid=%d and msgid='%s'" ,id,enc.enc(msg.id)); glocal.ret = atoi(row[0]) > 0; return glocal.ret; } PUBLIC void FOLDER_SQL::getupdmsgs (PRIVATE_MESSAGES &upds) { upds.add (&updmsg); } PUBLIC void FOLDER_SQL::checkupdate () { int newrev = getrevision(); if (newrev != revision) dialog_sendmessage (updmsg); }