From e3b89230f065c48c84b48c88edb6eb088374c487 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 03 Jul 2004 16:33:12 +0000 Subject: Initial revision --- (limited to 'kmicromail') diff --git a/kmicromail/.cvsignore b/kmicromail/.cvsignore new file mode 100644 index 0000000..3819f80 --- a/dev/null +++ b/kmicromail/.cvsignore @@ -0,0 +1,32 @@ +.moc +Makefile +addresspickerui.cpp +addresspickerui.h +composemailui.cpp +composemailui.h +editaccountsui.cpp +editaccountsui.h +imapconfigui.cpp +imapconfigui.h +logindialogui.cpp +logindialogui.h +nntpconfigui.cpp +nntpconfigui.h +pop3configui.cpp +pop3configui.h +selectmailtypeui.cpp +selectmailtypeui.h +smtpconfigui.cpp +smtpconfigui.h +settingsdialogui.cpp +settingsdialogui.h +statuswidgetui.cpp +statuswidgetui.h +newmaildirui.cpp +newmaildirui.h +sendmailprogressui.cpp +sendmailprogressui.h +selectstoreui.cpp +selectstoreui.h +nntpgroupsui.cpp +nntpgroupsui.h diff --git a/kmicromail/ProgrammersDoc/ReceivingMails.dia b/kmicromail/ProgrammersDoc/ReceivingMails.dia new file mode 100644 index 0000000..4e63dc6 --- a/dev/null +++ b/kmicromail/ProgrammersDoc/ReceivingMails.dia Binary files differ diff --git a/kmicromail/ProgrammersDoc/readme.txt b/kmicromail/ProgrammersDoc/readme.txt new file mode 100644 index 0000000..9ae3ded --- a/dev/null +++ b/kmicromail/ProgrammersDoc/readme.txt @@ -0,0 +1,6 @@ +This directory contains description how opiemail works and is implemented. + + +ReceivingMail.dia +================= +dia file containing the description of classes describing a a received mail. diff --git a/kmicromail/TODO b/kmicromail/TODO new file mode 100644 index 0000000..044dbb1 --- a/dev/null +++ b/kmicromail/TODO @@ -0,0 +1,11 @@ +- crosscompile libEtPan! +- do at least some error checking and report them to the user +- thread the whole send/recieve thing +- add mail recieve support +- queue mails for sending +- check source for memory leaks (there is a whole bunch out there) +- make bigger (64x64) desktop icon +- rename app to "mail" +- opie taskbar plugin +- integrate in opie pim +- get some sleep diff --git a/kmicromail/accountitem.cpp b/kmicromail/accountitem.cpp new file mode 100644 index 0000000..d0321ef --- a/dev/null +++ b/kmicromail/accountitem.cpp @@ -0,0 +1,1140 @@ + +#include "accountitem.h" +#include "accountview.h" +#include "newmaildir.h" +#include "nntpgroupsdlg.h" +#include "defines.h" + +#include +#include +#include +/* OPIE */ +//#include + +/* QT */ +#include +#include +#include + +using namespace Opie::Core; +#define SETPIX(x) if (!account->getOffline()) {setPixmap( 0,x);} else {setPixmap( 0, PIXMAP_OFFLINE );} +/** + * POP3 Account stuff + */ +POP3viewItem::POP3viewItem( POP3account *a, AccountView *parent ) + : AccountViewItem( parent ) +{ + account = a; + wrapper = AbstractMail::getWrapper( account ); + SETPIX(PIXMAP_POP3FOLDER); +#if 0 + if (!account->getOffline()) + { + setPixmap( 0, ); + } + else + { + setPixmap( 0, PIXMAP_OFFLINE ); + } +#endif + setText( 0, account->getAccountName() ); + setOpen( true ); +} + +POP3viewItem::~POP3viewItem() +{ + delete wrapper; +} + +AbstractMail *POP3viewItem::getWrapper() +{ + return wrapper; +} + +void POP3viewItem::refresh(QValueList > & ) +{ + refresh(); +} + +void POP3viewItem::refresh() +{ + if (account->getOffline()) return; + QValueList *folders = wrapper->listFolders(); + QListViewItem *child = firstChild(); + while ( child ) + { + QListViewItem *tmp = child; + child = child->nextSibling(); + delete tmp; + } + QValueList::ConstIterator it; + QListViewItem*item = 0; + for ( it = folders->begin(); it!=folders->end(); ++it) + { + item = new POP3folderItem( (*it), this , item ); + item->setSelectable( (*it)->may_select()); + } + delete folders; +} + +RECBODYP POP3viewItem::fetchBody( const RecMailP &mail ) +{ + + return wrapper->fetchBody( mail ); +} + +QPopupMenu * POP3viewItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + if (!account->getOffline()) + { + m->insertItem(QObject::tr("Disconnect",contextName),0); + m->insertItem(QObject::tr("Set offline",contextName),1); + } + else + { + m->insertItem(QObject::tr("Set online",contextName),1); + } + } + return m; +} + +void POP3viewItem::disconnect() +{ + QListViewItem *child = firstChild(); + while ( child ) + { + QListViewItem *tmp = child; + child = child->nextSibling(); + delete tmp; + } + wrapper->logout(); +} + +void POP3viewItem::setOnOffline() +{ + if (!account->getOffline()) + { + disconnect(); + } + account->setOffline(!account->getOffline()); + account->save(); + SETPIX(PIXMAP_POP3FOLDER); + refresh(); +} + +void POP3viewItem::contextMenuSelected(int which) +{ + switch (which) + { + case 0: + disconnect(); + break; + case 1: + setOnOffline(); + break; + } +} + +POP3folderItem::~POP3folderItem() +{} + +POP3folderItem::POP3folderItem( const FolderP&folderInit, POP3viewItem *parent , QListViewItem*after ) + : AccountViewItem(folderInit,parent,after ) +{ + pop3 = parent; + if (folder->getDisplayName().lower()!="inbox") + { + setPixmap( 0, PIXMAP_POP3FOLDER ); + } + else + { + setPixmap( 0, PIXMAP_INBOXFOLDER); + } + setText( 0, folder->getDisplayName() ); +} + +void POP3folderItem::refresh(QValueList&target) +{ + if (folder->may_select()) + pop3->getWrapper()->listMessages( folder->getName(),target ); +} + +RECBODYP POP3folderItem::fetchBody(const RecMailP&aMail) +{ + return pop3->getWrapper()->fetchBody(aMail); +} + +QPopupMenu * POP3folderItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + m->insertItem(QObject::tr("Refresh header list",contextName),0); + m->insertItem(QObject::tr("Delete all mails",contextName),1); + m->insertItem(QObject::tr("Move/Copie all mails",contextName),2); + } + return m; +} + +void POP3folderItem::downloadMails() +{ + AccountView*bl = pop3->accountView(); + if (!bl) return; + bl->downloadMails(folder,pop3->getWrapper()); +} + +void POP3folderItem::contextMenuSelected(int which) +{ + AccountView * view = (AccountView*)listView(); + switch (which) + { + case 0: + /* must be 'cause pop3 lists are cached */ + pop3->getWrapper()->logout(); + view->refreshCurrent(); + break; + case 1: + deleteAllMail(pop3->getWrapper(),folder); + break; + case 2: + downloadMails(); + break; + default: + break; + } +} + +/** + * NNTP Account stuff + */ +NNTPviewItem::NNTPviewItem( NNTPaccount *a, AccountView *parent ) + : AccountViewItem( parent ) +{ + account = a; + wrapper = AbstractMail::getWrapper( account ); + //FIXME + SETPIX(PIXMAP_POP3FOLDER); +#if 0 + if (!account->getOffline()) + { + setPixmap( 0, ); + } + else + { + setPixmap( 0, PIXMAP_OFFLINE ); + } +#endif + setText( 0, account->getAccountName() ); + setOpen( true ); +} + +NNTPviewItem::~NNTPviewItem() +{ + delete wrapper; +} + +AbstractMail *NNTPviewItem::getWrapper() +{ + return wrapper; +} + +void NNTPviewItem::refresh( QValueList & ) +{ + refresh(); +} + +void NNTPviewItem::refresh() +{ + if (account->getOffline()) return; + QValueList *folders = wrapper->listFolders(); + + QListViewItem *child = firstChild(); + while ( child ) + { + QListViewItem *tmp = child; + child = child->nextSibling(); + delete tmp; + } + QValueList::ConstIterator it; + QListViewItem*item = 0; + for ( it = folders->begin(); it!=folders->end(); ++it) + { + item = new NNTPfolderItem( (*it), this , item ); + item->setSelectable( (*it)->may_select()); + } + delete folders; +} + +RECBODYP NNTPviewItem::fetchBody( const RecMailP &mail ) +{ + + return wrapper->fetchBody( mail ); +} + +QPopupMenu * NNTPviewItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + if (!account->getOffline()) + { + m->insertItem(QObject::tr("Disconnect",contextName),0); + m->insertItem(QObject::tr("Set offline",contextName),1); + m->insertItem(QObject::tr("(Un-)Subscribe groups",contextName),2); + } + else + { + m->insertItem(QObject::tr("Set online",contextName),1); + } + } + return m; +} + +void NNTPviewItem::subscribeGroups() +{ + NNTPGroupsDlg dlg(account); + dlg.showMaximized(); + if ( dlg.exec()== QDialog::Accepted ){ + refresh(); + } +} + +void NNTPviewItem::disconnect() +{ + QListViewItem *child = firstChild(); + while ( child ) + { + QListViewItem *tmp = child; + child = child->nextSibling(); + delete tmp; + } + wrapper->logout(); +} + +void NNTPviewItem::setOnOffline() +{ + if (!account->getOffline()) + { + disconnect(); + } + account->setOffline(!account->getOffline()); + account->save(); + //FIXME + SETPIX(PIXMAP_POP3FOLDER); + refresh(); +} + +void NNTPviewItem::contextMenuSelected(int which) +{ + switch (which) + { + case 0: + disconnect(); + break; + case 1: + setOnOffline(); + break; + case 2: + subscribeGroups(); + break; + } +} + +NNTPfolderItem::~NNTPfolderItem() +{} + +NNTPfolderItem::NNTPfolderItem( const FolderP &folderInit, NNTPviewItem *parent , QListViewItem*after ) + : AccountViewItem( folderInit, parent,after ) +{ + nntp = parent; + if (folder->getDisplayName().lower()!="inbox") + { + setPixmap( 0, PIXMAP_POP3FOLDER ); + } + else + { + setPixmap( 0, PIXMAP_INBOXFOLDER); + } + setText( 0, folder->getDisplayName() ); +} + +void NNTPfolderItem::refresh(QValueList&target) +{ + if (folder->may_select()) + nntp->getWrapper()->listMessages( folder->getName(),target ); +} + +RECBODYP NNTPfolderItem::fetchBody(const RecMailP&aMail) +{ + return nntp->getWrapper()->fetchBody(aMail); +} + +QPopupMenu * NNTPfolderItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + m->insertItem(QObject::tr("Refresh header list",contextName),0); + m->insertItem(QObject::tr("Copy all postings",contextName),1); + } + return m; +} + +void NNTPfolderItem::downloadMails() +{ + AccountView*bl = nntp->accountView(); + if (!bl) return; + bl->downloadMails(folder,nntp->getWrapper()); +} + +void NNTPfolderItem::contextMenuSelected(int which) +{ + AccountView * view = (AccountView*)listView(); + switch (which) + { + case 0: + /* must be 'cause pop3 lists are cached */ + nntp->getWrapper()->logout(); + view->refreshCurrent(); + break; + case 1: + downloadMails(); + break; + default: + break; + } +} + +/** + * IMAP Account stuff + */ +IMAPviewItem::IMAPviewItem( IMAPaccount *a, AccountView *parent ) + : AccountViewItem( parent ) +{ + account = a; + wrapper = AbstractMail::getWrapper( account ); + SETPIX(PIXMAP_IMAPFOLDER); + setText( 0, account->getAccountName() ); + setOpen( true ); +} + +IMAPviewItem::~IMAPviewItem() +{ + delete wrapper; +} + +AbstractMail *IMAPviewItem::getWrapper() +{ + return wrapper; +} + +void IMAPviewItem::refresh(QValueList&) +{ + refreshFolders(false); +} + +const QStringList&IMAPviewItem::subFolders() +{ + return currentFolders; +} + +void IMAPviewItem::refreshFolders(bool force) +{ + if (childCount()>0 && force==false) return; + if (account->getOffline()) return; + + removeChilds(); + currentFolders.clear(); + QValueList * folders = wrapper->listFolders(); + + QValueList::Iterator it; + QListViewItem*item = 0; + QListViewItem*titem = 0; + QString fname,del,search; + int pos; + + for ( it = folders->begin(); it!=folders->end(); ++it) + { + if ((*it)->getDisplayName().lower()=="inbox") + { + item = new IMAPfolderItem( (*it), this , item ); + folders->remove(it); + break; + } + } + for ( it = folders->begin(); it!=folders->end(); ++it) + { + fname = (*it)->getDisplayName(); + currentFolders.append((*it)->getName()); + pos = fname.findRev((*it)->Separator()); + if (pos != -1) + { + fname = fname.left(pos); + } + IMAPfolderItem*pitem = (IMAPfolderItem*)findSubItem(fname); + if (pitem) + { + titem = item; + item = new IMAPfolderItem( (*it),pitem,pitem->firstChild(),this); + /* setup the short name */ + item->setText(0,(*it)->getDisplayName().right((*it)->getDisplayName().length()-pos-1)); + item = titem; + } + else + { + item = new IMAPfolderItem( (*it), this , item ); + } + } + delete folders; +} + +QPopupMenu * IMAPviewItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + if (!account->getOffline()) + { + m->insertItem(QObject::tr("Refresh folder list",contextName),0); + m->insertItem(QObject::tr("Create new folder",contextName),1); + m->insertSeparator(); + m->insertItem(QObject::tr("Disconnect",contextName),2); + m->insertItem(QObject::tr("Set offline",contextName),3); + } + else + { + m->insertItem(QObject::tr("Set online",contextName),3); + } + } + return m; +} + +void IMAPviewItem::createNewFolder() +{ + Newmdirdlg ndirdlg; + + ndirdlg.showMaximized(); + if ( ndirdlg.exec() ) + { + QString ndir = ndirdlg.Newdir(); + bool makesubs = ndirdlg.subpossible(); + QString delemiter = "/"; + IMAPfolderItem*item = (IMAPfolderItem*)firstChild(); + if (item) + { + delemiter = item->Delemiter(); + } + if (wrapper->createMbox(ndir,0,delemiter,makesubs)) + { + refreshFolders(true); + } + } +} + +void IMAPviewItem::contextMenuSelected(int id) +{ + + switch (id) + { + case 0: + refreshFolders(true); + break; + case 1: + createNewFolder(); + break; + case 2: + removeChilds(); + wrapper->logout(); + break; + case 3: + if (account->getOffline()==false) + { + removeChilds(); + wrapper->logout(); + } + account->setOffline(!account->getOffline()); + account->save(); + SETPIX(PIXMAP_IMAPFOLDER); + refreshFolders(false); + break; + default: + break; + } +} + +RECBODYP IMAPviewItem::fetchBody(const RecMailP&) +{ + return new RecBody(); +} + +bool IMAPviewItem::offline() +{ + return account->getOffline(); +} + +IMAPfolderItem::IMAPfolderItem( const FolderP& folderInit, IMAPviewItem *parent , QListViewItem*after ) + : AccountViewItem( folderInit, parent , after ) +{ + imap = parent; + if (folder->getDisplayName().lower()!="inbox") + { + setPixmap( 0, PIXMAP_IMAPFOLDER ); + } + else + { + setPixmap( 0, PIXMAP_INBOXFOLDER); + } + setText( 0, folder->getDisplayName() ); +} + +IMAPfolderItem::IMAPfolderItem(const FolderP &folderInit, IMAPfolderItem *parent , QListViewItem*after, IMAPviewItem *master ) + : AccountViewItem(folderInit, parent,after ) +{ + imap = master; + if (folder->getDisplayName().lower()!="inbox") + { + setPixmap( 0, PIXMAP_IMAPFOLDER ); + } + else + { + setPixmap( 0, PIXMAP_INBOXFOLDER); + } + setText( 0, folder->getDisplayName() ); +} + +IMAPfolderItem::~IMAPfolderItem() +{} + +const QString& IMAPfolderItem::Delemiter()const +{ + return folder->Separator(); +} + +void IMAPfolderItem::refresh(QValueList&target) +{ + if (folder->may_select()) + { + imap->getWrapper()->listMessages( folder->getName(),target ); + } + else + { + target.clear(); + } +} + +RECBODYP IMAPfolderItem::fetchBody(const RecMailP&aMail) +{ + return imap->getWrapper()->fetchBody(aMail); +} + +QPopupMenu * IMAPfolderItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + if (folder->may_select()) + { + m->insertItem(QObject::tr("Refresh header list",contextName),0); + m->insertItem(QObject::tr("Move/Copie all mails",contextName),4); + m->insertItem(QObject::tr("Delete all mails",contextName),1); + } + if (folder->no_inferior()==false) + { + m->insertItem(QObject::tr("Create new subfolder",contextName),2); + } + if (folder->getDisplayName().lower()!="inbox") + { + m->insertItem(QObject::tr("Delete folder",contextName),3); + } + } + return m; +} + +void IMAPfolderItem::createNewFolder() +{ + Newmdirdlg ndirdlg; + ndirdlg.showMaximized(); + if ( ndirdlg.exec() ) + { + QString ndir = ndirdlg.Newdir(); + bool makesubs = ndirdlg.subpossible(); + QString delemiter = Delemiter(); + if (imap->wrapper->createMbox(ndir,folder,delemiter,makesubs)) + { + imap->refreshFolders(true); + } + } +} + +void IMAPfolderItem::deleteFolder() +{ + int yesno = QMessageBox::warning(0,QObject::tr("Delete folder",contextName), + QObject::tr("
Realy delete folder
%1
and all if it content?
",contextName).arg(folder->getDisplayName()), + QObject::tr("Yes",contextName), + QObject::tr("No",contextName),QString::null,1,1); + + if (yesno == 0) + { + if (imap->getWrapper()->deleteMbox(folder)) + { + QListView*v=listView(); + IMAPviewItem * box = imap; + /* be carefull - after that this object is destroyd so don't use + * any member of it after that call!!*/ + imap->refreshFolders(true); + if (v) + { + v->setSelected(box,true); + } + } + } +} + +void IMAPfolderItem::downloadMails() +{ + AccountView*bl = imap->accountView(); + if (!bl) return; + bl->downloadMails(folder,imap->getWrapper()); +} + +void IMAPfolderItem::contextMenuSelected(int id) +{ + + AccountView * view = (AccountView*)listView(); + switch(id) + { + case 0: + view->refreshCurrent(); + break; + case 1: + deleteAllMail(imap->getWrapper(),folder); + break; + case 2: + createNewFolder(); + break; + case 3: + deleteFolder(); + break; + case 4: + downloadMails(); + break; + default: + break; + } +} + +/** + * MH Account stuff + */ +/* MH is a little bit different - the top folder can contains messages other than in IMAP and + POP3 and MBOX */ +MHviewItem::MHviewItem( const QString&aPath, AccountView *parent ) + : AccountViewItem( parent ) +{ + m_Path = aPath; + /* be carefull - the space within settext is wanted - thats why the string twice */ + wrapper = AbstractMail::getWrapper( m_Path,"Local Folders"); + setPixmap( 0, PIXMAP_LOCALFOLDER ); + setText( 0, " Local Folders" ); + setOpen( true ); + folder = 0; +} + +MHviewItem::~MHviewItem() +{ + delete wrapper; +} + +AbstractMail *MHviewItem::getWrapper() +{ + return wrapper; +} + +void MHviewItem::refresh( QValueList & target) +{ + refresh(false); + getWrapper()->listMessages( "",target ); +} + +void MHviewItem::refresh(bool force) +{ + if (childCount()>0 && force==false) return; + removeChilds(); + currentFolders.clear(); + QValueList *folders = wrapper->listFolders(); + QValueList::ConstIterator it; + MHfolderItem*item = 0; + MHfolderItem*pmaster = 0; + QString fname = ""; + int pos; + for ( it = folders->begin(); it!=folders->end(); ++it) + { + fname = (*it)->getDisplayName(); + /* this folder itself */ + if (fname=="/") + { + currentFolders.append(fname); + folder = (*it); + continue; + } + currentFolders.append(fname); + pos = fname.findRev("/"); + if (pos > 0) + { + fname = fname.left(pos); + pmaster = (MHfolderItem*)findSubItem(fname); + } + else + { + pmaster = 0; + } + if (pmaster) + { + item = new MHfolderItem( (*it), pmaster, item, this ); + } + else + { + item = new MHfolderItem( (*it), this , item ); + } + item->setSelectable((*it)->may_select()); + } + delete folders; +} + +RECBODYP MHviewItem::fetchBody( const RecMailP &mail ) +{ + + return wrapper->fetchBody( mail ); +} + +QPopupMenu * MHviewItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + m->insertItem(QObject::tr("Refresh folder list",contextName),0); + m->insertItem(QObject::tr("Create new folder",contextName),1); + m->insertItem(QObject::tr("Delete all mails",contextName),2); + m->insertItem(QObject::tr("Move/Copie all mails",contextName),3); + } + return m; +} + +void MHviewItem::createFolder() +{ + Newmdirdlg ndirdlg(0,0,true); + ndirdlg.showMaximized(); + if ( ndirdlg.exec() ) + { + QString ndir = ndirdlg.Newdir(); + if (wrapper->createMbox(ndir)) + { + refresh(true); + } + } +} + +void MHviewItem::downloadMails() +{ + AccountView*bl = accountView(); + if (!bl) return; + bl->downloadMails(folder,getWrapper()); +} + +QStringList MHviewItem::subFolders() +{ + return currentFolders; +} + +void MHviewItem::contextMenuSelected(int which) +{ + switch (which) + { + case 0: + refresh(true); + break; + case 1: + createFolder(); + break; + case 2: + deleteAllMail(getWrapper(),folder); + break; + case 3: + downloadMails(); + break; + default: + break; + } +} + +MHfolderItem::~MHfolderItem() +{} + +MHfolderItem::MHfolderItem( const FolderP &folderInit, MHviewItem *parent , QListViewItem*after ) + : AccountViewItem(folderInit, parent,after ) +{ + mbox = parent; + initName(); +} + +MHfolderItem::MHfolderItem(const FolderP& folderInit, MHfolderItem *parent, QListViewItem*after, MHviewItem*master) + : AccountViewItem(folderInit, parent,after ) +{ + folder = folderInit; + mbox = master; + initName(); +} + +void MHfolderItem::initName() +{ + QString bName = folder->getDisplayName(); + if (bName.startsWith("/")&&bName.length()>1) + { + bName.replace(0,1,""); + } + int pos = bName.findRev("/"); + if (pos > 0) + { + bName.replace(0,pos+1,""); + } + if (bName.lower() == "outgoing") + { + setPixmap( 0, PIXMAP_OUTBOXFOLDER ); + } + else if (bName.lower() == "inbox") + { + setPixmap( 0, PIXMAP_INBOXFOLDER); + } else if (bName.lower() == "drafts") { + setPixmap(0, SmallIcon ("edit")); + } else { + setPixmap( 0, PIXMAP_MBOXFOLDER ); + } + setText( 0, bName ); +} + +const FolderP&MHfolderItem::getFolder()const +{ + return folder; +} + +void MHfolderItem::refresh(QValueList&target) +{ + if (folder->may_select()) + mbox->getWrapper()->listMessages( folder->getName(),target ); +} + +RECBODYP MHfolderItem::fetchBody(const RecMailP&aMail) +{ + return mbox->getWrapper()->fetchBody(aMail); +} + +void MHfolderItem::deleteFolder() +{ + int yesno = QMessageBox::warning(0,QObject::tr("Delete folder",contextName), + QObject::tr("
Realy delete folder
%1
and all if it content?
",contextName).arg(folder->getDisplayName()), + QObject::tr("Yes",contextName), + QObject::tr("No",contextName),QString::null,1,1); + + if (yesno == 0) + { + if (mbox->getWrapper()->deleteMbox(folder)) + { + QListView*v=listView(); + MHviewItem * box = mbox; + /* be carefull - after that this object is destroyd so don't use + * any member of it after that call!!*/ + mbox->refresh(true); + if (v) + { + v->setSelected(box,true); + } + } + } +} + +QPopupMenu * MHfolderItem::getContextMenu() +{ + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + m->insertItem(QObject::tr("Move/Copie all mails",contextName),2); + m->insertItem(QObject::tr("Delete all mails",contextName),0); + m->insertItem(QObject::tr("Create new subfolder",contextName),3); + m->insertItem(QObject::tr("Delete folder",contextName),1); + } + return m; +} + +void MHfolderItem::downloadMails() +{ + AccountView*bl = mbox->accountView(); + if (!bl) return; + bl->downloadMails(folder,mbox->getWrapper()); +} + +void MHfolderItem::createFolder() +{ + Newmdirdlg ndirdlg(0,0,true); + ndirdlg.showMaximized(); + if (ndirdlg.exec() ) + { + QString ndir = ndirdlg.Newdir(); + if (mbox->getWrapper()->createMbox(ndir,folder)) + { + QListView*v=listView(); + MHviewItem * box = mbox; + /* be carefull - after that this object is destroyd so don't use + * any member of it after that call!!*/ + mbox->refresh(true); + if (v) + { + v->setSelected(box,true); + } + } + } +} + +void MHfolderItem::contextMenuSelected(int which) +{ + switch(which) + { + case 0: + deleteAllMail(mbox->getWrapper(),folder); + break; + case 1: + deleteFolder(); + break; + case 2: + downloadMails(); + break; + case 3: + createFolder(); + break; + default: + break; + } +} + +bool MHfolderItem::isDraftfolder() +{ + if (folder && folder->getName()==AbstractMail::defaultLocalfolder()+"/"+AbstractMail::draftFolder()) return true; + return false; +} + +/** + * Generic stuff + */ + +const QString AccountViewItem::contextName="AccountViewItem"; + +AccountViewItem::AccountViewItem( AccountView *parent ) + : QListViewItem( parent ) +{ + init(); + m_Backlink = parent; +} + +AccountViewItem::AccountViewItem( QListViewItem *parent) + : QListViewItem( parent),folder(0) +{ + init(); +} + +AccountViewItem::AccountViewItem( QListViewItem *parent , QListViewItem*after ) + :QListViewItem( parent,after ),folder(0) +{ + init(); +} + +AccountViewItem::AccountViewItem( const Opie::Core::OSmartPointer&folderInit,QListViewItem *parent , QListViewItem*after ) + :QListViewItem( parent,after ),folder(folderInit) +{ + init(); +} + +void AccountViewItem::init() +{ + m_Backlink = 0; +} + +AccountViewItem::~AccountViewItem() +{ + folder = 0; +} + +AccountView*AccountViewItem::accountView() +{ + return m_Backlink; +} + +void AccountViewItem::deleteAllMail(AbstractMail*wrapper,const FolderP&folder) +{ + if (!wrapper) return; + QString fname=""; + if (folder) fname = folder->getDisplayName(); + int yesno = QMessageBox::warning(0,QObject::tr("Delete all mails",contextName), + QObject::tr("
Realy delete all mails in box
%1
",contextName). + arg(fname), + QObject::tr("Yes",contextName), + QObject::tr("No",contextName),QString::null,1,1); + + if (yesno == 0) + { + if (wrapper->deleteAllMail(folder)) + { + AccountView * view = (AccountView*)listView(); + if (view) view->refreshCurrent(); + } + } +} + +void AccountViewItem::removeChilds() +{ + QListViewItem *child = firstChild(); + while ( child ) + { + QListViewItem *tmp = child; + child = child->nextSibling(); + delete tmp; + } +} + +bool AccountViewItem::matchName(const QString&name)const +{ + if (!folder) return false; + return folder->getDisplayName()==name; +} + + +AccountViewItem*AccountViewItem::findSubItem(const QString&path,AccountViewItem*start) +{ + AccountViewItem*pitem,*sitem; + if (!start) pitem = (AccountViewItem*)firstChild(); + else pitem = (AccountViewItem*)start->firstChild(); + while (pitem) + { + if (pitem->matchName(path)) + { + break; + } + if (pitem->childCount()>0) + { + sitem = findSubItem(path,pitem); + if (sitem) + { + pitem = sitem; + break; + } + } + pitem=(AccountViewItem*)pitem->nextSibling(); + } + return pitem; +} + +bool AccountViewItem::isDraftfolder() +{ + return false; +} diff --git a/kmicromail/accountitem.h b/kmicromail/accountitem.h new file mode 100644 index 0000000..f125eeb --- a/dev/null +++ b/kmicromail/accountitem.h @@ -0,0 +1,212 @@ +#ifndef __ACCOUNT_ITEM +#define __ACCOUNT_ITEM + +#include +#include +#include + +class POP3wrapper; +class RecMail; +class RecBody; +class QPopupMenu; +class Selectstore; +class AccountView; +class POP3account; +class NNTPaccount; +class IMAPaccount; +class AbstractMail; +class Folder; + +#define RECBODYP Opie::Core::OSmartPointer + +class AccountViewItem : public QListViewItem +{ + +public: + AccountViewItem( AccountView *parent ); + AccountViewItem( QListViewItem *parent); + AccountViewItem( QListViewItem *parent , QListViewItem*after ); + AccountViewItem( const Opie::Core::OSmartPointer&folderInit,QListViewItem *parent , QListViewItem*after ); + + virtual ~AccountViewItem(); + virtual void refresh(QValueList >&)=0; + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&)=0; + virtual QPopupMenu * getContextMenu(){return 0;}; + virtual void contextMenuSelected(int){} + virtual AccountView*accountView(); + virtual bool matchName(const QString&name)const; + virtual bool isDraftfolder(); + +protected: + AccountViewItem*findSubItem(const QString&path,AccountViewItem*start=0); + virtual void init(); + virtual void removeChilds(); + virtual void deleteAllMail(AbstractMail*wrapper,const Opie::Core::OSmartPointer&f); + static const QString contextName; + AccountView*m_Backlink; + Opie::Core::OSmartPointer folder; +}; + +class POP3viewItem : public AccountViewItem +{ + +public: + POP3viewItem( POP3account *a, AccountView *parent ); + virtual ~POP3viewItem(); + virtual void refresh(QValueList >&target ); + virtual RECBODYP fetchBody( const Opie::Core::OSmartPointer &mail ); + AbstractMail *getWrapper(); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + +protected: + POP3account *account; + virtual void refresh(); + AbstractMail *wrapper; + void disconnect(); + void setOnOffline(); +}; + +class POP3folderItem : public AccountViewItem +{ + +public: + POP3folderItem( const Opie::Core::OSmartPointer&folder, POP3viewItem *parent , QListViewItem*after ); + virtual ~POP3folderItem(); + virtual void refresh(QValueList >&); + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + +protected: + void downloadMails(); + POP3viewItem *pop3; +}; + + +class NNTPviewItem : public AccountViewItem +{ + +public: + NNTPviewItem( NNTPaccount *a, AccountView *parent ); + virtual ~NNTPviewItem(); + virtual void refresh(QValueList >&target ); + virtual RECBODYP fetchBody( const Opie::Core::OSmartPointer &mail ); + AbstractMail *getWrapper(); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + +protected: + NNTPaccount *account; + virtual void refresh(); + AbstractMail *wrapper; + void disconnect(); + void setOnOffline(); + void subscribeGroups(); +}; + +class NNTPfolderItem : public AccountViewItem +{ + +public: + NNTPfolderItem(const Opie::Core::OSmartPointer&folder, NNTPviewItem *parent , QListViewItem*after ); + virtual ~NNTPfolderItem(); + virtual void refresh(QValueList >&); + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + +protected: + void downloadMails(); + NNTPviewItem *nntp; +}; + + + +class IMAPviewItem : public AccountViewItem +{ + friend class IMAPfolderItem; +public: + IMAPviewItem( IMAPaccount *a, AccountView *parent ); + virtual ~IMAPviewItem(); + virtual void refresh(QValueList >&); + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&); + AbstractMail *getWrapper(); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + const QStringList&subFolders(); + virtual void refreshFolders(bool force=false); + bool offline(); + +protected: + virtual void createNewFolder(); + IMAPaccount *account; + AbstractMail *wrapper; + QStringList currentFolders; +}; + +class IMAPfolderItem : public AccountViewItem +{ + +public: + IMAPfolderItem( const Opie::Core::OSmartPointer&folder, IMAPviewItem *parent , QListViewItem*after ); + IMAPfolderItem( const Opie::Core::OSmartPointer&folder, IMAPfolderItem *parent , QListViewItem*after, IMAPviewItem *master ); + virtual ~IMAPfolderItem(); + virtual void refresh(QValueList >&); + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + virtual const QString& Delemiter()const; +protected: + virtual void createNewFolder(); + virtual void deleteFolder(); + virtual void downloadMails(); + IMAPviewItem *imap; +}; + +class MHviewItem : public AccountViewItem +{ + friend class MHfolderItem; + +public: + MHviewItem( const QString&aMboxPath, AccountView *parent ); + virtual ~MHviewItem(); + virtual void refresh(QValueList >&target ); + virtual RECBODYP fetchBody( const Opie::Core::OSmartPointer &mail ); + AbstractMail *getWrapper(); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + QStringList subFolders(); + virtual void refresh(bool force=false); + +protected: + void downloadMails(); + virtual void createFolder(); + QString m_Path; + AbstractMail *wrapper; + QStringList currentFolders; +}; + +class MHfolderItem : public AccountViewItem +{ + +public: + MHfolderItem( const Opie::Core::OSmartPointer&folder, MHviewItem *parent , QListViewItem*after ); + MHfolderItem( const Opie::Core::OSmartPointer&folder, MHfolderItem *parent, QListViewItem*after, MHviewItem*master); + virtual ~MHfolderItem(); + virtual void refresh(QValueList >&); + virtual RECBODYP fetchBody(const Opie::Core::OSmartPointer&); + virtual QPopupMenu * getContextMenu(); + virtual void contextMenuSelected(int); + virtual const Opie::Core::OSmartPointer&getFolder()const; + virtual bool isDraftfolder(); + +protected: + void downloadMails(); + virtual void createFolder(); + virtual void deleteFolder(); + void initName(); + MHviewItem *mbox; +}; + +#endif diff --git a/kmicromail/accountview.cpp b/kmicromail/accountview.cpp new file mode 100644 index 0000000..0893733 --- a/dev/null +++ b/kmicromail/accountview.cpp @@ -0,0 +1,170 @@ + +#include "accountview.h" +#include "accountitem.h" +#include "selectstore.h" + +#include +#include +#include +#include + +/* OPIE */ +#include + +/* QT */ +#include +#include + +using namespace Opie::Core; +AccountView::AccountView( QWidget *parent, const char *name, WFlags flags ) + : QListView( parent, name, flags ) +{ + connect( this, SIGNAL( selectionChanged(QListViewItem*) ), + SLOT( refresh(QListViewItem*) ) ); + connect( this, SIGNAL( mouseButtonPressed(int,QListViewItem*,const QPoint&,int) ),this, + SLOT( slotHold(int,QListViewItem*,const QPoint&,int) ) ); + setSorting(0); +} + +AccountView::~AccountView() +{ + imapAccounts.clear(); + mhAccounts.clear(); +} + +void AccountView::slotContextMenu(int id) +{ + AccountViewItem *view = static_cast(currentItem()); + if (!view) return; + view->contextMenuSelected(id); +} + +void AccountView::slotHold(int button, QListViewItem * item,const QPoint&,int) +{ + if (button==1) {return;} + if (!item) return; + AccountViewItem *view = static_cast(item); + QPopupMenu*m = view->getContextMenu(); + if (!m) return; + connect(m,SIGNAL(activated(int)),this,SLOT(slotContextMenu(int))); + m->setFocus(); + m->exec( QPoint( QCursor::pos().x(), QCursor::pos().y()) ); + delete m; +} + +void AccountView::populate( QList list ) +{ + clear(); + + imapAccounts.clear(); + mhAccounts.clear(); + + mhAccounts.append(new MHviewItem(AbstractMail::defaultLocalfolder(),this)); + + Account *it; + for ( it = list.first(); it; it = list.next() ) + { + if ( it->getType() == MAILLIB::A_IMAP ) + { + IMAPaccount *imap = static_cast(it); + imapAccounts.append(new IMAPviewItem( imap, this )); + } + else if ( it->getType() == MAILLIB::A_POP3 ) + { + POP3account *pop3 = static_cast(it); + /* must not be hold 'cause it isn't required */ + (void) new POP3viewItem( pop3, this ); + } + else if ( it->getType() == MAILLIB::A_NNTP ) + { + NNTPaccount *nntp = static_cast(it); + /* must not be hold 'cause it isn't required */ + (void) new NNTPviewItem( nntp, this ); + } + } +} + +void AccountView::refresh(QListViewItem *item) +{ + if ( item ) + { + m_currentItem = item; + QValueList headerlist; + AccountViewItem *view = static_cast(item); + view->refresh(headerlist); + emit refreshMailview(headerlist); + } +} + +void AccountView::refreshCurrent() +{ + m_currentItem = currentItem(); + if ( !m_currentItem ) return; + QValueList headerlist; + AccountViewItem *view = static_cast(m_currentItem); + view->refresh(headerlist); + emit refreshMailview(headerlist); +} + +void AccountView::refreshAll() +{ +} + +RecBodyP AccountView::fetchBody(const RecMailP&aMail) +{ + QListViewItem*item = selectedItem (); + if (!item) return new RecBody(); + AccountViewItem *view = static_cast(item); + return view->fetchBody(aMail); +} + +void AccountView::setupFolderselect(Selectstore*sels) +{ + sels->showMaximized(); + QStringList sFolders; + unsigned int i = 0; + for (i=0; i < mhAccounts.count();++i) + { + mhAccounts[i]->refresh(false); + sFolders = mhAccounts[i]->subFolders(); + sels->addAccounts(mhAccounts[i]->getWrapper(),sFolders); + } + for (i=0; i < imapAccounts.count();++i) + { + if (imapAccounts[i]->offline()) + continue; + imapAccounts[i]->refreshFolders(false); + sels->addAccounts(imapAccounts[i]->getWrapper(),imapAccounts[i]->subFolders()); + } +} + +void AccountView::downloadMails(const FolderP&fromFolder,AbstractMail*fromWrapper) +{ + AbstractMail*targetMail = 0; + QString targetFolder = ""; + Selectstore sels; + setupFolderselect(&sels); + if (!sels.exec()) return; + targetMail = sels.currentMail(); + targetFolder = sels.currentFolder(); + if ( (fromWrapper==targetMail && fromFolder->getName()==targetFolder) || + targetFolder.isEmpty()) + { + return; + } + if (sels.newFolder() && !targetMail->createMbox(targetFolder)) + { + QMessageBox::critical(0,tr("Error creating new Folder"), + tr("
Error while creating
new folder - breaking.
")); + return; + } + fromWrapper->mvcpAllMails(fromFolder,targetFolder,targetMail,sels.moveMails()); + refreshCurrent(); +} + +bool AccountView::currentisDraft() +{ + AccountViewItem *view = static_cast(currentItem()); + if (!view) return false; + return view->isDraftfolder(); +} diff --git a/kmicromail/accountview.h b/kmicromail/accountview.h new file mode 100644 index 0000000..787b0b0 --- a/dev/null +++ b/kmicromail/accountview.h @@ -0,0 +1,45 @@ +#ifndef ACCOUNTVIEW_H +#define ACCOUNTVIEW_H + +#include +#include +#include +#include + +class Selectstore; +class Folder; +class AbstractMail; +class Account; +class IMAPviewItem; +class MHviewItem; + +class AccountView : public QListView +{ + Q_OBJECT + +public: + AccountView( QWidget *parent = 0, const char *name = 0, WFlags flags = 0 ); + virtual ~AccountView(); + virtual void populate( QList list ); + virtual RecBodyP fetchBody(const Opie::Core::OSmartPointer&aMail); + virtual void downloadMails(const Opie::Core::OSmartPointer&fromFolder,AbstractMail*fromWrapper); + virtual bool currentisDraft(); + +public slots: + virtual void refreshAll(); + virtual void refresh(QListViewItem *item); + virtual void refreshCurrent(); + virtual void slotHold(int, QListViewItem *,const QPoint&,int); + virtual void slotContextMenu(int id); + void setupFolderselect(Selectstore*sels); + +signals: + void refreshMailview(const QValueList& ); + +protected: + QListViewItem* m_currentItem; + QValueList imapAccounts; + QValueList mhAccounts; +}; + +#endif diff --git a/kmicromail/addresspicker.cpp b/kmicromail/addresspicker.cpp new file mode 100644 index 0000000..ec6da49 --- a/dev/null +++ b/kmicromail/addresspicker.cpp @@ -0,0 +1,116 @@ + +#include "composemail.h" + +/* OPIE */ +//#include +//#include +#include +#include + +/* QT */ +#include +#include +#include + +/* STD */ +#include + +AddressPicker::AddressPicker( QWidget *parent, const char *name, bool modal, WFlags flags ) + : AddressPickerUI( parent, name, modal, flags ) +{ + okButton->setIconSet( Resource::loadPixmap( "enter" ) ); + cancelButton->setIconSet( Resource::loadPixmap( "editdelete" ) ); + + connect(okButton, SIGNAL(clicked()), SLOT(accept())); + connect(cancelButton, SIGNAL(clicked()), SLOT(close())); + qDebug("AddressPicker::AddressPicker pending access KA/PI "); +#if 0 + Opie::OPimContactAccess::List::Iterator it; + + QString lineEmail, lineName, contactLine; + /* what name has to set here???? */ + Opie::OPimContactAccess m_contactdb("opiemail"); + + QStringList mails; + QString pre,suf; + Opie::OPimContactAccess::List m_list = m_contactdb.sorted( true, 0, 0, 0 ); + for ( it = m_list.begin(); it != m_list.end(); ++it ) + { + if ((*it).defaultEmail().length()!=0) + { + mails = (*it).emailList(); + if ((*it).fileAs().length()>0) + { + pre = "\""+(*it).firstName()+" "+(*it).lastName()+"\" <"; + suf = ">"; + } + else + { + pre = ""; + suf = ""; + } + QStringList::ConstIterator sit = mails.begin(); + for (;sit!=mails.end();++sit) + { + contactLine=pre+(*sit)+suf; + addressList->insertItem(contactLine); + } + } + } + if ( addressList->count() <= 0 ) + { +#if 0 + // makes this realy sense?? + addressList->insertItem( + tr( "There are no entries in the addressbook." ) ); +#endif + addressList->setEnabled( false ); + okButton->setEnabled( false ); + } + else + { + // addressList->sort(); + } +#endif +} + +void AddressPicker::accept() +{ + QListBoxItem *item = addressList->firstItem(); + QString names; + + while ( item ) + { + if ( item->selected() ) + names += item->text() + ", "; + item = item->next(); + } + names.replace( names.length() - 2, 2, "" ); + + if ( names.isEmpty() ) + { + QMessageBox::information(this, tr("Error"), tr("

You have to select" + " at least one address entry.

"), tr("Ok")); + return; + } + + selectedNames = names; + QDialog::accept(); +} + +QString AddressPicker::getNames() +{ + QString names = 0; + + AddressPicker picker(0, 0, true); + + picker.showMaximized(); + int ret = picker.exec(); + if ( QDialog::Accepted == ret ) + { + return picker.selectedNames; + } + + return 0; +} + diff --git a/kmicromail/addresspickerui.ui b/kmicromail/addresspickerui.ui new file mode 100644 index 0000000..2e37eac --- a/dev/null +++ b/kmicromail/addresspickerui.ui @@ -0,0 +1,86 @@ + +AddressPickerUI + + QDialog + + name + AddressPickerUI + + + geometry + + 0 + 0 + 282 + 320 + + + + caption + Address Picker + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 3 + + + QListBox + + name + addressList + + + selectionMode + Multi + + + + QPushButton + + name + okButton + + + minimumSize + + 10 + 0 + + + + text + Ok + + + + QPushButton + + name + cancelButton + + + minimumSize + + 10 + 0 + + + + text + Cancel + + + + + diff --git a/kmicromail/composemail.cpp b/kmicromail/composemail.cpp new file mode 100644 index 0000000..2c2e279 --- a/dev/null +++ b/kmicromail/composemail.cpp @@ -0,0 +1,357 @@ + +#include "composemail.h" + +#include +#include +#include +#include + +/* OPIE */ +//#include +//#include +#include +//#include +#include +#include +//#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +//using namespace Opie::Core; +//using namespace Opie::Ui; +ComposeMail::ComposeMail( Settings *s, QWidget *parent, const char *name, bool modal, WFlags flags ) + : ComposeMailUI( parent, name, modal, flags ) +{ + + settings = s; + m_replyid = ""; + KABC::Addressee con = KABC::StdAddressBook::self()->whoAmI( ); + QStringList mails = con.emails(); + QString defmail = con.preferredEmail(); + if ( mails.count() == 0) + QMessageBox::information( parentWidget(), tr( "Hint" ), + tr( "Please apply\n\"Set Who Am I\"\nin KA/Pi to get the from\nfield automatically filled out!" ), + tr( "Ok" ) ); + if (defmail.length()!=0) { + fromBox->insertItem(defmail); + } + QStringList::ConstIterator sit = mails.begin(); + for (;sit!=mails.end();++sit) { + if ( (*sit)==defmail) + continue; + fromBox->insertItem((*sit)); + } + senderNameEdit->setText(con.formattedName()); + Config cfg( "mail" ); + cfg.setGroup( "Compose" ); + checkBoxLater->setChecked( cfg.readBoolEntry( "sendLater", false ) ); + + attList->addColumn( tr( "Name" ) ); + attList->addColumn( tr( "Size" ) ); + + QList accounts = settings->getAccounts(); + + Account *it; + for ( it = accounts.first(); it; it = accounts.next() ) { + if ( it->getType()==MAILLIB::A_SMTP ) { + SMTPaccount *smtp = static_cast(it); + smtpAccountBox->insertItem( smtp->getAccountName() ); + smtpAccounts.append( smtp ); + } + } + if ( smtpAccounts.count() > 0 ) { + fillValues( smtpAccountBox->currentItem() ); + } else { + QMessageBox::information( parentWidget(), tr( "Problem" ), + tr( "Please create an SMTP account first.\nThe SMTP is needed for sending mail." ), + tr( "Ok" ) ); + return; + } + connect( smtpAccountBox, SIGNAL( activated(int) ), SLOT( fillValues(int) ) ); + connect( toButton, SIGNAL( clicked() ), SLOT( pickAddressTo() ) ); + connect( ccButton, SIGNAL( clicked() ), SLOT( pickAddressCC() ) ); + connect( bccButton, SIGNAL( clicked() ), SLOT( pickAddressBCC() ) ); + connect( replyButton, SIGNAL( clicked() ), SLOT( pickAddressReply() ) ); + connect( addButton, SIGNAL( clicked() ), SLOT( addAttachment() ) ); + connect( deleteButton, SIGNAL( clicked() ), SLOT( removeAttachment() ) ); + connect( SaveButton, SIGNAL( clicked() ), SLOT( saveAsDraft()) ); + mMail = 0; + warnAttach = true; +} +void ComposeMail::saveAsDraft() +{ + + Opie::Core::OSmartPointer mail= new Mail(); + mail->setMail(fromBox->currentText()); + mail->setTo( toLine->text() ); + mail->setName(senderNameEdit->text()); + mail->setCC( ccLine->text() ); + mail->setBCC( bccLine->text() ); + mail->setReply( replyLine->text() ); + mail->setSubject( subjectLine->text() ); + if (!m_replyid.isEmpty()) { + QStringList ids; + ids.append(m_replyid); + mail->setInreply(ids); + } + QString txt = message->text(); + if ( !sigMultiLine->text().isEmpty() ) { + txt.append( "\n--\n" ); + txt.append( sigMultiLine->text() ); + } + mail->setMessage( txt ); + + /* only use the default drafts folder name! */ + Storemail wrapper(AbstractMail::draftFolder()); + wrapper.storeMail(mail); + + AttachViewItem *it = (AttachViewItem *) attList->firstChild(); + /* attachments we will ignore! */ + if ( it != NULL ) { + if ( warnAttach ) + QMessageBox::warning(0,tr("Store message"), + tr("
Attachments will not be stored in \"Draft\" folder
")); + warnAttach = false; + } + setStatus( tr("Mail saved as draft!") ); +} +void ComposeMail::clearStatus() +{ + topLevelWidget()->setCaption( tr("Compose mail") ); +} +void ComposeMail::setStatus( QString status ) +{ + topLevelWidget()->setCaption( status ); + QTimer::singleShot ( 5000, this, SLOT( clearStatus() ) ) ; +} +void ComposeMail::pickAddress( QLineEdit *line ) +{ + //qDebug(" ComposeMail::pickAddress "); + QString names ;//= AddressPicker::getNames(); + + KABC::Addressee::List list = KABC::AddresseeDialog::getAddressees(this); + uint i=0; + for (i=0; i < list.count(); i++) { + if ( !list[i].preferredEmail().isEmpty()) { + names+= "\""+list[i].realName() +"\"<" +list[i].preferredEmail() +">"; + if ( i < list.count() -1 ) + names+= ","; + } + } + + + if ( line->text().isEmpty() ) { + line->setText( names ); + } else if ( !names.isEmpty() ) { + line->setText( line->text() + ", " + names ); + } +} + + +void ComposeMail::setTo( const QString & to ) +{ + toLine->setText( to ); +} + +void ComposeMail::setSubject( const QString & subject ) +{ + subjectLine->setText( subject ); +} + +void ComposeMail::setInReplyTo( const QString & messageId ) +{ + m_replyid = messageId; +} + +void ComposeMail::setMessage( const QString & text ) +{ + message->setText( text ); +} + + +void ComposeMail::pickAddressTo() +{ + pickAddress( toLine ); +} + +void ComposeMail::pickAddressCC() +{ + pickAddress( ccLine ); +} + +void ComposeMail::pickAddressBCC() +{ + pickAddress( bccLine ); +} + +void ComposeMail::pickAddressReply() +{ + pickAddress( replyLine ); +} + +void ComposeMail::fillValues( int ) +{ +#if 0 + SMTPaccount *smtp = smtpAccounts.at( current ); + ccLine->clear(); + if ( smtp->getUseCC() ) { + ccLine->setText( smtp->getCC() ); + } + bccLine->clear(); + if ( smtp->getUseBCC() ) { + bccLine->setText( smtp->getBCC() ); + } + replyLine->clear(); + if ( smtp->getUseReply() ) { + replyLine->setText( smtp->getReply() ); + } + sigMultiLine->setText( smtp->getSignature() ); +#endif +} + +void ComposeMail::slotAdjustColumns() +{ + int currPage = tabWidget->currentPageIndex(); + + tabWidget->showPage( attachTab ); + attList->setColumnWidth( 0, attList->visibleWidth() - 80 ); + attList->setColumnWidth( 1, 80 ); + + tabWidget->setCurrentPage( currPage ); +} + +void ComposeMail::addAttachment() +{ + QString lnk = KFileDialog::getOpenFileName( "", "Add Attachment", this ); + if ( !lnk.isEmpty() ) { + Attachment *att = new Attachment( lnk ); + (void) new AttachViewItem( attList, att ); + } +} + +void ComposeMail::removeAttachment() +{ + if ( !attList->currentItem() ) { + QMessageBox::information( this, tr( "Error" ), + tr( "

Please select a File.

" ), + tr( "Ok" ) ); + } else { + attList->takeItem( attList->currentItem() ); + } +} + +void ComposeMail::accept() +{ + if (! checkBoxLater->isChecked() ) { + int yesno = QMessageBox::warning(0,tr("Stop editing message"), + tr("Send this message?"), + tr("Yes"), + tr("Cancel")); + + if (yesno == 1) { + return; + } + } +#if 0 + odebug << "Sending Mail with " + << smtpAccounts.at( smtpAccountBox->currentItem() )->getAccountName() << oendl; +#endif + Opie::Core::OSmartPointer mail=new Mail; + + SMTPaccount *smtp = smtpAccounts.at( smtpAccountBox->currentItem() ); + mail->setMail(fromBox->currentText()); + + if ( !toLine->text().isEmpty() ) { + mail->setTo( toLine->text() ); + } else { + QMessageBox::warning(0,tr("Sending mail"), + tr("No Receiver spezified" ) ); + return; + } + + mail->setName(senderNameEdit->text()); + mail->setCC( ccLine->text() ); + mail->setBCC( bccLine->text() ); + mail->setReply( replyLine->text() ); + mail->setSubject( subjectLine->text() ); + if (!m_replyid.isEmpty()) { + QStringList ids; + ids.append(m_replyid); + mail->setInreply(ids); + } + QString txt = message->text(); + if ( !sigMultiLine->text().isEmpty() ) { + txt.append( "\n--\n" ); + txt.append( sigMultiLine->text() ); + } + mail->setMessage( txt ); + AttachViewItem *it = (AttachViewItem *) attList->firstChild(); + while ( it != NULL ) { + mail->addAttachment( it->getAttachment() ); + it = (AttachViewItem *) it->nextSibling(); + } + + SMTPwrapper wrapper( smtp ); + wrapper.sendMail( mail,checkBoxLater->isChecked() ); + + QDialog::accept(); +} + +void ComposeMail::reject() +{ + //qDebug("ComposeMail::reject() "); + int yesno = QMessageBox::warning(0,tr("Stop editing message"), + tr("Store message into drafts?"), + tr("Yes"), + tr("No")); + + //qDebug("button %d ", yesno); + if (yesno == 0) { + saveAsDraft(); + } + if (yesno == 2) { + qDebug("return "); + return; + } + QDialog::reject(); +} + +ComposeMail::~ComposeMail() +{ +} + +void ComposeMail::reEditMail(const RecMailP¤t) +{ + RecMailP data = current; + message->setText(data->Wrapper()->fetchBody(current)->Bodytext()); + subjectLine->setText( data->getSubject()); + toLine->setText(data->To().join(",")); + ccLine->setText(data->CC().join(",")); + bccLine->setText(data->Bcc().join(",")); + replyLine->setText(data->Replyto()); +} + +AttachViewItem::AttachViewItem( QListView *parent, Attachment *att ) + : QListViewItem( parent ) +{ + attachment = att; + if ( !attachment->getPixmap().isNull() ) + setPixmap( 0,attachment->getPixmap() ); + setText( 0, att->getName().isEmpty() ? att->getFileName() : att->getName() ); + setText( 1, QString::number( att->getSize() ) ); +} + diff --git a/kmicromail/composemail.h b/kmicromail/composemail.h new file mode 100644 index 0000000..876b597 --- a/dev/null +++ b/kmicromail/composemail.h @@ -0,0 +1,86 @@ +#ifndef COMPOSEMAIL_H +#define COMPOSEMAIL_H + +#include +#include + +#include "composemailui.h" +//#include "addresspickerui.h" +#include +#include + +class RecMail; + +#include +#if 0 +class AddressPicker : public AddressPickerUI +{ + //Q_OBJECT + +public: + AddressPicker( QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags flags = 0 ); + static QString getNames(); + +protected: + QString selectedNames; + void accept(); + +}; +#endif +class RecMail; + +class ComposeMail : public ComposeMailUI +{ + Q_OBJECT + +public: + ComposeMail( Settings *s, QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags flags = 0 ); + virtual ~ComposeMail(); + + void reEditMail(const Opie::Core::OSmartPointer¤t); + +public slots: + void slotAdjustColumns(); + + void setTo( const QString & to ); + void setSubject( const QString & subject ); + void setInReplyTo( const QString & messageId ); + void setMessage( const QString & text ); + +protected slots: + void accept(); + void reject(); + +private slots: + void fillValues( int current ); + void pickAddress( QLineEdit *line ); + void pickAddressTo(); + void pickAddressCC(); + void pickAddressBCC(); + void pickAddressReply(); + void saveAsDraft(); + void addAttachment(); + void removeAttachment(); + void clearStatus(); + void setStatus( QString ); + +protected: + Opie::Core::OSmartPointer mMail; + Settings *settings; + QList smtpAccounts; + QString m_replyid; + bool warnAttach; +}; + +class AttachViewItem : public QListViewItem +{ +public: + AttachViewItem( QListView *parent, Attachment *att ); + Attachment *getAttachment() { return attachment; } + +private: + Attachment *attachment; + +}; + +#endif diff --git a/kmicromail/composemailui.ui b/kmicromail/composemailui.ui new file mode 100644 index 0000000..d566985 --- a/dev/null +++ b/kmicromail/composemailui.ui @@ -0,0 +1,472 @@ + +ComposeMailUI + + QDialog + + name + ComposeMailUI + + + geometry + + 0 + 0 + 276 + 262 + + + + caption + Compose Message + + + layoutMargin + + + layoutSpacing + + + + margin + 2 + + + spacing + 1 + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + layoutSpacing + + + QWidget + + name + mailTab + + + title + Mail + + + + margin + 1 + + + spacing + 1 + + + QLayoutWidget + + name + Layout10 + + + layoutSpacing + + + + margin + 0 + + + spacing + 1 + + + QLayoutWidget + + name + Layout9 + + + layoutSpacing + + + + margin + 0 + + + spacing + 3 + + + QComboBox + + name + fromBox + + + sizePolicy + + 3 + 0 + + + + editable + true + + + duplicatesEnabled + false + + + + QLineEdit + + name + senderNameEdit + + + sizePolicy + + 0 + 0 + + + + minimumSize + + 70 + 0 + + + + maximumSize + + 180 + 32767 + + + + + + + QLineEdit + + name + subjectLine + + + sizePolicy + + 3 + 0 + + + + + QLineEdit + + name + toLine + + + sizePolicy + + 3 + 0 + + + + + QLabel + + name + subjectLabel + + + text + Subject + + + + QLabel + + name + fromLabel + + + text + From + + + + QPushButton + + name + toButton + + + text + To + + + + + + QMultiLineEdit + + name + message + + + + + + QWidget + + name + optionsTab + + + title + Options + + + + margin + 4 + + + spacing + 3 + + + QPushButton + + name + replyButton + + + text + Reply-To + + + + QPushButton + + name + bccButton + + + text + BCC + + + + QLineEdit + + name + ccLine + + + + QLineEdit + + name + bccLine + + + + QLineEdit + + name + replyLine + + + + QMultiLineEdit + + name + sigMultiLine + + + + QLabel + + name + sigLabel + + + text + Signature + + + + + name + Spacer3 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + ccButton + + + text + CC + + + + + + QWidget + + name + attachTab + + + title + Attachment + + + + margin + 4 + + + spacing + 3 + + + QListView + + name + attList + + + selectionMode + Single + + + allColumnsShowFocus + true + + + showSortIndicator + true + + + + QPushButton + + name + deleteButton + + + text + Delete File + + + + QPushButton + + name + addButton + + + text + Add File + + + + + + + QCheckBox + + name + checkBoxLater + + + text + send later + + + + QLabel + + name + accountLabel + + + text + use: + + + + QComboBox + + name + smtpAccountBox + + + sizePolicy + + 3 + 0 + + + + + QPushButton + + name + SaveButton + + + text + Save + + + + + + fromBox + toButton + toLine + subjectLine + message + tabWidget + ccButton + ccLine + bccButton + bccLine + replyButton + replyLine + sigMultiLine + attList + addButton + deleteButton + + diff --git a/kmicromail/composemailui.ui.bup b/kmicromail/composemailui.ui.bup new file mode 100644 index 0000000..23338a5 --- a/dev/null +++ b/kmicromail/composemailui.ui.bup @@ -0,0 +1,481 @@ + +ComposeMailUI + + QDialog + + name + ComposeMailUI + + + geometry + + 0 + 0 + 252 + 360 + + + + caption + Compose Message + + + layoutMargin + + + layoutSpacing + + + + margin + 1 + + + spacing + 1 + + + QLayoutWidget + + name + Layout4 + + + layoutSpacing + + + + margin + 0 + + + spacing + 3 + + + QCheckBox + + name + checkBoxLater + + + text + send later + + + + QLabel + + name + accountLabel + + + text + use: + + + + QComboBox + + name + smtpAccountBox + + + sizePolicy + + 3 + 0 + + + + + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + layoutSpacing + + + QWidget + + name + mailTab + + + title + Mail + + + + margin + 1 + + + spacing + 1 + + + QLayoutWidget + + name + Layout10 + + + layoutSpacing + + + + margin + 0 + + + spacing + 1 + + + QLayoutWidget + + name + Layout9 + + + layoutSpacing + + + + margin + 0 + + + spacing + 3 + + + QComboBox + + name + fromBox + + + sizePolicy + + 3 + 0 + + + + editable + true + + + duplicatesEnabled + false + + + + QLineEdit + + name + senderNameEdit + + + sizePolicy + + 0 + 0 + + + + minimumSize + + 70 + 0 + + + + maximumSize + + 180 + 32767 + + + + + + + QLineEdit + + name + subjectLine + + + sizePolicy + + 3 + 0 + + + + + QLineEdit + + name + toLine + + + sizePolicy + + 3 + 0 + + + + + QLabel + + name + subjectLabel + + + text + Subject + + + + QLabel + + name + fromLabel + + + text + From + + + + QPushButton + + name + toButton + + + text + To + + + + + + QMultiLineEdit + + name + message + + + + + + QWidget + + name + optionsTab + + + title + Options + + + + margin + 4 + + + spacing + 3 + + + QPushButton + + name + replyButton + + + text + Reply-To + + + + QPushButton + + name + bccButton + + + text + BCC + + + + QLineEdit + + name + ccLine + + + + QLineEdit + + name + bccLine + + + + QLineEdit + + name + replyLine + + + + QMultiLineEdit + + name + sigMultiLine + + + + QLabel + + name + sigLabel + + + text + Signature + + + + + name + Spacer3 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + ccButton + + + text + CC + + + + + + QWidget + + name + attachTab + + + title + Attachment + + + + margin + 4 + + + spacing + 3 + + + QListView + + name + attList + + + selectionMode + Single + + + allColumnsShowFocus + true + + + showSortIndicator + true + + + + QPushButton + + name + deleteButton + + + text + Delete File + + + + QPushButton + + name + addButton + + + text + Add File + + + + + + + + + fromBox + toButton + toLine + subjectLine + message + tabWidget + ccButton + ccLine + bccButton + bccLine + replyButton + replyLine + sigMultiLine + attList + addButton + deleteButton + + diff --git a/kmicromail/config.in b/kmicromail/config.in new file mode 100644 index 0000000..f7fce91 --- a/dev/null +++ b/kmicromail/config.in @@ -0,0 +1,10 @@ +source noncore/net/mail/libmailwrapper/config.in + +config MAIL3 + boolean "opie-mail3 (a mail client)" + default "y" + depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2PIM && LIBOPIE2MM && LIBMAILWRAPPER + comment "opie-mail3 needs a libqpe, libopie2core, libopie2pim and the libmailwrapper" + depends ! ( ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2PIM && LIBOPIE2MM && LIBMAILWRAPPER ) + +source noncore/net/mail/taskbarapplet/config.in diff --git a/kmicromail/defines.h b/kmicromail/defines.h new file mode 100644 index 0000000..f2d7265 --- a/dev/null +++ b/kmicromail/defines.h @@ -0,0 +1,36 @@ +#ifndef DEFINE_CONSTANTS_H +#define DEFINE_CONSTANTS_H + + + +#define USER_AGENT "KMicroMail v1.92" + +#define PIXMAP_IMAPFOLDER SmallIcon ( "imapfolder" ) +#define PIXMAP_POP3FOLDER SmallIcon ( "pop3folder" ) +#define PIXMAP_INBOXFOLDER SmallIcon ( "inbox" ) +#define PIXMAP_MBOXFOLDER SmallIcon ( "mboxfolder" ) +#define PIXMAP_OUTBOXFOLDER SmallIcon ( "outbox" ) +#define PIXMAP_LOCALFOLDER SmallIcon ( "localfolder" ) +#define PIXMAP_OFFLINE SmallIcon ( "notconnected" ) + +#define IMAP_PORT "143" +#define IMAP_SSL_PORT "993" +#define SMTP_PORT "25" +#define SMTP_SSL_PORT "465" +#define POP3_PORT "110" +#define POP3_SSL_PORT "995" +#define NNTP_PORT "119" +#define NNTP_SSL_PORT "563" + +/* used for decoding imapfoldername */ +#define UNDEFINED 64 +#define MAXLINE 76 +#define UTF16MASK 0x03FFUL +#define UTF16SHIFT 10 +#define UTF16BASE 0x10000UL +#define UTF16HIGHSTART 0xD800UL +#define UTF16HIGHEND 0xDBFFUL +#define UTF16LOSTART 0xDC00UL +#define UTF16LOEND 0xDFFFUL + +#endif diff --git a/kmicromail/editaccounts.cpp b/kmicromail/editaccounts.cpp new file mode 100644 index 0000000..d272c3b --- a/dev/null +++ b/kmicromail/editaccounts.cpp @@ -0,0 +1,594 @@ + +#include "defines.h" +#include "editaccounts.h" +#include "kapplication.h" +/* OPIE */ +#include + +/* QT */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace Opie::Core; + +AccountListItem::AccountListItem( QListView *parent, Account *a) + : QListViewItem( parent ) +{ + account = a; + setText( 0, account->getAccountName() ); + QString ttext = ""; + switch (account->getType()) { + case MAILLIB::A_NNTP: + ttext="NNTP"; + break; + case MAILLIB::A_POP3: + ttext = "POP3"; + break; + case MAILLIB::A_IMAP: + ttext = "IMAP"; + break; + case MAILLIB::A_SMTP: + ttext = "SMTP"; + break; + default: + ttext = "UNKNOWN"; + break; + } + setText( 1, ttext); +} + +EditAccounts::EditAccounts( Settings *s, QWidget *parent, const char *name, bool modal, WFlags flags ) + : EditAccountsUI( parent, name, modal, flags ) +{ + settings = s; + + mailList->addColumn( tr( "Account" ) ); + mailList->addColumn( tr( "Type" ) ); + + newsList->addColumn( tr( "Account" ) ); + + connect( newMail, SIGNAL( clicked() ), SLOT( slotNewMail() ) ); + connect( editMail, SIGNAL( clicked() ), SLOT( slotEditMail() ) ); + connect( deleteMail, SIGNAL( clicked() ), SLOT( slotDeleteMail() ) ); + connect( newNews, SIGNAL( clicked() ), SLOT( slotNewNews() ) ); + connect( editNews, SIGNAL( clicked() ), SLOT( slotEditNews() ) ); + connect( deleteNews, SIGNAL( clicked() ), SLOT( slotDeleteNews() ) ); + + slotFillLists(); +} + +void EditAccounts::slotFillLists() +{ + mailList->clear(); + newsList->clear(); + + QList accounts = settings->getAccounts(); + Account *it; + for ( it = accounts.first(); it; it = accounts.next() ) + { + if ( it->getType()==MAILLIB::A_NNTP ) + { + (void) new AccountListItem( newsList, it ); + } + else + { + (void) new AccountListItem( mailList, it ); + } + } +} + +void EditAccounts::slotNewMail() +{ + QString *selection = new QString(); + SelectMailType selType( selection, this, 0, true ); + selType.show(); + if ( QDialog::Accepted == selType.exec() ) + { + slotNewAccount( *selection ); + } +} + +void EditAccounts::slotNewAccount( const QString &type ) +{ + if ( type.compare( "IMAP" ) == 0 ) + { + IMAPaccount *account = new IMAPaccount(); + IMAPconfig imap( account, this, 0, true ); + imap.showMaximized(); + if ( QDialog::Accepted == imap.exec() ) + { + settings->addAccount( account ); + account->save(); + slotFillLists(); + } + else + { + account->remove(); + } + } + else if ( type.compare( "POP3" ) == 0 ) + { + POP3account *account = new POP3account(); + POP3config pop3( account, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &pop3 ) ) + { + settings->addAccount( account ); + account->save(); + slotFillLists(); + } + else + { + account->remove(); + } + } + else if ( type.compare( "SMTP" ) == 0 ) + { + SMTPaccount *account = new SMTPaccount(); + SMTPconfig smtp( account, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &smtp ) ) + { + settings->addAccount( account ); + account->save(); + slotFillLists(); + + } + else + { + account->remove(); + } + } + else if ( type.compare( "NNTP" ) == 0 ) + { + NNTPaccount *account = new NNTPaccount(); + NNTPconfig nntp( account, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &nntp ) ) + { + settings->addAccount( account ); + account->save(); + slotFillLists(); + } + else + { + account->remove(); + } + } +} + +void EditAccounts::slotEditAccount( Account *account ) +{ + if ( account->getType() == MAILLIB::A_IMAP ) + { + IMAPaccount *imapAcc = static_cast(account); + IMAPconfig imap( imapAcc, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &imap ) ) + { + slotFillLists(); + } + } + else if ( account->getType()==MAILLIB::A_POP3 ) + { + POP3account *pop3Acc = static_cast(account); + POP3config pop3( pop3Acc, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &pop3 ) ) + { + slotFillLists(); + } + } + else if ( account->getType()==MAILLIB::A_SMTP ) + { + SMTPaccount *smtpAcc = static_cast(account); + SMTPconfig smtp( smtpAcc, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &smtp ) ) + { + slotFillLists(); + } + } + else if ( account->getType()==MAILLIB::A_NNTP) + { + NNTPaccount *nntpAcc = static_cast(account); + NNTPconfig nntp( nntpAcc, this, 0, true, WStyle_ContextHelp ); + if ( QDialog::Accepted == KApplication::execDialog( &nntp ) ) + { + slotFillLists(); + } + } +} + +void EditAccounts::slotDeleteAccount( Account *account ) +{ + if ( QMessageBox::information( this, tr( "Question" ), + tr( "

Do you really want to delete the selected Account?

" ), + tr( "Yes" ), tr( "No" ) ) == 0 ) + { + settings->delAccount( account ); + slotFillLists(); + } +} + +void EditAccounts::slotEditMail() +{ + if ( !mailList->currentItem() ) + { + QMessageBox::information( this, tr( "Error" ), + tr( "

Please select an account.

" ), + tr( "Ok" ) ); + return; + } + + Account *a = ((AccountListItem *) mailList->currentItem())->getAccount(); + slotEditAccount( a ); +} + +void EditAccounts::slotDeleteMail() +{ + if ( !mailList->currentItem() ) + { + QMessageBox::information( this, tr( "Error" ), + tr( "

Please select an account.

" ), + tr( "Ok" ) ); + return; + } + + Account *a = ((AccountListItem *) mailList->currentItem())->getAccount(); + slotDeleteAccount( a ); +} + +void EditAccounts::slotNewNews() +{ + slotNewAccount( "NNTP" ); +} + +void EditAccounts::slotEditNews() +{ + if ( !newsList->currentItem() ) + { + QMessageBox::information( this, tr( "Error" ), + tr( "

Please select an account.

" ), + tr( "Ok" ) ); + return; + } + + Account *a = ((AccountListItem *) newsList->currentItem())->getAccount(); + slotEditAccount( a ); +} + +void EditAccounts::slotDeleteNews() +{ + if ( !newsList->currentItem() ) + { + QMessageBox::information( this, tr( "Error" ), + tr( "

Please select an account.

" ), + tr( "Ok" ) ); + return; + } + + Account *a = ((AccountListItem *) newsList->currentItem())->getAccount(); + slotDeleteAccount( a ); +} + +void EditAccounts::slotAdjustColumns() +{ + int currPage = configTab->currentPageIndex(); + + configTab->showPage( mailTab ); + mailList->setColumnWidth( 0, mailList->visibleWidth() - 50 ); + mailList->setColumnWidth( 1, 50 ); + + configTab->showPage( newsTab ); + newsList->setColumnWidth( 0, newsList->visibleWidth() ); + + configTab->setCurrentPage( currPage ); +} + +void EditAccounts::accept() +{ + settings->saveAccounts(); + + QDialog::accept(); +} + +/** + * SelectMailType + */ + +SelectMailType::SelectMailType( QString *selection, QWidget *parent, const char *name, bool modal, WFlags flags ) + : SelectMailTypeUI( parent, name, modal, flags ) +{ + selected = selection; + selected->replace( 0, selected->length(), typeBox->currentText() ); + connect( typeBox, SIGNAL( activated(const QString&) ), SLOT( slotSelection(const QString&) ) ); +} + +void SelectMailType::slotSelection( const QString &sel ) +{ + selected->replace( 0, selected->length(), sel ); +} + +/** + * IMAPconfig + */ + +IMAPconfig::IMAPconfig( IMAPaccount *account, QWidget *parent, const char *name, bool modal, WFlags flags ) + : IMAPconfigUI( parent, name, modal, flags ) +{ + data = account; + + fillValues(); + + connect( ComboBox1, SIGNAL( activated(int) ), SLOT( slotConnectionToggle(int) ) ); + ComboBox1->insertItem( "Only if available", 0 ); + ComboBox1->insertItem( "Always, Negotiated", 1 ); + ComboBox1->insertItem( "Connect on secure port", 2 ); + ComboBox1->insertItem( "Run command instead", 3 ); + CommandEdit->hide(); + ComboBox1->setCurrentItem( data->ConnectionType() ); +} + +void IMAPconfig::slotConnectionToggle( int index ) +{ + if ( index == 2 ) + { + portLine->setText( IMAP_SSL_PORT ); + } + else if ( index == 3 ) + { + portLine->setText( IMAP_PORT ); + CommandEdit->show(); + } + else + { + portLine->setText( IMAP_PORT ); + } +} + +void IMAPconfig::fillValues() +{ + accountLine->setText( data->getAccountName() ); + serverLine->setText( data->getServer() ); + portLine->setText( data->getPort() ); + ComboBox1->setCurrentItem( data->ConnectionType() ); + userLine->setText( data->getUser() ); + passLine->setText( data->getPassword() ); + prefixLine->setText(data->getPrefix()); +} + +void IMAPconfig::accept() +{ + data->setAccountName( accountLine->text() ); + data->setServer( serverLine->text() ); + data->setPort( portLine->text() ); + data->setConnectionType( ComboBox1->currentItem() ); + data->setUser( userLine->text() ); + data->setPassword( passLine->text() ); + data->setPrefix(prefixLine->text()); + + QDialog::accept(); +} + +/** + * POP3config + */ + +POP3config::POP3config( POP3account *account, QWidget *parent, const char *name, bool modal, WFlags flags ) + : POP3configUI( parent, name, modal, flags ) +{ + data = account; + fillValues(); + + connect( ComboBox1, SIGNAL( activated(int) ), SLOT( slotConnectionToggle(int) ) ); + ComboBox1->insertItem( "Only if available", 0 ); + ComboBox1->insertItem( "Always, Negotiated", 1 ); + ComboBox1->insertItem( "Connect on secure port", 2 ); + ComboBox1->insertItem( "Run command instead", 3 ); + CommandEdit->hide(); + ComboBox1->setCurrentItem( data->ConnectionType() ); +} + +void POP3config::slotConnectionToggle( int index ) +{ + // 2 is ssl connection + if ( index == 2 ) + { + portLine->setText( POP3_SSL_PORT ); + } + else if ( index == 3 ) + { + portLine->setText( POP3_PORT ); + CommandEdit->show(); + } + else + { + portLine->setText( POP3_PORT ); + } +} + +void POP3config::fillValues() +{ + accountLine->setText( data->getAccountName() ); + serverLine->setText( data->getServer() ); + portLine->setText( data->getPort() ); + ComboBox1->setCurrentItem( data->ConnectionType() ); + userLine->setText( data->getUser() ); + passLine->setText( data->getPassword() ); +} + +void POP3config::accept() +{ + data->setAccountName( accountLine->text() ); + data->setServer( serverLine->text() ); + data->setPort( portLine->text() ); + data->setConnectionType( ComboBox1->currentItem() ); + data->setUser( userLine->text() ); + data->setPassword( passLine->text() ); + + QDialog::accept(); +} + +/** + * SMTPconfig + */ + +SMTPconfig::SMTPconfig( SMTPaccount *account, QWidget *parent, const char *name, bool modal, WFlags flags ) + : SMTPconfigUI( parent, name, modal, flags ) +{ + data = account; + + connect( loginBox, SIGNAL( toggled(bool) ), userLine, SLOT( setEnabled(bool) ) ); + connect( loginBox, SIGNAL( toggled(bool) ), passLine, SLOT( setEnabled(bool) ) ); + + fillValues(); + + connect( ComboBox1, SIGNAL( activated(int) ), SLOT( slotConnectionToggle(int) ) ); + ComboBox1->insertItem( "Only if available", 0 ); + ComboBox1->insertItem( "Always, Negotiated", 1 ); + ComboBox1->insertItem( "Connect on secure port", 2 ); + ComboBox1->insertItem( "Run command instead", 3 ); + CommandEdit->hide(); + ComboBox1->setCurrentItem( data->ConnectionType() ); +} + +void SMTPconfig::slotConnectionToggle( int index ) +{ + // 2 is ssl connection + if ( index == 2 ) + { + portLine->setText( SMTP_SSL_PORT ); + } + else if ( index == 3 ) + { + portLine->setText( SMTP_PORT ); + CommandEdit->show(); + } + else + { + portLine->setText( SMTP_PORT ); + } +} + +void SMTPconfig::fillValues() +{ + accountLine->setText( data->getAccountName() ); + serverLine->setText( data->getServer() ); + portLine->setText( data->getPort() ); + ComboBox1->setCurrentItem( data->ConnectionType() ); + loginBox->setChecked( data->getLogin() ); + userLine->setText( data->getUser() ); + passLine->setText( data->getPassword() ); +} + +void SMTPconfig::accept() +{ + data->setAccountName( accountLine->text() ); + data->setServer( serverLine->text() ); + data->setPort( portLine->text() ); + data->setConnectionType( ComboBox1->currentItem() ); + data->setLogin( loginBox->isChecked() ); + data->setUser( userLine->text() ); + data->setPassword( passLine->text() ); + + QDialog::accept(); +} + +/** + * NNTPconfig + */ + +NNTPconfig::NNTPconfig( NNTPaccount *account, QWidget *parent, const char *name, bool modal, WFlags flags ) + : NNTPconfigUI( parent, name, modal, flags ) +{ + data = account; + + connect( loginBox, SIGNAL( toggled(bool) ), userLine, SLOT( setEnabled(bool) ) ); + connect( loginBox, SIGNAL( toggled(bool) ), passLine, SLOT( setEnabled(bool) ) ); + connect( GetNGButton, SIGNAL( clicked() ), this, SLOT( slotGetNG() ) ); + fillValues(); + + connect( sslBox, SIGNAL( toggled(bool) ), SLOT( slotSSL(bool) ) ); +} + +void NNTPconfig::slotGetNG() { + save(); + data->save(); + NNTPwrapper* tmp = new NNTPwrapper( data ); + QStringList list = tmp->listAllNewsgroups(); + + ListViewGroups->clear(); + + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + QCheckListItem *item; + item = new QCheckListItem( ListViewGroups, (*it), QCheckListItem::CheckBox ); + if ( subscribedGroups.contains( (*it) ) >= 1 ) { + item->setOn( true ); + } + } +} + +void NNTPconfig::slotSSL( bool enabled ) +{ + if ( enabled ) + { + portLine->setText( NNTP_SSL_PORT ); + } + else + { + portLine->setText( NNTP_PORT ); + } +} + +void NNTPconfig::fillValues() +{ + accountLine->setText( data->getAccountName() ); + serverLine->setText( data->getServer() ); + portLine->setText( data->getPort() ); + sslBox->setChecked( data->getSSL() ); + loginBox->setChecked( data->getLogin() ); + userLine->setText( data->getUser() ); + passLine->setText( data->getPassword() ); + subscribedGroups = data->getGroups(); + /* don't forget that - you will overwrite values if user clicks cancel! */ + for ( QStringList::Iterator it = subscribedGroups.begin(); it != subscribedGroups.end(); ++it ) { + QCheckListItem *item; + item = new QCheckListItem( ListViewGroups, (*it), QCheckListItem::CheckBox ); + item->setOn( true ); + } +} + +void NNTPconfig::save() +{ + data->setAccountName( accountLine->text() ); + data->setServer( serverLine->text() ); + data->setPort( portLine->text() ); + data->setSSL( sslBox->isChecked() ); + data->setLogin( loginBox->isChecked() ); + data->setUser( userLine->text() ); + data->setPassword( passLine->text() ); + + QListViewItemIterator list_it( ListViewGroups ); + + QStringList groupList; + for ( ; list_it.current(); ++list_it ) { + + if ( ( (QCheckListItem*)list_it.current() )->isOn() ) { + groupList.append( list_it.current()->text(0) ); + } + + } + data->setGroups( groupList ); +} + +void NNTPconfig::accept() +{ + save(); + QDialog::accept(); +} + diff --git a/kmicromail/editaccounts.h b/kmicromail/editaccounts.h new file mode 100644 index 0000000..a9eb19f --- a/dev/null +++ b/kmicromail/editaccounts.h @@ -0,0 +1,153 @@ +#ifndef EDITACCOUNTS_H +#define EDITACCOUNTS_H + +#include +#include + +#include "editaccountsui.h" +#include "selectmailtypeui.h" +#include "imapconfigui.h" +#include "pop3configui.h" +#include "smtpconfigui.h" +#include "nntpconfigui.h" + +#include +#include + + +class AccountListItem : public QListViewItem +{ + +public: + AccountListItem( QListView *parent, Account *a); + Account *getAccount() { return account; } + +private: + Account *account; + +}; + +class EditAccounts : public EditAccountsUI +{ + Q_OBJECT + +public: + EditAccounts( Settings *s, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +public slots: + void slotNewAccount( const QString &type ); + void slotEditAccount( Account *account ); + void slotDeleteAccount( Account * account ); + void slotAdjustColumns(); + +protected slots: + void slotFillLists(); + void slotNewMail(); + void slotEditMail(); + void slotDeleteMail(); + void slotNewNews(); + void slotEditNews(); + void slotDeleteNews(); + void accept(); + +private: + Settings *settings; + +}; + +class SelectMailType : public SelectMailTypeUI +{ + Q_OBJECT + +public: + SelectMailType( QString *selection = 0, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +private slots: + void slotSelection( const QString &sel ); + +private: + QString *selected; + +}; + +class IMAPconfig : public IMAPconfigUI +{ + Q_OBJECT + +public: + IMAPconfig( IMAPaccount *account, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +public slots: + void fillValues(); + +protected slots: + void slotConnectionToggle( int index ); + void accept(); + +private: + IMAPaccount *data; + +}; + +class POP3config : public POP3configUI +{ + Q_OBJECT + +public: + POP3config( POP3account *account, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +public slots: + void fillValues(); + +protected slots: + void slotConnectionToggle( int index ); + void accept(); + +private: + POP3account *data; + +}; + +class SMTPconfig : public SMTPconfigUI +{ + Q_OBJECT + +public: + SMTPconfig( SMTPaccount *account, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +public slots: + void fillValues(); + +protected slots: + void slotConnectionToggle( int index ); + void accept(); + +private: + SMTPaccount *data; + +}; + +class NNTPconfig : public NNTPconfigUI +{ + Q_OBJECT + +public: + NNTPconfig( NNTPaccount *account, QWidget *parent = 0, const char *name = 0, bool modal = 0, WFlags flags = 0 ); + +public slots: + void fillValues(); + +protected slots: + void slotSSL( bool enabled ); + void accept(); + void slotGetNG(); + +private: + QStringList subscribedGroups; + void save(); + NNTPaccount *data; + clist* list; + +}; + +#endif diff --git a/kmicromail/editaccountsui.ui b/kmicromail/editaccountsui.ui new file mode 100644 index 0000000..d86f145 --- a/dev/null +++ b/kmicromail/editaccountsui.ui @@ -0,0 +1,223 @@ + +EditAccountsUI + + QDialog + + name + EditAccountsUI + + + geometry + + 0 + 0 + 260 + 320 + + + + caption + Configure Accounts + + + layoutMargin + + + layoutSpacing + + + + margin + 0 + + + spacing + 0 + + + QTabWidget + + name + configTab + + + layoutMargin + + + layoutSpacing + + + QWidget + + name + mailTab + + + title + Mail + + + + margin + 4 + + + spacing + 3 + + + QPushButton + + name + deleteMail + + + text + Delete + + + + QPushButton + + name + newMail + + + text + New + + + + QListView + + name + mailList + + + sizePolicy + + 7 + 7 + + + + resizePolicy + Manual + + + allColumnsShowFocus + true + + + showSortIndicator + true + + + toolTip + Name of the Account + + + + QPushButton + + name + editMail + + + text + Edit + + + + + + QWidget + + name + newsTab + + + title + News + + + + margin + 4 + + + spacing + 3 + + + QPushButton + + name + deleteNews + + + sizePolicy + + 1 + 0 + + + + text + Delete + + + + QPushButton + + name + editNews + + + text + Edit + + + + QListView + + name + newsList + + + allColumnsShowFocus + true + + + showSortIndicator + true + + + + QPushButton + + name + newNews + + + text + New + + + + + + + + + mailList + newMail + editMail + deleteMail + configTab + newsList + newNews + editNews + deleteNews + + diff --git a/kmicromail/imapconfigui.ui b/kmicromail/imapconfigui.ui new file mode 100644 index 0000000..a96c1a2 --- a/dev/null +++ b/kmicromail/imapconfigui.ui @@ -0,0 +1,259 @@ + +IMAPconfigUI + + QDialog + + name + IMAPconfigUI + + + geometry + + 0 + 0 + 425 + 428 + + + + caption + Configure IMAP + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QLineEdit + + name + serverLine + + + + QLabel + + name + portLabel + + + text + Port + + + + QLabel + + name + serverLabel + + + text + Server + + + + QLineEdit + + name + portLine + + + + QLineEdit + + name + accountLine + + + toolTip + Name of the Account + + + + QLabel + + name + accountLabel + + + text + Account + + + + Line + + name + line1 + + + orientation + Horizontal + + + + + name + spacer + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLineEdit + + name + userLine + + + + QLineEdit + + name + passLine + + + echoMode + Password + + + + QLabel + + name + prefixLabel + + + text + Prefix + + + + QLineEdit + + name + prefixLine + + + + QLabel + + name + userLabel + + + text + User + + + + Line + + name + line2 + + + enabled + true + + + caption + + + + orientation + Horizontal + + + layoutMargin + + + layoutSpacing + + + + Line + + name + Line3 + + + orientation + Horizontal + + + + QLabel + + name + passLabel + + + text + Password + + + + QLineEdit + + name + CommandEdit + + + text + ssh $SERVER exec + + + + QComboBox + + name + ComboBox1 + + + + QLabel + + name + TextLabel1 + + + text + Use secure sockets: + + + + + + accountLine + serverLine + portLine + userLine + passLine + + diff --git a/kmicromail/kmicromail.desktop b/kmicromail/kmicromail.desktop new file mode 100644 index 0000000..791ad4f --- a/dev/null +++ b/kmicromail/kmicromail.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +CanFastload=1 +Comment=KM/PI +Comment[de]=KM/PI +Display=640x480/144dpi,480x640/144dpi +Exec=kmpi +GenericName= +GenericName[de]= +Icon=kdepim/kmicromail/kmicromail +MimeType= +Name=KM/Pi +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application diff --git a/kmicromail/kmicromailE.pro b/kmicromail/kmicromailE.pro new file mode 100644 index 0000000..8f2438c --- a/dev/null +++ b/kmicromail/kmicromailE.pro @@ -0,0 +1,65 @@ +CONFIG += qt warn_on +TEMPLATE = app +HEADERS = defines.h \ + editaccounts.h \ + composemail.h \ + accountview.h \ + accountitem.h \ + mainwindow.h \ + viewmail.h \ + viewmailbase.h \ + opiemail.h \ + mailistviewitem.h \ + settingsdialog.h \ + statuswidget.h \ + newmaildir.h \ + selectstore.h \ + selectsmtp.h \ + nntpgroups.h \ + nntpgroupsdlg.h + +SOURCES = main.cpp \ + opiemail.cpp \ + mainwindow.cpp \ + accountview.cpp \ + accountitem.cpp \ + composemail.cpp \ + editaccounts.cpp \ + viewmail.cpp \ + viewmailbase.cpp \ + mailistviewitem.cpp \ + settingsdialog.cpp \ + statuswidget.cpp \ + newmaildir.cpp \ + selectstore.cpp \ + selectsmtp.cpp \ + nntpgroups.cpp \ + nntpgroupsdlg.cpp + +INTERFACES = editaccountsui.ui \ + selectmailtypeui.ui \ + imapconfigui.ui \ + pop3configui.ui \ + nntpconfigui.ui \ + smtpconfigui.ui \ + composemailui.ui \ + settingsdialogui.ui \ + statuswidgetui.ui \ + newmaildirui.ui \ + selectstoreui.ui \ + nntpgroupsui.ui + + +INCLUDEPATH += ../microkde ../microkde/kdecore ./libetpan/include $(QPEDIR)/include . .. ../microkde/kdeui ../qtcompat +LIBS += -L$(QPEDIR)/lib -lkmicromailwrapper -lqpe -lkmicrolibetpan -lmicrokde -lmicroqtcompat -lssl -lcrypto -ljpeg -lmicrokde -lmicroqtcompat -lmicrokabc +LIBS += $(QTOPIALIB) +#LIBS += -lqtopia +#next line for Zaurus only +#LIBS += -luuid +# +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/bin +TARGET = kmpi + + diff --git a/kmicromail/libetpan/config.h b/kmicromail/libetpan/config.h new file mode 100644 index 0000000..b7583bb --- a/dev/null +++ b/kmicromail/libetpan/config.h @@ -0,0 +1,112 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ +/* Define if you want to use OpenSSL. */ +#define USE_SSL 1 + +/* Define this to allow lazy syntax checking */ +#define UNSTRICT_SYNTAX 1 + +/* Define to the version number */ +/* #undef VERSION */ + +/* Define to detected Berkeley DB major version number */ +#define DBVERS 0 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the iconv() function. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Define this to the version of libEtPan */ +#define LIBETPAN_VERSION "0.32" + +/* Define this to the major version of libEtPan */ +#define LIBETPAN_VERSION_MAJOR 0 + +/* Define this to the minor version of libEtPan */ +#define LIBETPAN_VERSION_MINOR 32 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 diff --git a/kmicromail/libetpan/doc/API.sgml b/kmicromail/libetpan/doc/API.sgml new file mode 100644 index 0000000..4516979 --- a/dev/null +++ b/kmicromail/libetpan/doc/API.sgml @@ -0,0 +1,15097 @@ + + + + + 2003-12-03 + libEtPan! API + + + Viet Hoa + DINH + + + + 2003 + DINH Viet Hoa + + + + + + + Introduction + + This document will describe the API of libEtPan! + + + + + + Tools and datatypes + + + libEtPan! include a collection of datatypes such as lists, + arrays, hash tables and tools such as buffered I/O. + + + + + Array + + +#include <libetpan/libetpan.h> + +typedef struct carray_s carray; + + + + carray is an array of pointers that will + resize automatically in case a new element is added. + + + + The carray is implemented with an array + (void **) that can be resized. An array has a + size: this is the number of elements that can be added before + the table is resized. It also has a count of elements: this is + the elements that exist in the array. + + + + carray_new and carray_free + + +carray * carray_new(unsigned int initsize); + +void carray_free(carray * array); + + + + carray_new() creates a new array with an + initial size. The array is not resized until the number of + element reach the initial size. It returns + NULL in case of failure. + + + + carray_free() releases memory used by the + given array. + + + + carray creation + +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + exit(EXIT_FAILURE); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); +} + + + + + + carray_set_size + + +int carray_set_size(carray * array, uint32_t new_size); + + + + carray_set_size() sets the size of the + array. It returns 0 in case of success, + -1 in case of failure. + + + + preallocating carray + +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 +#define NEWSIZE 200 + +int main(void) +{ + carray * a; + unsigned int i; + char p[500]; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_set_size(NEWSIZE); + if (r < 0) + goto free; + + for(i = 0 ; i < NEWSIZE ; i ++) + carray_set(a, i, &p[i]); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + + + + + + + carray_count, carray_add, carray_get and carray_set + + +int carray_count(carray); + +int carray_add(carray * array, void * data, unsigned int * index); + +void * carray_get(carray * array, unsigned int indx); + +void carray_set(carray * array, unsigned int indx, void * value); + + + + carray_count() returns the number of + elements in the carray. + Complexity is O(1). + + + + carray_add()adds an element at the end of + the array. The index of the element is + returns in (* index) if + index is not NULL. It + returns 0 in case of success, + -1 in case of failure. + Complexity is O(1). + + + + carray_get() returns the elements contained + at the given cell of the table. + Complexity is O(1). + + + + carray_set() replace the element at the + given index of table table with the given value. + Complexity is O(1). + + + + carray access + +#include <libetpan/libetpan.h> +#include <string.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + int r; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + for(i = 0 ; i < carray_count(a) ; i ++) { + char * str; + + str = carray_get(a, i); + if (strcmp("foo-bar-2", str) == 0) + carray_set(a, i, "foo-bar-2-replacement"); + + printf("%s\n", str); + } + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + + + + + + + + carray_delete + + +int carray_delete(carray * array, uint32_t indx); + +int carray_delete_slow(carray * array, uint32_t indx); + +int carray_delete_fast(carray * array, uint32_t indx); + + + + carray_delete() removes an element of the + table. Order will not be garanteed. The returned result can + be ignored. + Complexity is O(1). + + + + carray_delete_slow() removes an element of + the table. Order will be garanteed. The returned result can + be ignored. + Complexity is O(n). + + + + carray_delete_fast() the element will just + be replaced with NULL. Order will be kept + but the number of elements will remains the same. The + returned result can be ignored. + Complexity is O(1). + + + + deletion in carray + +#include <libetpan/libetpan.h> + +#define SIZE 50 + +carray * build_array(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + return a; + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + +void delete(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete(a, 0); + /* resulting size is 2, order of elements is undefined */ +} + +void delete_slow(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* resulting size is 2, order of elements is the same */ +} + +void delete_fast(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* + resulting size is 3, + order of elements is { NULL, foo-bar-2, foo-bar-3 } + */ +} + + + + + + + carray_data + + +void ** carray_data(carray); + + + + carray_datareturns the table used for + implementation : + (void **). + + + + + + + + + + List + + +#include <libetpan/libetpan.h> + +typedef struct clist_s clist; + +typedef clistcell clistiter; + + + + clist() is a list of cells. + Each cell of the list contains one element. This element is a + pointer. An iterator (clistiter) is a + pointer to an element of the list. With an iterator, we can + get the previous element of the list, the next element of the + list and the content of the element. + + + + clist_new and clist_free + + +clist * clist_new(void); + +void clist_free(clist *); + + + + clist_new() allocates a new empty list and + returns it. + + + + clist_free() frees the entire list with + its cells. + + + + clist creation + +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + goto err; + + r = clist_append(list, "foo-bar"); + if (r < 0) + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + + + + + clist_isempty and clist_count + + +int clist_isempty(clist *); + +int clist_count(clist *); + + + + clist_isempty() returns 1 if the list is + empty, else it is 0. + Complexity is O(1). + + + + clist_count() returns the number of + elements in the list. + Complexity is O(1). + + + + + running through clist + + +clistiter * clist_begin(clist *); + +clistiter * clist_end(clist *); + +clistiter * clist_next(clistiter *); + +clistiter * clist_previous(clistiter *); + +void * clist_content(clistiter *); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + + + + clist_begin() returns an iterator to the + first element of the list. + Complexity is O(1). + + + + clist_end() returns an iterator to the last + element of the list. + Complexity is O(1). + + + + clist_next() returns an iterator to the + next element of the list. + Complexity is O(1). + + + + clist_previous() returns an iterator to the + previous element of the list. + Complexity is O(1). + + + + clist_content() returns the element + contained in the cell pointed by the iterator in the list. + Complexity is O(1). + + + + clist_nth() returns an iterator on the + index-th element of the list. + Complexity is O(n). + + + + clist_nth_data() returns the index-th + element of the list. + Complexity is O(n). + + + + displaying content of clist + +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + + + + + + clist modification + + +int clist_prepend(clist *, void *); + +int clist_append(clist *, void *); + +int clist_insert_before(clist *, clistiter *, void *); + +int clist_insert_after(clist *, clistiter *, void *); + +clistiter * clist_delete(clist *, clistiter *); + + + + clist_prepend() adds an element at the + beginning of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + + + + clist_append() adds an element at the end + of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + + + + clist_insert_before() adds an element + before the element pointed by the given iterator in the + list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + + + + clist_insert_after() adds an element after + the element pointed by the given iterator in the list. + Returns 0 on sucess, -1 on error. + Complexity is O(1). + + + + clist_delete() the elements pointed by + the given iterator in the list and returns an iterator to + the next element of the list. + Complexity is O(1). + + + + deleting elements in a clist + +#include <libetpan/libetpan.h> + +voir print_content(void * content, void * user_data) +{ + char * str; + + str = content; + + printf("%s\n", str); +} + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + iter = = clist_begin(list); + while (iter != NULL) + char * str; + + str = clist_content(iter); + if (strcmp(str, "foo-bar") == 0) + iter = clist_delete(list, cur); + else + iter = clist_next(iter); + } + + clist_foreach(list, print_content, NULL); + printf("\n"); + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + + + + + clist_foreach + + +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + + + + clist_foreach() apply a fonction to each + element of the list. + Complexity is O(n). + + + + + clist_concat + + +void clist_concat(clist * dest, clist * src); + + + + clist_concat() adds all the elements of src + at the end of dest. Elements are added in the same + order. src is an empty list when the operation is finished. + Complexity is O(1). + + + + merging two clists + +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clist * list_2; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + list_2 = build_string_list_2(); + if (list == NULL) + goto free_list; + + clist_concat(list, list_2); + clist_free(list_2); + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free_list: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + + + + + + + + Hash table + + +#include <libetpan/libetpan.h> + +typedef struct chash chash; + +typedef struct chashcell chashiter; + +typedef struct { + char * data; + int len; +} chashdatum; + + + + chash is a hash table. + chashiter is a pointer to an element of the + hash table. + chashdatum is an element to be placed in + the hash table as a key or a value. It consists in + data and a corresponding length. + + + + chash_new and chash_free + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +chash * chash_new(int size, int flags); + +void chash_free(chash * hash); + + + + chash_new() returns a new empty hash table + or NULL if this + failed. size is the initial size of the + table used for implementation. flags can + be a combinaison of CHASH_COPYKEY and + CHASH_COPYVALUE. + CHASH_COPYKEY enables copy of key, so + that the initial value used for chash_set() + + + + chash_free() releases memory used by the + hash table. + + + + + chash_set and chash_get + +int chash_set(chash * hash, + chashdatum * key, chashdatum * value, chashdatum * oldvalue); + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + + + + chash_set() adds a new element into the + hash table. If a previous element had the same key, it is + returns into oldvalue if oldvalue is + different of NULL. + Medium complexity is O(1). + + + + returns -1 if it fails, 0 on success. + + + + chash_get()returns the corresponding value + of the given key. If there is no corresponding value, -1 is + returned. 0 on success. + Medium complexity is O(1). + + + + chash insert and lookup + +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + + key.data = "foo"; + key.len = strlen("foo"); + value.data = str1; + value.data = strlen(str1) + 1; + /* + 1 is needed to get the terminal zero in the returned string */ + r = chash_set(hash, &key, &value, NULL); + if (r < 0) + goto free_hash; + + key.data = "bar"; + key.len = strlen("bar"); + value.data = str2; + value.data = strlen(str2) + 1; + if (r < 0) + goto free_hash; + + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + + + + + + chash_delete + +int chash_delete(chash * hash, + chashdatum * key, chashdatum * oldvalue); + + + + deletes the key/value pair given the corresponding key. + The value is returned in old_value. + If there is no corresponding value, -1 is returned. 0 on success. + Medium complexity is O(1). + + + + key deletion in a chash + +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = build_hash(); + + key.data = "foo"; + key.len = strlen("foo"); + chash_delete(hash, &key, &value); + + /* it will never be possible to lookup "foo" */ + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + + + + + + chash_resize + +int chash_resize(chash * hash, int size); + + + + chash_resize() changes the size of the + table used for implementation of the hash table. + returns 0 on success, -1 on failure. + + + + + running through the chash + +chashiter * chash_begin(chash * hash); + +chashiter * chash_next(chash * hash, chashiter * iter); + +void chash_key(chashiter * iter, chashdatum * result); + +void chash_value(chashiter iter, chashdatum * result); + + + + chash_begin() returns a pointer to the + first element of the hash table. Returns + NULL if there is no elements in the hash + table. + Complexity is O(n). + + + + chash_next() returns a pointer to the next + element of the hash table. Returns NULL + if there is no next element. + Complexity is O(n) but n calls to chash_next() also has + a complexity of O(n). + + + + chash_key() returns the key of the given + element of the hash table. + + + + chash_value returns the value of the + given element of the hash table. + + + + running through a chash + +int main(void) +{ + chash * hash; + int r; + chashiter * iter; + + hash = build_hash(); + + /* this will display all the values stored in the hash */ + for(iter = chash_begin(hash) ; iter != NULL ; iter = + chash_next(hash, iter)) { + chashdatum key; + chashdatum value; + char * str; + + chash_value(iter, &value); + str = value.data; + printf("%s\n", str); + } + + chash_free(hash); +} + + + + + + chash_size and chash_count + +int chash_size(chash * hash); + +int chash_count(chash * hash); + + + + chash_size() returns the size of the table + used for implementation of the hash table. + Complexity is O(1). + + + + chash_count() returns the number of + elements in the hash table. + Complexity is O(1). + + + + + + + Buffered I/O + + +#include <libetpan/libetpan.h> + +typedef struct _mailstream mailstream; + + + + streams are objects where we can read data from and write data + to. They are not seekable. That can be for example a pipe or a + network stream. + + + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +int mailstream_close(mailstream * s); + + + + mailstream_new() creates a new stream + stream with the low-level (see ) + stream and a given buffer size. + + + + mailstream_close() closes the stream. + This function will be in charge to free the + mailstream_low structure. + + + + +ssize_t mailstream_write(mailstream * s, void * buf, size_t count); + +int mailstream_flush(mailstream * s); + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +ssize_t mailstream_feed_read_buffer(mailstream * s); + + + + mailstream_write() writes a buffer to the + given stream. This write operation will be buffered. + + + + mailstream_flush() will force a write of + all buffered data for a given stream. + + + + mailstream_read() reads data from the + stream to the given buffer. + + + + mailstream_feed_read_buffer() this function + will just fill the buffer for reading. + + + +mailstream_low * mailstream_get_low(mailstream * s); + +void mailstream_set_low(mailstream * s, mailstream_low * low); + + + + mailstream_get_low() returns the low-level + stream of the given stream. + + + + mailstream_set_low() changes the low-level + of the given stream. Useful, for + example, when a stream change from clear stream to SSL + stream. + + + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + + + + mailstream_read_line() reads an entire line + from the buffer and store it into the + given string. returns NULL on error, the + corresponding array + of char is returned otherwise. + + + + mailstream_read_line_append() reads an entire + line from the buffer and appends it to the + given string. returns NULL on error, the + array of char corresponding to the entire buffer is returned + otherwise. + + + + mailstream_read_line_remove_eol() reads an + entire line from the buffer and store it into the + given string. All CR LF are removed. + returns NULL on error, the corresponding + array of char is returned otherwise. + + + + mailstream_read_multiline() reads a + multiline data (several lines, the data are ended with + a single period '.') + from the given stream and store it into the given + multiline buffer (multiline_buffer). progr_rate should be 0 + and progr_fun NULL (deprecated things). + stream_buffer is a buffer used for internal + work of the function. + size should be 0 (deprecated things). + + + +int mailstream_is_end_multiline(char * line); + + + + returns 1 if the line is an end of multiline data (a single + period '.', eventually with CR and/or LF). 0 is returned + otherwise. + + + +int mailstream_send_data(mailstream * s, char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + + + + sends multiline data to the given stream. + size is the size of the data. + progr_rate and progr_fun + are deprecated. progr_rate must be 0, + progr_fun must be NULL. + + + + socket stream + + +mailstream * mailstream_socket_open(int fd); + + + + mailstream_socket_open() will open a + clear-text socket. + + + + + TLS stream + + +mailstream * mailstream_ssl_open(int fd); + + + + mailstream_ssl_open() will open a + TLS/SSL socket. + + + + + + + non-buffered I/O + + +#include <libetpan/libetpan.h> + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + + + + mailstream_low is a non-buffered stream. + + + + The mailstream_low_driver is a set of + functions used to access the stream. + + + + + + mailstream_read/write/close() is the same + interface as read/write/close() + system calls, except that the file descriptor is replaced with the + mailstream_low structure. + + + + + mailstream_get_fd() returns the file + descriptor used for this non-buffered stream. + + + + + mailstream_free() is in charge to free + the internal structure of the mailstream_low and the + mailstream_low itself. + + + + + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + + + + mailstream_low_new() creates a low-level mailstream with the + given internal structure (data) and using the given set of + functions (driver). + + + +ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +int mailstream_low_close(mailstream_low * s); + +int mailstream_low_get_fd(mailstream_low * s); + +void mailstream_low_free(mailstream_low * s); + + + + Each of these calls will call the corresponding function defined + in the driver. + + + + + + + + strings + + +#include <libetpan/libetpan.h> + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; +}; + +typedef struct _MMAPString MMAPString; + + + + MMAPString is a string which size that can increase automatically. + + + + constructor and destructor + +MMAPString * mmap_string_new(const char * init); + +MMAPString * mmap_string_new_len(const char * init, size_t len); + +MMAPString * mmap_string_sized_new(size_t dfl_size); + +void mmap_string_free(MMAPString * string); + + + + mmap_string_new() allocates a new + string. init is the intial value of the string. + NULL will be returned on error. + + + + mmap_string_new_len() allocates a new + string. init is the intial value of the + string, len is the length of the initial string. + NULL will be returned on error. + + + + mmap_string_sized_new() allocates a new + string. dfl_size is the initial allocation of + the string. NULL will be returned on error. + + + + mmap_string_free() release the memory used + by the string. + + + + + string value modification + +MMAPString * mmap_string_assign(MMAPString * string, const char * rval); + +MMAPString * mmap_string_truncate(MMAPString *string, size_t len); + + + + mmap_string_assign() sets a new value for + the given string. + NULL will be returned on error. + + + + mmap_string_truncate() sets a length for + the string. + NULL will be returned on error. + + + +MMAPString * mmap_string_set_size (MMAPString * string, size_t len); + + + + sets the allocation of the string. + NULL will be returned on error. + + + + + insertion in string, deletion in string + +MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos, + const char * val, size_t len); + +MMAPString * mmap_string_append(MMAPString * string, const char * val); + +MMAPString * mmap_string_append_len(MMAPString * string, + const char * val, size_t len); + +MMAPString * mmap_string_append_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend(MMAPString * string, const char * val); + +MMAPString * mmap_string_prepend_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val, + size_t len); + +MMAPString * mmap_string_insert(MMAPString * string, size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, size_t pos, + size_t len); + + + + For complexity here, n is the size of the given MMAPString, + and len is the size of the string to insert. + + + + mmap_string_insert_len() inserts the given + string value of given length in the string at the given + position. NULL will be returned on error. + Complexity is O(n + len). + + + + mmap_string_append() appends the given + string value at the end of the string. + NULL will be returned on error. + Complexity is O(len). + + + + mmap_string_append_len() appends the + given string value of given length at the end of the + string. NULL will be returned on error. + Complexity is O(len). + + + + mmap_string_append_c() appends the given + character at the end of the string. + NULL will be returned on error. + Complexity is O(1). + + + + mmap_string_prepend() insert the given + string value at the beginning of the string. + NULL will be returned on error. + Complexity is O(n + len). + + + + mmap_string_prepend_c() insert the given + character at the beginning of the string. + NULL will be returned on error. + Complexity is O(n). + + + + mmap_string_prepend_len() insert the given + string value of given length at the beginning of the string. + NULL will be returned on error. + Complexity is O(n + len). + + + + mmap_string_insert() inserts the given + string value in the string at the given position. + NULL will be returned on error. + Complexity is O(n + len). + + + + mmap_string_insert_c() inserts the given + character in the string at the given position. + NULL will be returned on error. + Complexity is O(n). + + + + mmap_string_erase() removes the given + count of characters (len) at the given position of the + string. NULL will be returned on error. + Complexity is O(n). + + + + + + referencing string + +int mmap_string_ref(MMAPString * string); + +int mmap_string_unref(char * str); + + + + MMAPString provides a mechanism that let you use MMAPString + like normal strings. You have first to use + mmap_string_ref(), so that you notify + that the string will be used as a normal string, then, you + use mmapstr->str to refer to the + string. When you have finished and you want to free a string + corresponding to a MMAPString, you will + use mmap_string_unref. + + + + mmap_string_ref() references the string + so that the array of characters can be used as a normal + string then released with + mmap_string_unref(). + The array of characters will be obtained with string->str. + returns -1 on error, 0 on success. + + + + + + + + Internet Message Format + + + libEtPan! implements Internet Message parser. Currently, format + is RFC 2822. + This module also allows to generate messages. + + + + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + + + allocation functions will return NULL on failure + + functions returning integer will be returning one of the + following error code: + MAILIMF_NO_ERROR, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + or MAILIMF_ERROR_FILE. + + + + + Quick start + + + You will need this module when you want to parse headers + of messages or when you want to build message headers + conformant to standards. + + + + Parse message headers + + You will use one of the four following functions, depending + on your needs : + + + + + mailimf_envelope_and_optional_fields_parse + (), + + + + + mailimf_envelope_fields_parse + (), + + + + + mailimf_optional_fields_parse + (), + + + + + mailimf_fields_parse + (). + + + + + + + Render the message headers + + Build your message headers, then use + mailimf_fields_write + () + to render the headers. + + + + + + Data types + + + mailimf_mailbox - mailbox + +#include <libetpan/libetpan.h> + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + + This is an email mailbox with a display name. + + + + example of mailbox + +DINH Viet Hoa <hoa@users.sourceforge.net> + + + + + mailimf_mailbox_new creates and + initializes a data structure with a value. + Strings given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_mailbox_free frees memory used by + the structure and substructures will also be released. + + + + mailbox creation and display + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + /* do the things */ + mailimf_mailbox_free(mb); + + return 0; +} + +/* display mailbox information */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox(struct mailimf_mailbox * mb) +{ + if (mb->mb_display_name != NULL) + printf("display name: %s\n", mb->mb_display_name); + printf("address specifier : %s\n", mb->mb_addr_spec); +} + + + + + + + mailimf_address - address + + +#include <libetpan/libetpan.h> + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + + + + This is a mailbox or a group of mailbox. + + + + + + ad_type can be MAILIMF_ADDRESS_MAILBOX or + MAILIMF_ADDRESS_GROUP. + + + + + ad_data.ad_mailbox is a mailbox if + ad_type is + MAILIMF_ADDRESS_MAILBOX + see ) + + + + + ad_data.group is a group if type is + MAILIMF_ADDRESS_GROUP. + see ) + + + + + + mailimf_address_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_address_free frees memory used by + the structure and substructures will also be released. + + + + address creation and display + +/* creates an address of type mailbox */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_mb; + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + + a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + /* do the things */ + mailimf_address_free(a_mb); +} + +/* creates an address of type group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_g; + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + + a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g); + /* do the things */ + mailimf_address_free(a_g); + + return 0; +} + +/* display the content of an address */ + +#include <libetpan/libetpan.h> + +void display_address(struct mailimf_address * a) +{ + clistiter * cur; + + switch (a->ad_type) { + case MAILIMF_ADDRESS_GROUP: + display_mailimf_group(a->ad_data.ad_group); + break; + + case MAILIMF_ADDRESS_MAILBOX: + display_mailimf_mailbox(a->ad_data.ad_mailbox); + break; + } +} + + + + + + + mailimf_mailbox_list - list of mailboxes + + +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + + This is a list of mailboxes. + + + + mb_list is a list of mailboxes. This is a + clist which elements are of type + mailimf_mailbox (see ). + + + + mailimf_mailbox_list_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_mailbox_list_free() frees memory used by the + structure and substructures will also be released. + + + + Creation and display of mailimf_mailbox_list + +/* creates a list of mailboxes with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + /* do the things */ + mailimf_mailbox_list_free(mb_list); + + return 0; +} + +/* display a list of mailboxes */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox_list(struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + display_mailbox(mb); + printf("\n"); + } +} + + + + + + + mailimf_address_list - list of addresses + + +#include <libetpan/libetpan.h> + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + This is a list of addresses. + + + + ad_list is a list of addresses. This is a + clist which elements are + of type mailimf_address (see ). + + + + mailimf_address_list_new() creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + + + mailimf_address_list_free() frees memory + used by the structure and substructures will also be released. + + + + creation and display of list of addresses + +/* creates a list of addresses with two addresses */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address_list * addr_list; + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + addr_list = mailimf_address_list_new(list); + /* do the things */ + mailimf_address_list_free(mb_list); + + return 0; +} + +/* display a list of addresses */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_address_list(struct mailimf_address_list * addr_list) +{ + clistiter * cur; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + display_address(addr); + printf("\n"); + } +} + + + + + + + mailimf_group - named group of mailboxes + +#include <libetpan/libetpan.h> + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + + + + This is a list of mailboxes tagged with a name. + + + + example of group + + they play music: <steve@morse.foo>, <neal@morse.foo>, + <yngwie@malmsteen.bar>, <michael@romeo.bar>; + + + + + grp_display_name is the name that will be + displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, + address2@domain2;'. + This must be allocated with malloc(). + grp_mb_list is a list of mailboxes + (see ). + + + + mailimf_group_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_group_free() frees memory used by + the structure and substructures will also be released. + + + + creation and display of a group + +/* creates an empty group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + /* do the things */ + mailimf_group_free(g); +} + +/* creates a group with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + + display_name = strdup("my_group"); + g = mailimf_group_new(display_name, mb_list); + /* do the things */ + mailimf_group_free(g); + + return 0; +} + +/* display content of group */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_group(struct mailimf_group * group) +{ + printf("name of the group: %s\n", a->group->display_name); + for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + display_mailbox(mb); + printf("\n"); + } +} + + + + + + + mailimf_date_time - date of a message + + +#include <libetpan/libetpan.h> + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + + This is the date and time of a message. + For example : + + + example of date + +Thu, 11 Dec 2003 00:15:02 +0100. + + + + + + + dt_day is the day of month (1 to 31) + + + + + dt_month (1 to 12) + + + + + dt_year (4 digits) + + + + + dt_hour (0 to 23) + + + + + dt_min (0 to 59) + + + + + dt_sec (0 to 59) + + + + + dt_zone (this is the decimal value that + we can read, for example: for + '-0200', the value is + -200). + + + + + + mailimf_date_time_new() creates and + initializes a date structure with a value. + + + + mailimf_date_time_free() frees memory used + by the structure. + + + + creation and display of date + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + /* do the things */ + mailimf_date_time_free(d); + + return 0; +} + +/* display the date */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_date(struct mailimf_date_time * d) +{ + printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n", + d->dt_day, d->dt_month, d->dt_year, + d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); +} + + + + + + + mailimf_orig_date - parsed content of date header + + +#include <libetpan/libetpan.h> + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + This is the content of a header Date or + Resent-Date. + It encapsulates a mailimf_date_time + + + + dt_date_time is the parsed date + (see ). + + + + mailimf_orig_date_new() creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + + + mailimf_orig_date_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of Date field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + struct mailimf_orig_date * date; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + date = mailimf_orig_date_new(d); + /* do the things */ + mailimf_orig_date_free(date); + + return 0; +} + +/* display date header */ + +#include <libetpan/libetpan.h> + +void display_orig_date(struct mailimf_orig_date * orig_date) +{ + display_date_time(d->dt_date_time); +} + + + + + + + mailimf_from - parsed content of From header + +#include <libetpan/libetpan.h> + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + + + + This is the content of a header From or + Resent-From. + + + frm_mb_list is the parsed mailbox list + (see ). + + + + mailimf_from_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_from_free() frees memory used by + the structure and substructures will also be released. + + + + creation and display of a From header + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + /* do the things */ + mailimf_from_free(from); + + return 0; +} + +/* display content of from header */ + +#include <libetpan/libetpan.h> + +void display_from(struct mailimf_from * from) +{ + display_mailbox_list(from->frm_mb_list); +} + + + + + + + mailimf_sender - parsed content of Sender header + + +#include <libetpan/libetpan.h> + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + + + + This is the content of a header Sender or + Resent-Sender. + + + + snd_mb is the parsed mailbox + (see ). + + + + mailimf_sender_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_sender_free() This function frees + memory used by the structure and substructures + will also be released. + + + + creation and display of Sender field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + + sender = mailimf_sender_new(mb); + /* do the things */ + mailimf_sender_free(sender); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_sender(struct mailimf_sender * sender) +{ + display_mailbox(sender->snd_mb); +} + + + + + + + mailimf_reply_to - parsed content of Reply-To header + + +#include <libetpan/libetpan.h> + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + This is the content of a header Reply-To. + + + + addr_list is the parsed address list + (see ). + + + + mailimf_reply_to_new() creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + + + + mailimf_reply_to_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of Reply-To field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + reply_to = mailimf_reply_to_new(addr_list); + /* do the things */ + mailimf_reply_to_free(reply_to); + + return 0; +} + +/* display Reply-To header */ + +#include <libetpan/libetpan.h> + +void display_reply_to(struct mailimf_reply_to * reply_to) +{ + display_address_list(reply_to->addr_list); +} + + + + + + + mailimf_to - parsed content of To header + + + struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + + + + This is the content of a header To or + Resent-To. + + + + to_addr_list is the parsed address list + (see ). + + + + mailimf_to_new() creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created + object and will be freed if the object is released. + + + + mailimf_to_free() frees memory used by the + structure and substructures will also be released. + + + + creation and display of To field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + /* do the things */ + mailimf_to_free(to); + + return 0; +} + +/* display To header */ + +#include <libetpan/libetpan.h> + +void display_to(struct mailimf_to * to) +{ + display_address_list(to->to_addr_list); +} + + + + + + + mailimf_cc - parsed content of Cc + + +#include <libetpan/libetpan.h> + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * +mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); + + + + This is the content of a header Cc or + Resent-Cc. + + + + cc_addr_list is the parsed address list + (see ). + + + + mailimf_cc_new() creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + + + + mailimf_cc_free() This function frees + memory used by the structure and substructures will also be + released. + + + + creation and display of Cc field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + cc = mailimf_cc_new(addr_list); + /* do the things */ + mailimf_cc_free(cc); + + return 0; +} + +/* display content of Cc field */ + +#include <libetpan/libetpan.h> + +void display_cc(struct mailimf_cc * cc) +{ + display_address_list(cc->cc_addr_list); +} + + + + + + + + + mailimf_bcc - parsed content of Bcc field + + +#include <libetpan/libetpan.h> + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + + This is the content of a header Bcc or + Resent-Bcc. + + + + bcc_addr_list is the parsed address list + (see ). + + + + mailimf_bcc_new() creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + + + + mailimf_bcc_free() frees memory used by the + structure and substructures will also be released. + + + + creation and display of Bcc field + +/* create visible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + bcc = mailimf_bcc_new(addr_list); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* create unvisible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_bcc * bcc; + + bcc = mailimf_bcc_new(NULL); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* display content of Bcc field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_bcc(struct mailimf_bcc * bcc) +{ + if (bcc->addr_list == NULL) { + printf("hidden Bcc\n"); + } + else { + display_address_list(bcc->bcc_addr_list); + } +} + + + + + + + mailimf_message_id - parsed content of Message-ID header + + +#include <libetpan/libetpan.h> + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + This is the content of a header Message-ID + or Resent-Message-ID. For example : + + + + example of Message-ID + +Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>> + + + + + mid_value is the message identifier. + It is not enclosed by angle bracket. + + + + mailimf_message_id_new() This function + creates and initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + The given string is allocated with + malloc() and is not enclosed by angle bracket. + + + + mailimf_message_id_free() frees memory + used by the structure and substructures will also be + released. + + + + creation and display of Message-ID field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_message_id * msg_id; + char * id; + + id = strdup("1037197913.3dd26259752fa@imp.free.fr"); + msg_id = mailimf_message_id_new(id); + /* do the things */ + mailimf_message_id_free(msg_id); + + return 0; +} + +/* display message id */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message_id(struct mailimf_message_id * msg_id) +{ + printf("%s\n", msg_id->mid_value); +} + + + + + + + mailimf_in_reply_to - parsed content of In-Reply-To + field + + +#include <libetpan/libetpan.h> + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + + content of a header In-Reply-To. + For example : + + + +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + + + + mid_list is a clist + in which elements are message identifiers. + their types are (char *) and they are + allocated with malloc(). + + + + mailimf_in_reply_to_new() creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + + + + mailimf_in_reply_to_free() frees memory + used by the structure and substructures will also be + released. + + + + creation and display of In-Reply-To field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_in_reply_to * in_reply_to; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid")); + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(in_reply_to); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to) +{ + clistiter * cur; + + for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + + + + + + + mailimf_references - parsed content of References field + + +#include <libetpan/libetpan.h> + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + + + + This is the content of a header References. + For example : + + +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + <3FD5FA78.A1D98E7@oleane.net> + <etPan.3fd5fc69.2b349482.730e@homer> + + + + mid_list is a clist + in which elements are message identifiers. + their types are (char *) and they are + allocated with malloc(). + + + + mailimf_references_new() creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + + + + mailimf_references_free() frees memory + used by the structure and substructures will also be + released. + + + + creation and display of References field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_references * ref; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("etPan.3eb29de4.5fc4d652.3f83@homer")); + + ref = mailimf_references_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(ref); + + return 0; +} + +/* display references */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_references(struct mailimf_references * ref) +{ + clistiter * cur; + + for(cur = clist_begin(ref->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * msg_id; + + msg_id = clist_content(cur); + + printf("%s\n", msg_id); + } +} + + + + + + + mailimf_subject - parsed content of Subject field + + +#include <libetpan/libetpan.h> + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); + + + + This is the content of a header Subject. + + + + sbj_value is the value of the field. + + + + mailimf_subject_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_subject_free frees memory used by + the structure and substructures will also be released. + + + + creation and display of Subject field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_subject * subject; + + subject = mailimf_subject_new(strdup("example of subject")); + /* do the things */ + mailimf_subject_free(subject); + + return 0; +} + +/* display subject header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_subject(struct mailimf_subject * subject) +{ + printf("%s\n", subject->value); +} + + + + + + + mailimf_comments - parsed content of Comments field + + +#include <libetpan/libetpan.h> + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + + + + This is the content of a header Comments. + + + + cm_value is the value of the field. + + + + mailimf_comments_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_comments_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of Comment field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_comments * comments; + + comments = mailimf_comments_new(strdup("example of comment")); + /* do the things */ + mailimf_comments_free(comments); + + return 0; +} + +/* display the content of a comments */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_comments(struct mailimf_comments * comments) +{ + printf("%s\n", comments->cm_value); +} + + + + + + + mailimf_keywords - parsed content of Keywords field + + +#include <libetpan/libetpan.h> + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + + + This is the content of a header Keywords. + + + + kw_list is the list of keywords. This is + a list of (char *) allocated with malloc(). + + + + mailimf_keywords_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_keywords_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of Keywords field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_keywords * keywords; + clist * list; + + list = clist_new(); + clist_append(list, strdup("sauerkraut")); + clist_append(list, strdup("potatoes")); + clist_append(list, strdup("cooking")); + + keywords = mailimf_keywords_new(list); + /* do the things */ + mailimf_keywords_free(keywords); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_keywords(struct mailimf_keywords * kw) +{ + clistiter * cur; + + for(cur = clist_begin(kw->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + + + + + + + mailimf_return - parsed content of Return-Path field + + +#include <libetpan/libetpan.h> + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + + + + This is the content of a header + Return-Path. + + + + ret_path is the parsed value of Return-Path + (see ). + + + + mailimf_return_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_return_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of Return-Path field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + struct mailimf_return * r; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + r = mailimf_return_new(path); + /* do the things */ + mailimf_return_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> + +void display_return(struct mailimf_return * r) +{ + display_path(r->ret_path); +} + + + + + + + mailimf_path - address in Return-Path field + + +#include <libetpan/libetpan.h> + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + + + + This is the encapsulation of address specifier for + Return-Path content. + + + + pt_addr_spec is a mailbox destination. + + + + mailimf_path_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + The given string is allocated with + malloc(). This is a address + specifier. + + + + mailimf_path_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of return path + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + /* do the things */ + mailimf_path_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_path(struct mailimf_path * path) +{ + printf("%s\n", path->pt_addr_spec); +} + + + + + + + mailimf_optional_field - non-standard header + + +#include <libetpan/libetpan.h> + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + + + This is a non-standard header or unparsed header. + + + + + + fld_name is the name of the header + field. + + + + + fld_value is the value of the header + field. + + + + + + mailimf_optional_field_new() This + function creates and initializes a data structure with a + value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + + + field name and field value have to be allocated with + malloc(). + + + + mailimf_optional_field_free() This + function frees memory used by the structure and + substructures will also be released. + + + + creation and display of non-standard fields + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_optional_field * opt; + + opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value")); + /* do the things */ + mailimf_optional_field_free(opt); + + return 0; +} + +/* display the optional field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_optional_field(struct mailimf_optional_field * opt) +{ + printf("%s: %s\n", opt->fld_name, opt->fld_value); +} + + + + + + + mailimf_field - header field + + +#include <libetpan/libetpan.h> + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + + + + This is one header field of a message. + + + + + + type is the type of the field. This define the + type of the field. + Only the corresponding field should be, then, + filled. The value of this field can be one of : + MAILIMF_FIELD_RETURN_PATH, + MAILIMF_FIELD_RESENT_DATE, + MAILIMF_FIELD_RESENT_FROM, + MAILIMF_FIELD_RESENT_SENDER, + MAILIMF_FIELD_RESENT_TO, + MAILIMF_FIELD_RESENT_CC, + MAILIMF_FIELD_RESENT_BCC, + MAILIMF_FIELD_RESENT_MSG_ID, + MAILIMF_FIELD_ORIG_DATE, + MAILIMF_FIELD_FROM, + MAILIMF_FIELD_SENDER, + MAILIMF_FIELD_REPLY_TO, + MAILIMF_FIELD_TO, + MAILIMF_FIELD_CC, + MAILIMF_FIELD_BCC, + MAILIMF_FIELD_MESSAGE_ID, + MAILIMF_FIELD_IN_REPLY_TO, + MAILIMF_FIELD_REFERENCES, + MAILIMF_FIELD_SUBJECT, + MAILIMF_FIELD_COMMENTS, + MAILIMF_FIELD_KEYWORDS, + MAILIMF_FIELD_OPTIONAL_FIELD. + + + + + fld_data.fld_return_path is the + parsed content of the Return-Path field + if type is MAILIMF_FIELD_RETURN_PATH + (see ). + + + + + fld_data.fld_resent_date is the + parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + (see ). + + + + + fld_data.fld_resent_from is the + parsed content of the Resent-From field + if type is MAILIMF_FIELD_RESENT_FROM + (see ). + + + + + fld_data.fld_resent_sender is the + parsed content of the Resent-Sender field + if type is MAILIMF_FIELD_RESENT_SENDER + (see ). + + + + + fld_data.fld_resent_to is the parsed + content of the Resent-To field + if type is MAILIMF_FIELD_RESENT_TO + (see ). + + + + + fld_data.fld_resent_cc is the parsed + content of the Resent-Cc field + if type is MAILIMF_FIELD_CC + (see ). + + + + + fld_data.fld_resent_bcc is the parsed + content of the Resent-Bcc field + if type is MAILIMF_FIELD_BCC + (see ). + + + + + fld_data.fld_resent_msg_id is the + parsed content of the Resent-Message-ID field + if type is MAILIMF_FIELD_RESENT_MSG_ID + (see ). + + + + + fld_data.fld_orig_date is the parsed + content of the Date field + if type is MAILIMF_FIELD_ORIG_DATE + (see ). + + + + + fld_data.fld_from is the parsed + content of the From field + if type is MAILIMF_FIELD_FROM + (see ). + + + + + fld_data.fld_sender is the parsed + content of the Sender field + if type is MAILIMF_FIELD_SENDER + (see ). + + + + + fld_data.fld_reply_to is the parsed + content of the Reply-To field + if type is MAILIMF_FIELD_REPLY_TO + (see ). + + + + + fld_data.fld_to is the parsed content + of the To field if type is + MAILIMF_FIELD_TO + (see ). + + + + + fld_data.fld_cc is the parsed content + of the Cc field if type is + MAILIMF_FIELD_CC + (see ). + + + + + fld_data.fld_bcc is the parsed + content of the Bcc field if type is + MAILIMF_FIELD_BCC + (see ). + + + + + fld_data.fld_message_id is the parsed + content of the Message-ID field + if type is MAILIMF_FIELD_MESSAGE_ID + (see ). + + + + + fld_data.fld_in_reply_to is the + parsed content of the In-Reply-To field + if type is MAILIMF_FIELD_IN_REPLY_TO + (see ). + + + + + fld_data.fld_references is the parsed + content of the References field + if type is MAILIMF_FIELD_REFERENCES + (see ). + + + + + fld_data.fld_subject is the content + of the Subject field + if type is MAILIMF_FIELD_SUBJECT + (see ). + + + + + fld_data.fld_comments is the content of the + Comments field + if type is MAILIMF_FIELD_COMMENTS + (see ). + + + + + fld_data.fld_keywords is the parsed + content of the Keywords field + if type is MAILIMF_FIELD_KEYWORDS + (see ). + + + + + fld_data.fld_optional_field is an + other field and is not parsed + if type is MAILIMF_FIELD_OPTIONAL_FIELD + (see ). + + + + + + mailimf_field_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_field_free() frees memory used by + the structure and substructures will also be released. + + + + creation and display of field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_field * f; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + /* do the things */ + mailimf_field_free(f); + + return 0; +} + +/* display content of the header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_field(struct mailimf_field * field) +{ + switch (field->type) { + case MAILIMF_FIELD_RETURN_PATH: + printf("Return-Path:\n"); + display_return(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + printf("Resent-Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + printf("Resent-From:\n"); + display_from(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_SENDER: + printf("Resent-Sender:\n"); + display_sender(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + printf("Resent-To:\n"); + display_to(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + printf("Resent-Cc:\n"); + display_from(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + printf("Resent-Bcc:\n"); + display_from(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + printf("Resent-Message-ID:\n"); + display_message_id(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + printf("Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + printf("From:\n"); + display_from(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + printf("Sender:\n"); + display_sender(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + printf("Reply-To:\n"); + display_reply_to(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + printf("To:\n"); + display_to(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + printf("Cc:\n"); + display_cc(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + printf("Bcc:\n"); + display_bcc(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + printf("Message-ID:\n"); + display_message_id(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + printf("In-Reply-To:\n"); + display_in_reply_to(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + printf("References:\n"); + display_references(field->fld_data.fld_references_to); + break; + case MAILIMF_FIELD_SUBJECT: + printf("Subject:\n"); + display_subject(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + printf("Comments:\n"); + display_comments(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + printf("Keywords:\n"); + display_keywords(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + printf("[optional field]:\n"); + display_optional_field(field->fld_data.fld_optional_field); + break; + } +} + + + + + + + mailimf_fields - list of header fields + + +#include <libetpan/libetpan.h> + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + + + + This is the list of header fields of a message. + + + + fld_list is a list of header fields. This + is a clist which elements are + of type mailimf_field (see ). + + + + mailimf_fields_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_fields_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of header fields + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + +/* display list of headers */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_fields(struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(field->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * f; + + f = clist_content(cur); + + display_field(f); + printf("\n"); + } +} + + + + + + + mailimf_body - message body without headers + + +#include <libetpan/libetpan.h> + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + + + + This is the text content of a message (without headers). + + + + + + bd_text is the beginning of the + text part, it is a substring of an other string. + It is not necessarily zero terminated. + + + + + bd_size is the size of the text part + + + + + + + mailimf_body_new() creates and + initializes a data structure with a value. + Text given as argument will NOT be released. + + + + mailimf_body_free() frees memory used by + the structure. + + + + creation and display of message body + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + + b = mailimf_body_new("this is the content of the message", 34); + /* do the things */ + mailimf_body_free(b); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_body(struct mailimf_body * b) +{ + char * text; + + text = malloc(b->size + 1); + strncpy(text, b->bd_text, b->bd_size); + text[b->size] = 0; + + puts(text); + printf("\n"); + + free(text); + + return 0; +} + + + + + + + mailimf_message - parsed message + + +#include <libetpan/libetpan.h> + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + + + + This is the message content (text and headers). + + + + + + msg_fields is the header fields of + the message + (see ). + + + + + msg_body is the text part of the message + (see ). + + + + + + mailimf_message_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailimf_message_free() frees memory used + by the structure and substructures will also be released. + + + + creation and display of message + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + struct mailimf_message * m; + struct mailimf_fields * fields; + struct mailimf_fields * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build text content */ + + b = mailimf_body_new("this is the content of the message", 34); + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* build message */ + + m = mailimf_message_new(fields, b); + /* do the things */ + mailimf_message_free(m); + + return 0; +} + +/* display the message */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message(struct mailimf_message * msg) +{ + display_fields(msg->msg_fields); + printf("\n"); + display_body(msg->msg_body); + printf("\n"); +} + + + + + + + mailimf_single_fields - simplified fields + + +#include <libetpan/libetpan.h> + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + + + + Structure that contains some standard fields and allows access + to a given header without running through the list. + + + + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when + parsing fields. + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + + + + + fld_orig_date is the parsed "Date" + field + (see ). + + + + + fld_from is the parsed "From" field + (see ). + + + + + fld_sender is the parsed "Sender "field + (see ). + + + + + reply_to is the parsed "Reply-To" field + (see ). + + + + + fld_to is the parsed "To" field + (see ). + + + + + fld_cc is the parsed "Cc" field + (see ). + + + + + fld_bcc is the parsed "Bcc" field + (see ). + + + + + fld_message_id is the parsed + "Message-ID" field. + (see ). + + + + + fld_in_reply_to is the parsed + "In-Reply-To" field. + (see ). + + + + + fld_references is the parsed + "References" field. + (see ). + + + + + fld_subject is the parsed "Subject" field + (see ). + + + + + fld_comments is the parsed "Comments" field + (see ). + + + + + fld_keywords is the parsed "Keywords" field + (see ). + + + + + + mailimf_single_fields_new() creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will NOT be freed if the + object is released. + + + + mailimf_single_fields_free() frees memory + used by the structure and + substructures will NOT be + released. They should be released by the application. + + + + mailimf_single_fields_init() will + initialize fill the data structure, using + the given argument (fields). The + interesting fields will be filled into + single_fields. + + + + using mailimf_single_fields + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields * single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* create the single fields */ + single_fields = mailimf_single_fields_new(fields); + /* do the things */ + mailimf_single_fields_free(single_fields); + mailimf_fields_free(fields); + + return 0; +} + + + + + using mailimf_single_fields without memory allocation + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* fill the single fields */ + mailimf_fields_fields_init(&single_fields, fields); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + + + + + + + + Parser functions + + + + mailimf_address_list_parse + +int +mailimf_address_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + + + + mailimf_address_list_parse() parse a list + of addresses in RFC 2822 form. + + + + + + message this is a string containing + the list of addresses. + + + + + length this is the size of the given string + + + + + index this is a pointer to the + start of the list of + addresses in the given string, + (* index) is modified to point + at the end of the parsed data. + + + + + result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing a list of addresses + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address_list * addr_list; + size_t current_index; + + current_index = 0; + r = mailimf_address_list_parse(mem, stat_info.st_size, + &current_index, &addr_list); + if (r == MAILIMF_NO_ERROR) { + display_address_list(addr_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_list_free(addr_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailimf_address_parse + + +#include <libetpan/libetpan.h> + +int +mailimf_address_parse(char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + + + + mailimf_address_parse() parse an address + in RFC 2822 form. + + + + + + message this is a string containing the + address. + + + + + length this is the size of the given + string. + + + + + index index this is a pointer to the + start of the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result the result of the parse operation + is stored in (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing an address + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address * addr; + size_t current_index; + + current_index = 0; + r = mailimf_address_parse(mem, stat_info.st_size, + &current_index, &addr); + if (r == MAILIMF_NO_ERROR) { + display_address(addr); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_free(addr); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_body_parse + + +#include <libetpan/libetpan.h> + +int mailimf_body_parse(char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + + + + mailimf_body_parse() parse text body of a + message. + + + + + + message this is a string containing + the message body part. + + + + + length this is the size of the given + string. + + + + + index this is a pointer to the start + of the message text part in + the given string, (* index) is + modified to point at the end + of the parsed data. + + + + + result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing a message body + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_body * b; + struct mailimf_fields * f; + size_t current_index; + size_t size; + + size = stat_info.st_size; + current_index = 0; + r = mailimf_fields_parse(mem, size, &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_crlf_parse(mem, size, &current_index); + /* ignore parse error of crlf */ + + r = mailimf_body_parse(mem, size, &current_index, &b); + if (r == MAILIMF_NO_ERROR) { + + display_body(b); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_body_free(b); + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_envelope_and_optional_fields_parse + + +#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + + mailimf_envelope_and_optional_fields_parse() + returns a list of most useful headers (parsed). The other + headers will be placed in the list in a non-parsed form. + + + + + + message this is a string containing the header. + + + + + length this is the size of the given string + + + + + index index this is a pointer to the + start of the header in the given string, (* + index) is modified to point at the end + of the parsed data + + + + + result the result of the parse + operation is stored in (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing commonly used fields and return other fields + in a non-parsed form + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_envelope_fields_parse + + +#include <libetpan/libetpan.h> + +int mailimf_envelope_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + + mailimf_envelope_fields_parse() return a + list of most useful headers (parsed). + + + + + + message this is a string containing the header + + + + + length this is the size of the given string + + + + + index index this is a pointer to the + start of the header in + the given string, (* index) is + modified to point at the end + of the parsed data + + + + + result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing commonly used fields + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_optional_fields_parse + + +#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + + mailimf_optional_fields_parse return a + list of non-parsed headers. + + + + + + message this is a string containing the header + + + + + length this is the size of the given string + + + + + index index this is a pointer to the + start of the header in + the given string, (* index) is + modified to point at the end + of the parsed data + + + + + result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing optional fields + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_optional_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailimf_fields_parse + + +#include <libetpan/libetpan.h> + +int mailimf_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + + mailimf_fields_parse() parse headers of a + message. + + + + + + message this is a string containing the header + + + + + length this is the size of the given string + + + + + index index this is a pointer to the + start of the header in + the given string, (* index) is + modified to point at the end + of the parsed data + + + + + result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + parsing header fields + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(f); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailimf_ignore_field_parse + + +#include <libetpan/libetpan.h> + +int mailimf_ignore_field_parse(char * message, size_t length, + size_t * index); + + + + mailimf_ignore_field_parse() skip the + next header. + + + + + + message this is a string containing the header + + + + + length this is the size of the given string + + + + + index index this is a pointer to the + start of the field to skip in + the given string, (* index) is + modified to point at the end + of the parsed data + + + + + + return MAILIMF_NO_ERROR on success, + MAILIMF_ERROR_XXX on error. + + + + skipping fields + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + size_t current_index; + + current_index = 0; + r = mailimf_ignore_field_parse(mem, stat_info.st_size, + &current_index); + if (r == MAILIMF_NO_ERROR) { + /* do the things */ + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailimf_mailbox_list_parse + + +#include <libetpan/libetpan.h> + +int +mailimf_mailbox_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + + + + mailimf_mailbox_list_parse() parse a list + of mailboxes in RFC 2822 form. + + + + + + message this is a string containing the + list of mailboxes. + + + + + length this is the size of the given + string. + + + + + index index this is a pointer to the + start of the list of + mailboxes in the given string, + (* index) is modified to point + at the end of the parsed data. + + + + + result the result of the parse + operation is stored in + (* result). + (see ) + + + + + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + + + + parsing a list of mailboxes + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_list_parse(mem, stat_info.st_size, + &current_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_list_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_mailbox_parse + + +#include <libetpan/libetpan.h> + +int mailimf_mailbox_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + + + + mailimf_mailbox_parse parse a mailbox in + RFC 2822 form. + + + + + + message this is a string containing the + mailbox. + + + + + length this is the size of the given + string. + + + + + index index this is a pointer to the + start of the mailbox in the given string, + (* index) is modified to point + at the end of the parsed data. + + + + + result the result of the parse + operation is stored in + (* result). + (see ) + + + + + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + + + + parsing a mailbox + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_parse(mem, stat_info.st_size, + &current_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailimf_message_parse + + +#include <libetpan/libetpan.h> + +int mailimf_message_parse(char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + + + + mailimf_message_parse parse message + (headers and body). + + + + + + message this is a string containing + the message content. + + + + + param length this is the size of the given + string. + + + + + param index this is a pointer to the + start of the message in + the given string, (* index) is + modified to point at the end + of the parsed data. + + + + + param result the result of the parse + operation is stored in + (* result) + (see ). + + + + + + parsing a message + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_message * m; + size_t current_index; + + current_index = 0; + r = mailimf_message_parse(mem, stat_info.st_size, + &current_index, &m); + if (r == MAILIMF_NO_ERROR) { + display_message(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_message_free(m); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + + Creation functions + + mailimf_mailbox_list + +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + + + + + mailimf_mailbox_list_new_empty() creates a + new empty list of mailboxes. + + + + + mailimf_mailbox_list_add adds a mailbox + to the list of mailboxes. + + + + + mailimf_mailbox_list_add_parse adds a + mailbox given in form of a string to the list of mailboxes. + + + + + mailimf_mailbox_list_add_mb adds a + mailbox given in form of a couple : display name, mailbox + address. + + + + + + mailbox_list is the list of mailboxes. + + + + + mb is a mailbox + (see ). + + + + + mb_str is a mailbox given in the form + of a string. + + + + + display_name is the display name. + + + + + address is the mailbox address. + + + + + + creating a list of mailboxes + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + + mb_list = mailimf_mailbox_list_new_empty(); + + mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"), + strdup("dinh.viet.hoa@free.fr")); + mailimf_mailbox_list_add(mb_list, mb); + + mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>"); + + mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com")); + + mailimf_mailbox_list_free(mb_list); +} + + + + + + mailimf_address_list + +#include <libetpan/libetpan.h> + +struct mailimf_address_list * mailimf_address_list_new_empty(); + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + + + + + mailimf_address_list_new_empty() creates a + new empty list of addresses. + + + + + mailimf_address_list_add adds an address + to the list of addresses. + + + + + mailimf_address_list_add_parse adds an + address given in form of a string to the list of addresses. + + + + + mailimf_address_list_add_mb adds a + mailbox given in form of a couple : display name, mailbox + address. + + + + + + address_list is the list of mailboxes. + + + + + addr is an address. + (see ). + + + + + addr_str is an address given in the form of a + string. + + + + + display_name is the display name. + + + + + address is the mailbox address. + + + + + + + mailimf_fields + +#include <libetpan/libetpan.h> + +struct mailimf_fields * +mailimf_fields_new_empty(void); + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +char * mailimf_get_message_id(void); + +struct mailimf_date_time * mailimf_get_current_date(void); + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc); + + + + + + from is the parsed content of the + From field + (see ). + + + + + sender is the parsed content of the + Sender field + (see ). + + + + + reply_to is the parsed content of the + Reply-To field + (see ). + + + + + to is the parsed content of the + To field + (see ). + + + + + cc is the parsed content of the + Cc field + (see ). + + + + + bcc is the parsed content of the + Bcc field + (see ). + + + + + message_id is the parsed content of + the Message-ID field + (see ). + + + + + in_reply_to is the parsed content of + the In-Reply-To field + (see ). + + + + + references is the parsed content of + the References field + (see ). + + + + + subject is the content of the + Subject field + (see ). + + + + + resent_date is the parsed content of + the Resent-Date field + (see ). + + + + + resent_from is the parsed content of + the Resent-From field + (see ). + + + + + resent_sender is the parsed content of the + Resent-Sender field + (see ). + + + + + resent_to is the parsed content of + the Resent-To field + (see ). + + + + + resent_cc is the parsed content of + the Resent-Cc field + (see ). + + + + + resent_bcc is the parsed content of the + Resent-Bcc field + (see ). + + + + + resent_msg_id is the parsed content of the + Resent-Message-ID field + (see ). + + + + + + + mailimf_fields_new_empty() creates a new + empty set of headers. + + + + + mailimf_field_new_custom() creates a new + custom header. + + + + + mailimf_fields_add() adds a header to the + set of headers. + + + + + mailimf_fields_add_data() adds some headers + to the set of headers. + + + + + mailimf_fields_new_with_data_all() creates + a set of headers with some headers (including Date and + Message-ID). + + + + + mailimf_fields_new_with_data() creates a + set of headers with some headers (Date and Message-ID will + be generated). + + + + + mailimf_get_message_id() generates a + Message-ID. The result must be freed using + free(). + + + + + mailimf_get_current_date() generates a + Date. The result must be freed using + mailimf_date_time_free. + + + + + mailimf_resent_fields_add_data() adds some + resent headers to the set of headers. + + + + + mailimf_resent_fields_new_with_data_all() + creates a set of headers with some resent headers (including + Resent-Date and Resent-Message-ID). + + + + + mailimf_resent_fields_new_with_data() + creates a set of headers with some resent headers + (Resent-Date and Resent-Message-ID will be generated) + + + + creation of header fields + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * field; + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + fields = mailimf_fields_new_empty(); + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer")); + mailimf_fields_add(fields, field); + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + struct mailimf_date_time * date; + char * msg_id; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + + fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL, + NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + + + + + + + + Rendering of messages + + Header fields + +#include <libetpan/libetpan.h> + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + + + + + + col current column is given for wrapping + purpose in (* col), + the resulting columns will be returned.. + + + + + f is the file descriptor. It can be + stdout for example. + + + + + fields is the header fields + (see ). + + + + + field is a field + (see ). + + + + + + + mailimf_fields_write outputs the set of + header fields. + + + + + mailimf_envelope_fields_write outputs the + set of header fields except the optional fields. + + + + + mailimf_field_write outputs a header. + + + + rendering of fields + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_envelope_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_field * field; + int col; + + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer")); + + col = 0; + mailimf_field_write(stdout, &col, field); + + mailimf_field_free(field); +} + + + + + + + + + + MIME + + + libEtPan! implements a MIME message parser (also known as + messages with attachments or + multipart messages). This also allows to generate MIME messages. + + + + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + + + allocation functions will return NULL on failure + + functions returning integer will be returning one of the + following error code: + MAILIMF_NO_ERROR, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + or MAILIMF_ERROR_FILE. + + + + + Quick start + + + You will need this module when you want to parse a MIME + message. + + + + Parse MIME message + + You will use the following function : + + + + + mailmime_parse + () + + + + + + + Render the MIME message + + Build your MIME message, then use + mailmime_write + () + to render a MIME message. + + + + + + Data types + + + mailmime_composite_type - Composite MIME type + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + + + + This is a MIME composite type such as message or + multipart. + + + + ct_type can have one of the 3 following values : + MAILMIME_COMPOSITE_TYPE_MESSAGE when the + composite MIME type + is message, + MAILMIME_COMPOSITE_TYPE_MULTIPART when + the composite MIME type + is multipart, + MAILMIME_COMPOSITE_TYPE_EXTENSION for + other and ct_token is set + in this case. + MAILMIME_COMPOSITE_TYPE_ERROR is used + internally on parse error. + + + + mailmime_composite_type_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_composite_type_free() frees + memory used by + the structure and substructures will also be released. + + + + create and display MIME composite type + +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_composite_type * ct; + + ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + + /* do your things ... */ + + mailmime_composite_type_free(ct); + + exit(EXIT_SUCCESS); +} + +void display_composite_type() +{ + switch (ct->type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + printf("composite type is message\n"); + break; + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + printf("composite type is multipart\n"); + break; + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + printf("composite type: %s\n", ct->ct_token); + break; + } +} + + + + + + + + mailmime_content - MIME content type (Content-Type) + + +#include <libetpan/libetpan.h> + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + + + + This is a MIME content type such as message/rfc822 or + text/plain. + + + + + + ct_type is the main MIME type, + for example text in + plain/text + (see ). + + + ct_subtype is the MIME subtype, + for example plain in + plain/text. + + + + + ct_parameters is the list of parameters for + the given MIME type. For example, for plain/text, + we can find charset=iso-8859-1, + format=flowed. Each element of the list + if of type struct mailmime_parameter * + (see ). + + + + + + mailmime_content_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_content_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME content type + +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_content * content; + struct mailmime_type * type; + struct mailmime_discrete_type * dt; + struct mailmime_parameter * param; + clist * param_list; + + dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL); + param_list = clist_new(); + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + clist_append(param_list, param); + + content = mailmime_content_new(type, strdup("plain"), param_list); + + /* do your things */ + + exit(EXIT_SUCCESS); +} + +void display_mime_content(struct mailmime_content * content_type) +{ + clistiter * cur; + + printf("type:\n"); + display_type(content_type->ct_type); + printf("\n"); + printf("subtype: %s\n", content_type->ct_subtype); + printf("\n"); + + for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + display_mime_parameter(param); + printf("\n"); + } + printf("\n"); +} + + + + + + + + mailmime_discrete_type - MIME discrete type + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + + + + This is a MIME discrete type such as text or + image. This is also known as single part. This kind + of part does not have any child. + + + + dt_type is one of the given values : + MAILMIME_DISCRETE_TYPE_TEXT if part is text, + MAILMIME_DISCRETE_TYPE_IMAGE if part is an image, + MAILMIME_DISCRETE_TYPE_AUDIO if part is + audio data, + MAILMIME_DISCRETE_TYPE_VIDEO if part is video, + MAILMIME_DISCRETE_TYPE_APPLICATION if + part is application data or + MAILMIME_DISCRETE_TYPE_EXTENSION for other. + In the case of MAILMIME_DISCRETE_TYPE_EXTENSION, + dt_extension is filled in. + MAILMIME_DISCRETE_TYPE_ERROR is used internally. + + + + mailmime_discrete_type_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_discrete_type_free() frees + memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME discrete type + +#include <libetpan/libetpan.h> + +/* standard type */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +/* extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION, + strdup("my-type")); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + printf("text\n"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + printf("image\n"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + printf("audio\n"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + printf("video\n"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + printf("application\n"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + printf("extension : %s\n", discrete_type->dt_extension); + break; + } +} + + + + + + + + mailmime_field - MIME header field + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + + + + This is a parsed MIME header field; + + + + + + fld_type is the type of MIME header field. The value can + be + MAILMIME_FIELD_TYPE + if field is Content-Type, + MAILMIME_FIELD_TRANSFER_ENCODING + if field is Content-Transfer-Encoding, + MAILMIME_FIELD_ID + if field is Content-ID, + MAILMIME_FIELD_DESCRIPTION + if field is Content-Description, + MAILMIME_FIELD_VERSION + if field is MIME-Version, + MAILMIME_FIELD_DISPOSITION + if field is Content-Disposition or + MAILMIME_FIELD_LANGUAGE + if field is Content-Language. + MAILMIME_FIELD_NONE is used internally. + + + + + fld_data.fld_content is set in case of + Content-Type. + (see ). + + + + + fld_data.fld_encoding is set in case of + Content-Transfer-Encoding. + (see ). + + + + + fld_data.fld_id is set in case of + Content-ID. This is a string. + + + + + fld_data.fld_description is set in case of + Content-Description. This is a string. + + + + + fld_data.fld_version is set in case of + MIME-Version. This is an integer built + using the following formula : + fld_version = major * 2^16 + minor. + Currenly MIME-Version is always 1.0, this means that + fld_version will always be 2^16 (in C language, + this is 1 << 16). + + + + + fld_data.fld_disposition is set in case of + Content-Disposition. + (see ). + + + + + fld_data.fld_language is set in case of + Content-Language. + (see ). + + + + + + mailmime_field_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_field_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME header field + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + + /* do the things */ + + mailmime_field_free(field); +} + +void display_mime_field(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + printf("content-type:"); + display_mime_content(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + printf("content-transfer-encoding:"); + display_mime_mechanism(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + printf("content-id: %s\n", field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + printf("content-description: %s\n", field->fld_data.fld_description); + break; + case MAILMIME_FIELD_VERSION: + printf("mime-version: %i.%i\n", + field->version>> 16, field->fld_data.fld_version & 0xFFFF); + break; + case MAILMIME_FIELD_DISPOSITION: + printf("content-disposition:"); + display_mime_disposition(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + printf("content-language:"); + display_mime_language(field->fld_data.fld_language); + break; + } +} + + + + + + + mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding) + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + + + + This is a MIME transfer encoding mechanism description. + + + + enc_type is an encoding type. The value of this field + can be + MAILMIME_MECHANISM_7BIT + if mechanism is 7bit, + MAILMIME_MECHANISM_8BIT + if mechanism is 8bit, + MAILMIME_MECHANISM_BINARY + if mechanism is binary, + MAILMIME_MECHANISM_QUOTED_PRINTABLE + if mechanism is quoted-printable, + MAILMIME_MECHANISM_BASE64 + if mechanism is base64 or + MAILMIME_MECHANISM_TOKEN for other. + In case of MAILMIME_MECHANISM_TOKEN, + field enc_token is filled in. + MAILMIME_MECHANISM_ERROR is used internally. + + + + mailmime_mechanism_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_mechanism_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME transfer encoding mechanism + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN, + strdup("uuencoding")); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +void display_mime_mechanism(struct mailmime_mechanism * encoding) +{ + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("extension : %s\n", encoding->enc_token); + break; + } +} + + + + + + + mailmime_fields - header fields + + +#include <libetpan/libetpan.h> + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + + + + This is the header fields of a MIME part. + + + + fld_list is the list of the header fields. + Each element of the list is a mailmime_field + (See ). + + + + mailmime_fields_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_fields_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME fields + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + clist * list; + struct mailmime_mechanism * encoding; + struct mailmime_disposition * disposition; + + list = clist_new(); + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + clist_append(list, field); + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL); + clist_append(list, field); + + /* look at the example in mailmime_disposition to see how to + build a mailmime_disposition */ + disposition = build_mime_disposition(); + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + clist_append(list, field); + + fields = mailmime_fields_new(list); + + /* do the things */ + + mailmime_fields_free(fields); +} + +void display_mime_fields(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + display_field(field); + } +} + + + + + + + mailmime_parameter - MIME type parameter + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + + + + This is the MIME type parameter in + Content-Type MIME header + field. For example, this can be + charset="iso-8859-1". + + + + + + pa_name is the name of the parameter, + for example : charset. + + + + + pa_value is the value of the parameter, + for example : iso-8859-1. + + + + + + mailmime_parameter_new() creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_parameter_free() frees memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME type parameter + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_parameter * param; + + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + + /* do the things */ + + mailmime_parameter_free(param); +} + +void display_mime_parameter(struct mailmime_parameter * param) +{ + printf("%s = %s\n", param->pa_name, param->pa_value); +} + + + + + + + + mailmime_type - MIME main type + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + + + + This is the MIME main type (no subtype, no parameter). + + + + + + tp_type. The value of this field + is either MAILMIME_TYPE_DISCRETE_TYPE for MIME discrete type, + or MAILMIME_TYPE_COMPOSITE_TYPE for MIME composite type. + MAILMIME_TYPE_ERROR is used internally. + + + + + tp_data.tp_discrete_type is set when tp_type + is MAILMIME_TYPE_DISCRETE_TYPE + (see ). + + + + + tp_data.tp_composite_type is set when tp_type + is MAILMIME_TYPE_COMPOSITE_TYPE + (see ). + + + + + + mailmime_discrete_type_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_discrete_type_free() frees + memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME main type + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_discrete_type * discrete_type; + + discrete_type = + mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL); + + /* do the things */ + + mailmime_type_free(type); +} + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type); + + /* do the things */ + + mailmime_type_free(type); +} + +void display_mime_type(struct mailmime_type * type) +{ + printf("mime type:\n"); + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + printf("discrete type:\n"); + display_mime_discrete_type(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + printf("composite type:\n"); + display_mime_composite_type(type->tp_data.tp_composite_type); + break; + } + printf("\n"); +} + + + + + + + mailmime_language - Language of MIME part + + +#include <libetpan/libetpan.h> + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + + + + This is the language used in the MIME part. + + + + lg_list is the list of codes of languages used + in the MIME part. This is a list of strings. + + + + mailmime_language_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_language_free() frees + memory used by + the structure and substructures will also be released. + + + + Creation and display of language of MIME part + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_language * language; + clist * list; + + list = clist_new(); + + clist_append(list, strdup("fr")); + clist_append(list, strdup("en")); + + language = mailmime_language_new(list); + + /* do the things */ + + mailmime_language_free(language); +} + +void display_mime_language(struct mailmime_language * language) +{ + clistiter * cur; + + printf("languages: "); + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * name; + + name = clist_content(cur); + printf("%s ", name); + } + printf("\n"); +} + + + + + + + + mailmime_data - Content of MIME part + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_ + + + This is the content of MIME part, content of + preamble or content of epilogue. + + + + dt_type can be + MAILMIME_DATA_TEXT if + the content is a string in memory, + MAILMIME_DATA_FILE if the + content is in a file, + + + + dt_encoding is the encoding mechanism + of the part. The value of this field can be + MAILMIME_MECHANISM_7BIT if mechanism is + 7bit, + MAILMIME_MECHANISM_8BIT if mechanism is + 8bit, + MAILMIME_MECHANISM_BINARY if mechanism is + binary, + MAILMIME_MECHANISM_QUOTED_PRINTABLE if + mechanism is quoted-printable, + MAILMIME_MECHANISM_BASE64 if mechanism is + base64 or + MAILMIME_MECHANISM_TOKEN for other. If + MAILMIME_MECHANISM_TOKEN, the part will + be considered as binary. + MAILMIME_MECHANISM_ERROR is used internally. + + + + dt_encoded is set to 1 if the part is + already encoded with the mechanism given in + dt_encoding. It is set to 0 if the part + is already decoded or if it is necessary to encode that part + before rendering it. + + + + dt_data.dt_text.dt_data is a pointer to the + content of the part and dt_data.dt_text.dt_length + is the length of the data if dt_type is + MAILMIME_DATA_TEXT. + + + + dt_data.dt_filename is the name of the file if + dt_type is MAILMIME_DATA_FILE. + + + + mailmime_data_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_data_free() frees + memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME part content + + +#include <libetpan/libetpan.h> + +/* build data with a string */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, "foo bar", 7, NULL); + + /* do the things */ + + mailmime_data_free(data); +} + +/* build data with a file */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, NULL, 0, strdup("foo.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + +void display_mime_data(struct mailmime_data * data) +{ + switch (data->dt_encoding) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("other\n"); + break; + } + + if (data->dt_encoded) + printf("already encoded\n"); + else + printf("not encoded\n"); + + switch (data->dt_type) { + MAILMIME_DATA_TEXT: + printf("data : %p %i\n", data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + break; + MAILMIME_DATA_FILE, + printf("data (file) : %s\n", data->dt_data.dt_filename); + break; + } +} + + + + + + + mailmime - MIME part + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + + + + This describes the MIME structure of a message or a subpart + of a message. + + + + common + + + + + mm_parent_type. MIME part type can be + single part, multipart or message part. This describes the MIME part + type of the parent. The value can be + MAILMIME_NONE if there is no parent part, + MAILMIME_SINGLE if parent is a single part, + MAILMIME_MULTIPLE if parent is a multipart, + MAILMIME_MESSAGE if parent is a mesage part. + + + + + + mm_parent is the parent MIME structure. + + + + + + mm_multipart_pos. In the case the parent + is a multipart. This is the position in the list of children + of the parent. This position is given by a + clisiter *. + + + + + + mm_type. This describes the MIME part type + of this part. The value can be + MAILMIME_SINGLE if this is a single part, + MAILMIME_MULTIPLE if this is a multipart, + MAILMIME_MESSAGE if this is a mesage part. + + + + + + mm_mime_start. This is used mostly internally. + This gives the beginning of the header of the MIME part, when this + is parsed from a string in memory. + + + + + + + mm_length. This gives the length of the MIME part, + including the MIME header fields. + + + + + + mm_mime_fields is the list of parsed MIME headers + of this part. Content-Type must be excluded and stored + in mm_content_type instead + (see ). + + + + + + + mm_content_type is the parsed + Content-Type field + (see ). + + + + + + + mm_body is the content of the MIME part + (excluding MIME header), when it is parsed from a string + in memory + (see ). + + + + + + + single part + + + + + When the part is a single part (mm_type + is MAILMIME_SINGLE). The following fields + are valid. + + + + + + mm_data.mm_single is the content of the + MIME part (excluding MIME header), when it is parsed from a string + in memory. This must have the same + value as mm_body when it is set + (see ). + + + + + + + multipart + + + + + When the part is a multipart (mm_type + is MAILMIME_MULTIPLE). The following fields + are valid. + + + + + + mm_data.mm_multipart.mm_preamble + is the content of the preamble of the multipart + (see ). + + + + + + mm_data.mm_multipart.mm_epilogue + is the content of the epilogue of the multipart + (see ). + + + + + + mm_data.mm_multipart.mm_mp_list + is the list of sub parts + + + + + + + message part + + + + + When the part is a message (mm_type + is MAILMIME_MESSAGE). The following fields + are valid. + + + + + + mm_data.mm_message.mm_fields is the list of + the header fields of the message + (see ). + + + + + + mm_data.mm_message.mm_msg_mime is + the subpart + of the message part. + + + + + + + constructor and destructor + + + mailmime_new() creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + + + + mailmime_free() frees + memory used by + the structure and substructures will also be released. + + + + Creation and display of MIME part + + +#include <libetpan/libetpan.h> + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + "foo", 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + str = malloc(4); + strcpy(str, "foo"); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a MIME part with a sub-message */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, sub_mime, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build a MIME part with a sub-message (given by a string) */ + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * msg_content; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + str = malloc(sizeof(SUB_MESSAGE)); + strcpy(str, SUB_MESSAGE); + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, sizeof(SUB_MESSAGE), NULL); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, NULL, msg_content); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a multipart message */ + + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + struct mailmime_data * body; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + clist * list; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("mixed"), NULL); + + list = clist_new(); + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + PREAMBLE, sizeof(PREAMBLE), NULL); + + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + EPILOGUE, sizeof(EPILOGUE), NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + NULL, preamble, epilogue, list, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* display mime part info */ + +void display_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + printf("single part\n"); + break; + case MAILMIME_MULTIPLE: + printf("multipart\n"); + break; + case MAILMIME_MESSAGE: + printf("message\n"); + break; + } + + printf("part : %p, length : %i\n", + mime->mm_mime_start, mime->mm_length); + printf("\n"); + + if (mime->mm_mime_fields != NULL) { + printf("MIME headers :\n"); + display_mime_fields(mime->mm_mime_fields); + printf("\n"); + } + + printf("content type :\n"); + display_content(mime->mm_content_type); + printf("\n"); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + display_mime_data(mime->mm_data.mm_single); + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble) { + printf("preamble :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_preamble); + printf("\n"); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + display_mime(clist_content(cur)); + } + + if (mime->mm_data.mm_multipart.mm_epilogue) { + printf("epilogue :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_epilogue); + printf("\n"); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields) { + printf("headers :\n"); + display_field(mime->mm_data.mm_message.mm_msg_fields); + printf("\n"); + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + printf("sub message %p :\n", + mime->mm_data.mm_message.mm_msg_mime); + display_mime(mime->mm_data.mm_message.mm_msg_mime); + printf("end of sub message %p\n", + mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + + + + + + + + + mailmime_disposition - MIME disposition information (Content-Disposition) + + +#include <libetpan/libetpan.h> + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + + + This is the parsed Content-Disposition + header field. + + + + + + dsp_type is the type of disposition + (see ). + + + + + + dsp_parms is the list of parameters + of Content-Disposition header field. + Each element is of type mailmime_disposition_parm + (see ). + + + + + + Creation and display of MIME disposition information + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_disposition_type * disposition_type; + clist * disposition_parms; + struct mailmime_disposition_parm * param; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + clist_append(disposition_parms, param); + + disposition = mailmime_disposition_new(disposition_type, disposition_parms); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + +void display_mime_disposition(struct mailmime_disposition * disposition) +{ + clistiter * cur; + + printf("disposition type:\n"); + display_mailmime_disposition_type(disposition->dsp_type); + printf("\n"); + printf("disposition parameters:\n"); + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parm * param; + + param = clist_content(cur); + display_mime_disposition_parm(param); + } + printf("\n"); +} + + + + + + + + mailmime_disposition_type - Type of MIME disposition + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + + + This is the type of MIME disposition. + Parsed Content-Disposition field without + parameters. + + + + dsp_type is the type of disposition. + The value can be + MAILMIME_DISPOSITION_TYPE_INLINE + if MIME disposition is inline, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT + if MIME disposition is attachment, + MAILMIME_DISPOSITION_TYPE_EXTENSION + for other. In this case, dsp_extension must be + set. + MAILMIME_DISPOSITION_TYPE_ERROR is used internally. + + + + Creation and display of MIME disposition type + +#include <libetpan/libetpan.h> + +/* standard disposition type */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +/* disposition type extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION, + strdup("mydisposition")); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +void display_mime_disposition_type(struct mailmime_disposition_type * disposition_type) +{ + switch (disposition->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + printf("inline\n"); + break; + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + printf("attachment\n"); + break; + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + printf("extension : %s\n", disposition_type->dsp_extension); + break; + } +} + + + + + + + mailmime_disposition_parm - MIME disposition parameter + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + + + + This is a parameter of MIME disposition information. For + example, this can be + filename="foo.jpg". + + + + + + pa_type is the type of + disposition. The value can be + MAILMIME_DISPOSITION_PARM_FILENAME + for a filename parameter, + MAILMIME_DISPOSITION_PARM_CREATION_DATE + for a creation date parameter, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE + for a modification date parameter, + MAILMIME_DISPOSITION_PARM_READ_DATE + for a last read date parameter, + MAILMIME_DISPOSITION_PARM_SIZE + for a file size parameter or + MAILMIME_DISPOSITION_PARM_PARAMETER + for other parameters. + + + + + + pa_data.pa_filename is the filename + parameter when pa_type is + MAILMIME_DISPOSITION_PARM_FILENAME + This is a string containing the name of the + file. + + + + + pa_data.pa_creation_date is the + creation date parameter when pa_type is + MAILMIME_DISPOSITION_PARM_CREATION_DATE. + This is a string containing the formatted creation date. + + + + + + pa_data.pa_modification_date is the + modification date parameter when pa_type is + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE. + This is a string containing the formatted modification date. + + + + + + pa_data.pa_read_date is the + last read date parameter when pa_type is + MAILMIME_DISPOSITION_PARM_READ_DATE. + This is a string containing the formatted last read date. + + + + + + pa_data.pa_size is the size + parameter when pa_type is + MAILMIME_DISPOSITION_PARM_SIZE. + This gives the size of the file. + + + + + + pa_data.pa_parameter is the + name and the value of the parameter when + pa_type is + MAILMIME_DISPOSITION_PARM_PARAMETER + (see ) + + + + + + Creation and display of MIME disposition + parameter + + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_parm * param; + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + /* do the things */ + + mailmime_disposition_parm_free(param); +} + +void display_mime_dsp_parm(struct mailmime_disposition_parm * param) +{ + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + printf("filename: %s\n", param->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + printf("creation date: %s\n", param->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + printf("modification date: %s\n", param->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + printf("read date: %s\n", param->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + printf("size: %lu\n", (unsigned long) param->pa_data.pa_size); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + printf("MIME disposition param:\n"); + display_mime_parameter(param->pa_data.pa_parameter); + break; + } +} + + + + + + + mailmime_single_fields - MIME headers + + + +#include <libetpan/libetpan.h> + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + + + + mailmime_fields (see ) is the native structure + that MIME module will use, this module will provide an easier + structure to use when + parsing fields. mailmime_single_fields is + an easier structure to get parsed fields, rather than + iteration over the list of fields. + + + + + + fld_content is the MIME content type + (see ). + + + + + fld_content_charset is the value + of the MIME type parameter charset. + + + + + fld_content_boundary is the value + of the MIME type parameter boundary. + + + + + fld_content_name is the value + of the MIME type parameter name. + + + + + fld_encoding is the MIME encoding + mechanism used + (see ). + + + + + fld_id is the content of the field + Content-ID. + + + + + fld_description is the content of the field + Content-Description. + + + + + fld_version is the version of MIME + in use. + + + + + fld_disposition is the MIME + disposition information + (see ). + + + + + fld_disposition_filename is + the filename parameter of the + MIME disposition information. + + + + + fld_disposition_creation_date is + the creation-date parameter of the + MIME disposition information. + + + + + fld_disposition_modification_date is + the modification-date parameter of the + MIME disposition information. + + + + + fld_disposition_read_date is + the read-date parameter of the + MIME disposition information. + + + + + fld_disposition_size is + the size parameter of the + MIME disposition information. + + + + + fld_language is the language + of the MIME part + (see ). + + + + + single_fields is the structure to fill. + + + + + fld_fields is the MIME fields list to + use to fill the single_fields. + + + + + + mailmime_single_fields_new() creates and + initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will NOT be freed if the + object is released. + + + + mailmime_single_fields_free() frees + memory used by the structure and + substructures will NOT be + released. They should be released by + the application. + + + + mailimf_single_fields_init() will + initialize fill the data structure, using + the given argument (fld_fields and + fld_content). The interesting fields will + be filled into single_fields. + + + + Creation and display of single fields + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_single_fields * single_fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + single_fields = mailmime_single_fields_new(mime_fields, content_type); + + /* do the things */ + + mailmime_single_fields_free(single_fields); + mailmime_fields_free(mime_fields); +} + +void display_mime_single_fields(struct mailmime_single_fields * single_fields) +{ + if (single_fields->fld_content != NULL) { + printf("content type:\n"); + display_mime_content(single_fields->fld_content); + printf("\n"); + } + if (single_fields->fld_content_charset != NULL) { + printf("content type charset: %s\n", + single_fields->fld_content_charset); + printf("\n"); + } + if (single_fields->fld_content_boundary != NULL) { + printf("content type boundary: %s\n", + single_fields->fld_content_boundary); + printf("\n"); + } + if (single_fields->content_name != NULL) { + printf("content type name: %s\n", single_fields->content_name); + printf("\n"); + } + if (single_fields->fld_encoding != NULL) { + printf("content transfer encoding:\n"); + display_mime_mechanism(single_fields->fld_encoding); + printf("\n"); + } + if (single_fields->fld_id != NULL) { + printf("content id: %s\n", single_fields->fld_id); + printf("\n"); + } + if (single_fields->fld_description != NULL) { + printf("content description: %s\n", single_fields->fld_description); + printf("\n"); + } + if (single_fields->fld_version != 0) { + printf("mime version: %i.%i\n", + single_fields->fld_version>> 16, + single_fields->fld_version & 0xFFFF); + printf("\n"); + } + if (single_fields->fld_disposition != NULL) { + printf("content disposition:\n"); + display_mime_disposition(single_fields->fld_disposition); + printf("\n"); + } + if (single_fields->fld_disposition_filename != NULL) { + printf("content disposition filename: %s\n", + single_fields->fld_disposition_filename); + printf("\n"); + } + if (single_fields->fld_disposition_creation_date != NULL) { + printf("content disposition creation date: %s\n", + single_fields->fld_disposition_creation_date); + printf("\n"); + } + if (single_fields->fld_disposition_modification_date != NULL) { + printf("content disposition modification date: %s\n", + single_fields->fld_disposition_modification_date); + printf("\n"); + } + if (single_fields->fld_disposition_read_date != NULL) { + printf("content disposition read date: %s\n", + single_fields->fld_disposition_read_date; + printf("\n"); + } + if (single_fields->fld_disposition_size != (size_t) -1) { + printf("content disposition size : %i\n", + single_fields->fld_disposition_size); + printf("\n"); + } + if (single_fields->language != NULL) { + printf("content language:\n"); + display_mime_language(single_fields->fld_language); + printf("\n"); + } +} + + + + + + + + + Parser functions + + + + mailmime_content_parse + + +#include <libetpan/libetpan.h> + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + + + + This function will parse the content of a + Content-Type header field. + + + + + + message is a string containing + the MIME content type. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + Parsing MIME content type + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_content(content_type); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_description_parse + + +#include >libetpan/libetpan.h< + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + + + + This will parse the content of + Content-Description MIME header field. + + + + + + message is a string containing + the MIME content description. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result). + The result string must be freed with + free(). + + + + + + Parsing MIME description + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Description") == 0) { + char * description; + size_t current_index; + + current_index = 0; + r = mailmime_description_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &description); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", description); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + + mailmime_encoding_parse + + +#include >libetpan/libetpan.h< + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + + + + This function will parse the content of + Content-Transfer-Encoding header field. + + + + + + message is a string containing + the MIME encoding mechanism. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing MIME encoding mechanism + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Transfer-Encoding") == 0) { + struct mailmime_content * encoding; + size_t current_index; + + current_index = 0; + r = mailmime_encoding_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &encoding); + if (r == MAILIMF_NO_ERROR) { + display_mime_mechanism(encoding); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_mechanism_free(encoding); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_field_parse + + +#include <libetpan/libetpan.h> + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + + + + This function will parse a MIME header field. + + + + + + field is a non-parsed field + (see ). + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing MIME header field + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_field(mime_field); + mailmime_field_free(mime_field); + status = EXIT_SUCCESS; + } + } + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailmime_id_parse + + +#include >libetpan/libetpan.h< + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + + + + This will parse the content of + Content-ID MIME header field. + + + + + + message is a string containing + the MIME content identifier. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result). + The result string must be freed with + free(). + + + + + + Parsing MIME content identifier + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-ID") == 0) { + char * id; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &id); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", id); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_fields_parse + + +#include <libetpan/libetpan.h> + +int +mailmime_fields_parse(struct mailimf_fields * fields, + struct mailmime_fields ** result); + + + + This function will parse a MIME header fields. + + + + + + fields is a list of RFC 2822 fields + (see ). + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing MIME header fields + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_fields(mime_fields); + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailmime_version_parse + + +#include <libetpan/libetpan.h> + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + + + + This will parse the content of + MIME-Version MIME header field. + + + + + + message is a string containing + the MIME version. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing MIME version + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + uint32_t version; + size_t current_index; + + current_index = 0; + r = mailmime_version_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &version); + if (r == MAILIMF_NO_ERROR) { + printf("%i.%i\n", version >> 16, version & 0xFFFF); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_parameter_parse + + +#include <libetpan/libetpan.h> + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + + + + This will parse a MIME parameter (parameter of + Content-Type or parameter of + Content-Disposition). + + + + + + message is a string containing + the MIME parameter. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing a MIME parameter + + +#include <libetpan/libetpan.h> + +#define PARAM_STR "foo=bar" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_parameter * param; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1, + &current_index, &param); + if (r == MAILIMF_NO_ERROR) { + display_mime_parameter(param); + /* do the things */ + mailmime_parameter_free(param); + status = EXIT_SUCCESS; + } + + exit(status); +} + + + + + + + mailmime_language_parse + + +#include <libetpan/libetpan.h> + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + + + + This function will parse the content of a + Content-Language header. + + + + + + message is a string containing + the MIME content language. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + Parsing the MIME content langage + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Language") == 0) { + struct mailmime_language * lang; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &lang); + if (r == MAILIMF_NO_ERROR) { + display_mime_language(lang); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_disposition_parse + + +#include <libetpan/libetpan.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + + + + This function will parse the content of a + Content-Disposition MIME header field. + + + + + + message is a string containing + the MIME content disposition. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + Parsing the MIME content disposition + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Disposition") == 0) { + struct mailmime_disposition * dsp; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &dsp); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition(dsp); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_disposition_type_parse + + +#include <libetpan/libetpan.h> + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** + result); + + + + This function will parse the type of MIME content + disposition. + + + + + + message is a string containing + the MIME content disposition type. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing a MIME content disposition type + + +#include <libetpan/libetpan.h> + +#define DSP_TYPE_STR "attachment" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_disposition_type * dsp_type; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1, + &current_index, &dsp_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition_type(dsp_type); + /* do the things */ + mailmime_disposition_type_free(dsp_type); + status = EXIT_SUCCESS; + } + + exit(status); +} + + + + + + + mailmime_encoded_phrase_parse + + +#include <libetpan/libetpan.h> + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + + + + This function will decode a MIME encoded header string, + encoded with RFC 2047. + + + + + + default_fromcode is the default + code to use for parts of string that are not marked + with charset. + + + + + message is the string to decode. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + tocode is the destination charset + for decoding. + + + + + result. The result of the parse + operation is stored in (* result). + + + + + + decoding a MIME encoded header string + + +#include <libetpan/libetpan.h> + +#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?=" + +int main(int argc, char ** argv) +{ + size_t cur_token; + char * decoded_subject; + + cur_token = 0; + mailmime_encoded_phrase_parse("iso-8859-1", + TEST_STRING, sizeof(TEST_STRING), + &cur_token, "iso-8859-1", &decoded_subject); + + printf("%s\n", decoded_subject); + + /* do the things */ + + free(decoded_subject); +} + + + + + + + + mailmime_parse + + +#include <libetpan/libetpan.h> + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + + + + This will parse a MIME message. + + + + + + message is a string containing + the MIME message. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + (see ). + + + + + + parsing a MIME message + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailmime * mime; + size_t current_index; + + current_index = 0; + r = mailmime_parse(mem, stat_info.st_size, + &current_index, &mime); + if (r == MAILIMF_NO_ERROR) { + display_mime(mime); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_free(mime); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_base64_body_parse + + +#include <libetpan/libetpan.h> + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + + + + This function will parse a body part encoded using base64. + + + + + + message is a string encoded using + base64. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + The result must be freed with + mmap_string_unref(). + + + + + + Parsing a base64 encoded part + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_base64_body_parse(mem, stat_info.st_size, + &current_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_quoted_printable_body_parse + + +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + + + This function will parse a body part encoded using quoted + printable. + + + + + + message is a string encoded using + quoted printable. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + The result must be freed with + mmap_string_unref(). + + + + + + Parsing a quoted printable encoded part + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size, + &current_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_binary_body_parse + + +#include <libetpan/libetpan.h> + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + + + + This function will parse a body part encoded using binary + (no encoding). + + + + + + message is a string encoded using + binary. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + result. The result of the parse + operation is stored in (* result) + The result must be freed with + mmap_string_unref(). + + + + + + Parsing a binary encoded part + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_binary_body_parse(mem, stat_info.st_size, + &current_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + mailmime_part_parse + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + + + This function will parse a body part encoded using a + given MIME encoding mechanism. + + + + + + message is a string encoded using + binary. + + + + + length is the size of the given + string. + + + + + index is a pointer to the start of + the address in the given string, (* + index) is modified to point at the end of the + parsed data. + + + + + encoding is a MIME encoding + mechanism. The value can be + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64 or + MAILMIME_MECHANISM_TOKEN + (see ). + + + + + result. The result of the parse + operation is stored in (* result) + The result must be freed with + mmap_string_unref(). + + + + + + Parsing a MIME encoded part + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_part_parse(mem, stat_info.st_size, &current_index, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + Rendering of MIME parts + + + + mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write + + +#include <libetpan/libetpan.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + + + + mailmime_fields_write render the MIME + header fields. + + + + mailmime_content_write render the MIME + content type header field. + + + + mailmime_content_write render the + content of the MIME content type header field. + + + + + + col current column is given for wrapping + purpose in (* col), + the resulting columns will be returned.. + + + + + f is the file descriptor. It can be + stdout for example. + + + + + fields is the header fields + (see ). + + + + + content is the header fields + (see ). + + + + + + rendering MIME header fields + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mime * mime_fields; + int col; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + col = 0; + mailmime_fields_write(stdout, &col, mime_fields); + + mailmime_fields_free(mime_fields); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_type_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + + + + + + + mailmime_write + + +#include <libetpan/libetpan.h> + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + + + + This function will render a MIME message. + + + + + + col current column is given for wrapping + purpose in (* col), + the resulting columns will be returned.. + + + + + f is the file descriptor. It can be + stdout for example. + + + + + build_info is the MIME message to + render. + + + + + + + + + mailmime_quoted_printable_write + and mailmime_base64_write + + +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + + + + mailmime_quoted_printable_write() will + render a string to quoted printable. + + + + mailmime_base64_write() will + render a string to base64. + + + + + + col current column is given for wrapping + purpose in (* col), + the resulting columns will be returned.. + + + + + f is the file descriptor. It can be + stdout for example. + + + + + text is the string to render. + + + + + size is the size of the string to + render. + + + + + + render base64 or quoted printable + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_quoted_printable_write(stdout, &col, + "this is a test", 14); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_base64_write(stdout, &col, "this is a test", 14); +} + + + + + + + mailmime_data_write + + +#include <libetpan/libetpan.h> + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + + + + mailmime_data_write will + render MIME data. + + + + + + col current column is given for wrapping + purpose in (* col), + the resulting columns will be returned.. + + + + + f is the file descriptor. It can be + stdout for example. + + + + + data is the data to render + (see ). + + + + + + + + + Creation functions + + + + mailmime_disposition_new_filename and + mailmime_disposition_new_with_data + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + + + + These functions will create a MIME content disposition + information. + + + + + + type a standard MIME disposition : + MAILMIME_DISPOSITION_TYPE_INLINE or + MAILMIME_DISPOSITION_TYPE_ATTACHMENT. + + + filename is the filename. + + + creation_date is the creation date. + + + modification_date is the modification + date. + + + read_date is the last read date. + + + size is the size of the file. + + + + + This will return a MIME content disposition + (see ). + + + + + + creating a MIME content disposition + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + + + + + + + mailmime_fields_new_empty and mailmime_fields_add + + +#include <libetpan/libetpan.h> + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + + + + mailmime_fields_new_empty() will + create a new empty MIME header fields list. + + + + mailmime_fields_add() will add + MIME header fields to the MIME header fields list. + + + + + + fields. The MIME header field will + be added to this MIME header fields list + (see ). + + + + + field is the MIME header field to add + (see ). + + + + + + creating a MIME header fields list + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_fields * fields; + struct mailmime_field * field; + + fields = mailmime_fields_new_empty(); + field = build_mime_field(); + + /* do the things */ + + mailmime_fields_add(fields, field); + + mailmime_fields_free(fields); +} + + + + + + + mailmime_fields_new_with_data and + mailmime_fields_new_with_version + + +#include <libetpan/libetpan.h> + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + + + + mailmime_fields_new_with_data() will + create a MIME header fields list with all the given fields + (NULL can be used for the value if the + field must not be present). + MIME-Version header field will + not be added. + + + + mailmime_fields_new_with_version() will + create a MIME header fields list with all the given fields + (NULL can be used for the value if the + field must not be present). + MIME-Version header field will be added. + + + + creating new fields + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_fields * mime_fields; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + mime_fields = mailmime_fields_new_with_version(encoding, NULL, + NULL, disposition, NULL); + + /* do the things */ + + mailmime_fields_free(mime_fields); +} + + + + + + + mailmime_get_content_message + + +#include <libetpan/libetpan.h> + +struct mailmime_content * mailmime_get_content_message(void); + +struct mailmime_content * mailmime_get_content_text(void); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + + + + mailmime_get_content_message() will + create a MIME content type + message/rfc822. + + + + mailmime_get_content_text() will + create a MIME content type + plain/text. + + + + mailmime_get_content_new_with_str() will + create a MIME content type given by the string + plain/text. + + + + str. This string will + NOT be referenced by any structure. + This string will only be parsed to create the structure. + + + + Creating a MIME content type + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_message(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_new_with_str("multipart/mixed"); + + /* do the things */ + + mailmime_content_free(content); +} + + + + + + + mailmime_data_new_data and mailmime_data_new_file + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + + + + mailmime_data_new_data() will create a + new MIME content, using a string in memory. + + + + mailmime_data_new_file() will create a + new MIME content, using a file. + + + + + + encoding is the MIME encoding + mechanism used to encode this part. The value can be + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE or + MAILMIME_MECHANISM_BASE64 + (see ). + + + + + encoded is set to 1 if the part is + already encoded with the mechanism given in + encoding. + + + + + data is a pointer to the + content of the part. + + + + + length is the length of the data. + + + + + filename is the name of the file. + + + + + + creating MIME content + + +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0, + DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_data_free(data); +} + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + + + + + + + mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content + + +#include <libetpan/libetpan.h> + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +struct mailmime * mailmime_multiple_new(const char * type); + + + + mailmime_new_message_data() will create a + new MIME message with the given subpart. + + + + mailmime_new_empty() will create a + new MIME part with the given content type and MIME fields + but with no content. + + + + mailmime_new_with_content() will create a + new MIME part with a content type given by a string and a + given MIME fields list. + + + + mailmime_multiple_new() will create a + new MIME multipart with a content type given by a string. + + + + + + msg_mime is the sub part to add to the + MIME message when creating it + (see ). + + + + + content is the content type of the part + to create + (see ). + + + + + content_type is the content type of + the part to create given by a string. + + + + + mime_fields is the list of MIME + header fields + (see ). + + + + + + creating a MIME part + + +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &single_part); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + struct mailmime_content * content; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + content = mailmime_get_content_text(); + single_part = mailmime_new_empty(content, mime_fields); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + /* do the things */ + + mailmime_free(mime); +} + + + + + + + mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text + + +#include <libetpan/libetpan.h> + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + + + + mailmime_set_preamble_file() will define + the preamble of a multipart. + + + + mailmime_set_preamble_text() will define + the preamble of a multipart. + + + + mailmime_set_epilogue_file() will define + the epilogue of a multipart. + + + + mailmime_set_preamble_text() will define + the preamble of a multipart. + + + + + + build_info is the MIME part to modify + (see ). + + + + + data_str is the string to define + as epilogue or prologue. + + + + + length is the length of the string to + define as epilogue or prologue. + + + + + filename is the name of the file + which content will be defined as epilogue or prologue. + + + + + + setting preamble and epilogue + + +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + mailmime_set_preamble_file(mime, strdup("foo-bar.txt")); + + mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_free(mime); +} + + + + + + + mailmime_set_body_file and mailmime_set_body_text + + +#include <libetpan/libetpan.h> + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + + + + mailmime_set_body_file() will define + the body of a single part. + + + + mailmime_set_body_text() will define + the body of a single part. + + + + + + build_info is the MIME part to modify + (see ). + + + + + data_str is the string to define + as the body of the part. + + + + + length is the length of the string to + define as the body of the part. + + + + + filename is the name of the file + which content will be defined as the body of the part. + + + + + + creating a MIME part + + +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + + + /* do the things */ + + mailmime_free(mime); +} + + + + + + + + mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part + + +#include <libetpan/libetpan.h> + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + + + + mailmime_add_part() will add a sub MIME + part. + + + + mailmime_remove_part() will detach the + given sub part from its parent. + + + + mailmime_smart_add_part() will add a sub + MIME part. If the parent part is a message and no child + exist, the part is set as the child. If the parent part is a + message and a child already exists, if the child is + multipart, the part to add is added as child of this + multipart, else a multipart is added and the part is added + as child of the multipart. + + + + mailmime_smart_remove_part() will detach + the given sub part from its parent. The sub part will be + freed. + + + + + + build_info is the parent MIME part + (see ). + + + + + part is the part to add + (see ). + + + + + mime is the parent MIME part + (see ). + + + + + mime_sub is the part to add or to + detach + (see ). + + + + + + modifying MIME structure + + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime * other_sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + sub_mime = mailmime_new_empty(content, mime_fields); + + content = mailmime_get_content_text(); + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + other_sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_smart_add_part(mime, sub_mime); + mailmime_smart_add_part(mime, other_sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(sub_mime); + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_smart_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(mime); +} + + + + + + + mailmime_set_imf_fields + + +#include <libetpan/libetpan.h> + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + + + mailmime_set_imf_fields() will set the + fields of the given MIME message. + + + + + + build_info is the MIME message to + modify + (see ). + + + + + fields is the header fields to set + for the message + (see ). + + + + + + modifying MIME structure + + +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime_fields * mime_fields; + struct mailimf_fields * imf_fields; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + + mailmime_new_with_content("text/plain", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + imf_fields = build_fields(); + + mailmime_set_imf_fields(mime, imf_fields); + + /* do the things */ + + mailmime_free(mime); +} + + + + + + + mailmime_fields_new_encoding and + mailmime_fields_new_filename + + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + + + + mailmime_fields_new_encoding() will + create a list of MIME header fields with only + Content-Transfer-Encoding. + + + + mailmime_fields_new_filename() will + create a list of MIME header fields with + Content-Transfer-Encoding and + Content-Disposition. + + + + The result will be a list of MIME header fields + (see ). + + + + + + encoding_type is the MIME encoding + mechanism. The value can be + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE or + MAILMIME_MECHANISM_BASE64 + (see ). + + + + + dsp_type is the disposition type. + The value can be + MAILMIME_DISPOSITION_TYPE_INLINE or + MAILMIME_DISPOSITION_TYPE_ATTACHMENT + (see ). + + + + + filename is the filename for MIME + content disposition. + + + + + + creating MIME fields with only Content-Transfer-Encoding + + +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_fields * fields; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + +int main(void) +{ + struct mailmime_fields * fields; + + fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + + + + + + + + Helper functions + + + + mailmime_transfer_encoding_get + + +#include <libetpan/libetpan.h> + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + + + + mailmime_transfer_encoding_get() will + return the standard MIME encoding mechanism. + + + + + + fields is the list of MIME header + fields. + + + + + An integer representing the MIME encoding mechanism will + be returned + (see ). + + + + + + extracting MIME encoding mechanism + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + int encoding; + + encoding = mailmime_transfer_encoding_get(mime_fields); + + /* do the things */ + + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + mailmime_content_charset_get and + mailmime_content_param_get + + +#include <libetpan/libetpan.h> + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + + + mailmime_content_charset_get() will + return the charset parameter of + MIME content type. + + + + mailmime_content_param_get() will + return the value of a given parameter of + MIME content type. + + + + mailmime_extract_boundary() will + return the charset parameter of + MIME content type. + + + + + + content is the MIME content type. + + + + + name is the name of the parameter to + extract. + + + + + With mailmime_extract_boundary(), the + returned value must be freed with + free(). + + + + + + extracting information from MIME content type + + +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + &current_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + &current_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + char * charset; + char * name; + char * boundary; + + charset = mailmime_content_charset_get(content_type); + name = mailmime_content_param_get(content_type, "name"); + boundary = mailmime_extract_boundary(content_type); + + /* do the things */ + + free(boundary); + + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + + + + + + + + Storages, folders, messages + + + + Introduction + + + This part will give the definition of some objects. + + + + Message + + + A message is the common e-mail message or news message you + read or send. + + + + + MIME part + + + A message can have attachment such as images or other documents. + The attachment are organized into a tree structure. Each + node of this structure is a MIME part. + + + + + Mailbox + + + A mailbox will contain a given number of messages. + + + + + Storage + + + A storage is a "physical" localisation of your mailbox. This + can be on a filesystem (local or remote disk, this is the + case of MH, mbox and maildir), or this can be on a remote + host (this is the case for POP3, IMAP or NNTP). + + + + + Folder + + + A storage, for the same user, can contain a given number of + mailboxes, depending the storage capabilities, then, the + storage driver capabilities. With etPan!, MH, IMAP and NNTP + storages can have more than one mailbox. The mailboxes will + be called folders. On storage where we only have one + mailbox, the unique mailbox is the unique folder. + + + + + Session + + + The session is the network connection or the entity to which + the commands of the drivers are given. + + + + + + Error codes + + + Error codes returned as integers can be one of the following : + + + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + + + + + + Storage + + + Storage driver + + +#include <libetpan/libetpan.h> + +typedef struct mailstorage_driver mailstorage_driver; + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + + + + This is the driver for a storage. + + + + + + sto_name is the name of the driver. + + + + + sto_connect() connects the storage to + the remote access or to the path in the local filesystem. + + + + + sto_get_folder_session() can have two + kinds of behaviour. Either it creates a new session and + independant from the session used by the storage and + select the given mailbox or it selects the given mailbox + in the current session. It depends on the efficiency of + the mail access. + + + XXX - in the future, this will be moved to the + folder driver + + + + + sto_uninitialize() frees the data + created with mailstorage constructor. + + + + + + + Storage + + +#include <libetpan/libetpan.h> + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + + + + sto_id is an identifier for the + storage. This can be NULL. + + + + + sto_data is the internal data + of the storage. This can only be changed by the driver. + + + + + sto_session is the session used by + the storage. The session can be used to send commands. + + + + + sto_driver is the driver of the + storage. + + + + + sto_shared_folders is the list of + folders that share the session with the storage. + This is used internally. + + + + + sto_user_data is a field for free + use. The user can store any data in that field. + + + + + + + mailstorage_new and mailstorage_free + + +#include <libetpan/libetpan.h> + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + + + + mailstorage_new() initializes a storage + structure with an identifier (sto_id) and + with no driver. + + + + mailstorage_free() free the memory used + by a storage. + + + + + mailstorage_connect and mailstorage_disconnect + + +#include <libetpan/libetpan.h> + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + + + + mailstorage_connect() connects the storage. + This function can also be used to confirm that a storage + connection is valid when the storage is already connected. + + + + mailstorage_disconnect() disconnects the + storage. + + + + + IMAP storage + + +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + + + + + Example + + + use of storage + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + + + + + + + Folder + + + Folder driver + + +#include <libetpan/libetpan.h> + +typedef struct mailfolder_driver mailfolder_driver; + +struct mailfolder_driver { + int (* fld_get_session)(struct mailfolder * folder, + mailsession ** result); + + int (* fld_noop)(struct mailfolder * folder); + + int (* fld_check)(struct mailfolder * folder); + + int (* fld_expunge)(struct mailfolder * folder); + + int (* fld_status)(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + int (* fld_append_message)(struct mailfolder * folder, + char * message, size_t size); + + int (* fld_get_messages_list)(struct mailfolder * folder, + struct mailmessage_list ** result); + + int (* fld_get_envelopes_list)(struct mailfolder * folder, + struct mailmessage_list * result); + + int (* fld_get_message)(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + int (* fld_get_message_by_uid)(struct mailfolder * folder, + const char * uid, mailmessage ** result); +} + + + + XXX - this will be implemented in the future. + + + + + + fld_get_session() will return the session + this folder should use. + + + + + For other method, you should see . + + + + + + + Folder + + +#include <libetpan/libetpan.h> + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + + + + + + fld_pathname is the pathname specific to + the driver. + + + + + + fld_virtual_name is the identifier of + this folder. This can be NULL. + + + + + + fld_storage is the storage used for this + folder (see ). + + + + + + fld_session is the session used for this + folder. + + + + + + fld_shared_session is set to 1 if the + folder use the same session as the storage. This is used + internally. + + + + + + fld_pos is the + position in the list of folders of the storage. + This is used internally. + + + + + + use of fld_parent, + fld_sibling_index and + fld_children is deprecated. + + + + + + fld_user_data is a field for free + use. The user can store any data in that field. + + + + + + + mailfolder_new and mail_folder_free + + +#include <libetpan/libetpan.h> + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + + + + mailfolder_new() initializes a folder + structure with an identifier + (fld_virtual_name) with path name + (fld_pathname). The folder will be owned + by the given storage (fld_storage). + + + + mailfolder_free() free the memory used + by the folder. + + + + + mailfolder_connect and mailfolder_disconnect + + +#include <libetpan/libetpan.h> + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + + + + mailfolder_connect() connects the folder. + This function can also be used to confirm that a folder + connection is valid when the folder is already connected. + When doing operations with several folders, you have to be + sure that this function has been called before making calls + on folder. + + + + mailfolder_disconnect() disconnects the + folder. + + + + + mailfolder_noop + + +#include <libetpan/libetpan.h> + +int mailfolder_noop(struct mailfolder * folder); + + + + This function will only send noop to the mail access. + + + + + mailfolder_check + + +#include <libetpan/libetpan.h> + +int mailfolder_check(struct mailfolder * folder); + + + + A call to this function will save to disk the internal state + of the selected mailbox (such as flags). + + + + + mailfolder_expunge + + +#include <libetpan/libetpan.h> + +int mailfolder_expunge(struct mailfolder * folder); + + + + A call to this function will delete all messages marked for + deletion. + + + + + mailfolder_status + + +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + + + A call to this function will return some counts of messages + in the mailbox. + + + + + mailfolder_append_message + + +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + + + + This function will store a new message in the given folder. + The message is given by a string in memory + (message) and a size + (size). + + + + + mailfolder_get_messages_list + + +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + + + + This function will return the list of messages in the given + folder (see ). + + + + + mailfolder_get_envelopes_list + + +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + + + + This function will fill the list of parsed header fields + structure in the mailmessage structures + of the given list of messages (result). + + + + + mailfolder_get_message + + +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + + + This function will return the message identified by a + message index (num) + This will return a mailmessage structure + in (* result) (see ). + + + + + mailfolder_get_message_by_uid + + +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + + + + This function will return the message identified by a + unique identifier (uid) + This will return a mailmessage structure + in (* result) (see ). + + + + + Example + + + use of folder + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + + mailfolder_get_messages_list(folder, &msg_list); + + /* do the things */ + + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + + + + + + + + Message + + + Message driver + + +#include <libetpan/libetpan.h> + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + + + + + msg_name is the name of the driver. + + + + + + msg_initialize() will initialize the + internal message state (field + msg_data of + mailmessage structure (see ). + + + + + + msg_uninitialize() will free the + internal message state. + + + + + + msg_flush() will release memory used + by the MIME structure of the message. + + + + + + msg_check() will store the flags of + the message into the session, so that the message can be + released without the flags are lost. + + + + + + msg_fetch_result_free() will free a + string returned by any fetch_XXX() function. + + + + + + msg_fetch() will fetch a message. + + + + + + msg_fetch_header() will fetch the + header fields of a message. + + + + + + msg_fetch_body() will fetch a message + without its main header. + + + + + + msg_fetch_size() will return the size + of a message. + + + + + + msg_get_bodystructure will retrieve + the MIME structure of the message. The returned + structure must NOT be freed. + + + + + + msg_fetch_section() will fetch the + content of the section of the message. + + + + + + msg_fetch_section_header() will fetch + the header of a section of the message if the content of + the section is a message. + + + + + + msg_fetch_section_mime() will fetch + the MIME header of a section of the message. + + + + + + msg_fetch_section_body() will fetch + the body of a section (without the headers) of the + message if the content of the section is a message. + + + + + + msg_fetch_envelope() will return + a given number of parsed header fields. + + + + + + msg_get_flags() will return the + flags of the message. + The returned structure must NOT be + freed. + + + + + + + Message + + +#include <libetpan/libetpan.h> + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + + + + + msg_session is the session related to + the message + (see ). + + + + + + msg_driver is the driver used for the + message + (see ). + + + + + + msg_index is an index to indentify + the message. + + + + + + msg_uid is the unique identifier of + the message, valid accross disconnections. + + + + + + msg_size is the size of the message. + + + + + + msg_fields is the list of parsed + header fields of the message. This can be + NULL + (see ). + + + + + + msg_flags is the flags of the + message. This can be NULL + (see ). + + + + + + msg_resolved will tell if the field + msg_single_fields has been initialized. + + + + + + msg_single_fields will be filled + using msg_fields + (see ). + + + + + + msg_mime is the MIME structure of the + message. It is intialized at least when + get_bodystructure() is called once. + + + + + + msg_cached is 1 when the message was + cached. This is used internally. + + + + + + msg_data is the internal state of the + message. The content depends on the driver. + + + + + + msg_folder is used to reference the + mailfolder, this is a workaround due to the problem with + initial conception, where folder notion did not exist. + + + + + + msg_user_data is a field for free + use. The user can store any data in that field. + + + + + + + mailmessage_new + + +#include <libetpan/libetpan.h> + +mailmessage * mailmessage_new(void); + +void mailmessage_free(mailmessage * info); + + + + mailmessage_new() will create a new + message (without driver). This is used internally by + drivers. + + + + mailmessage_free() will free the memory + used by the given message. + + + + + mailmessage_init + + +#include <libetpan/libetpan.h> + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + + + + mailmessage_init() will initialize a + message with a driver. + + + + + + msg_info is the message to initialize + (see ). + + + + + + session is the session related to the + message + (see ). + + + + + + driver is the driver to use for the + message + (see ). + + + + + + index is the index of the message. + + + + + + size is the size of the message. + + + + + + + mailmessage_flush + + +#include <libetpan/libetpan.h> + +int mailmessage_flush(mailmessage * info); + + + + This function will release the memory used by the MIME + structure of the message. + + + + + mailmessage_check + + +#include <libetpan/libetpan.h> + +int mailmessage_check(mailmessage * info); + + + + After you set some flags, if you want to notify them to the + session before destroying the message, you can use this function. + + + + + mailmessage_fetch_result_free + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + + + + This function will free a string returned by any + mailmessage_fetch_XXX() function. + + + + + mailmessage_fetch + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + + + + This function returns the content of the message (headers + and text). + + + + + mailmessage_fetch_header + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + + + + This function returns the header of the message as a string. + + + + + + mailmessage_fetch_body + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + + + + This function returns the content of the message (without + headers). + + + + + mailmessage_fetch_size + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + + + + This function returns the size of the message content. + + + + + mailmessage_get_bodystructure + + +#include <libetpan/libetpan.h> + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + + + + This functions returns the MIME structure of the message. + The returned information MUST not be + freed by hand. It is freed by + mailmessage_flush() or + mailmessage_free() + (see ). + + + + + mailmessage_fetch_section + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + + + This function returns the content of a MIME part. + + + + + mailmessage_fetch_section_header + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + + This function returns the header of the message contained + in the given MIME part. + + + + + mailmessage_fetch_section_mime + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + + This function returns the MIME header of the given MIME + part. + + + + + mailmessage_fetch_section_body + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + + This function returns the text part of the message contained + in the given MIME part. + + + + + mailmessage_fetch_envelope + + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + + + + mailmessage_get_flags + + +#include <libetpan/libetpan.h> + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + + + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + + + + mailmessage_resolve_single_fields + + +#include <libetpan/libetpan.h> + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + + + + This function will use the fields information to fill + the single_fields structure in the mailmessage structure. + + + + + Message list + + +#include <libetpan/libetpan.h> + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +void mailmessage_list_free(struct mailmessage_list * env_list); + + + + This is a list of messages. + + + + msg_tab is an array containing the + messages (see linkend="carray"). + + + + mailmessage_list_new() will initialize a + list of messages, using a given array of messages. + + + + mailmessage_list_free() will free the + memory used by the list of messages. This will also free the + messages. + + + + + Message tree + + +#include <libetpan/libetpan.h> + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + + + This is a node of a tree of messages. + + + + + + node_parent is the parent of this + node. + + + + + + node_msgid is the content of the + field Message-ID of the message. + + + + + + node_date is the date in UNIX + format. + + + + + + node_msg is the message of the node. + The message should have the msg_fields + field initialized. + + + + + + node_children is the list of + children of this node. + + + + + + node_is_reply is set to 1 if the + message is a reply. + + + + + + node_base_subject is the base subject + of the message (base subject is defined in definition of + IMAP thread draft). + + + + + + mailmessage_tree_new() will initialize a + message node. + + + + mailmessage_tree_free() will release + memory used by the node. This will NOT + free the message. + + + + + Message flags + + +#include <libetpan/libetpan.h> + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +void mail_flags_free(struct mail_flags * flags); + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + + + + This is the structure containing the message flags. + + + + + + fl_flags will contain the standards + flags. The value will be a combinaison (with or binary + operation) of MAIL_FLAG_XXX values. + + + + + fl_extension will be a list (see + ) of strings representing the + non-standard flags. + + + + + + + Example + + + use of message + + +#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, + &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_envelopes_fields_parse(data, len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, + "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, + "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = mailimf_fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, + mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + mailmessage * msg; + + mailfolder_get_messages_list(folder, &msg_list); + + if (carray_count(msg_list->msg_tab) > 0) { + struct mailmime * mime; + + msg = carray_get(msg_list->msg_tab, 0); + + mailmessage_get_bodystructure(msg, &mime); + + recursive_fetch(msg, mime); + + /* do the things */ + + mailmessage_flush(msg); + } + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + + + + + + + Session + + + Session driver + + +#include <libetpan/libetpan.h> + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +}; + + + + This is a driver for a session. + + + + + + sess_name is the name of the driver. + + + + + + sess_initialize() is the function + that will initializes a data structure (field + sess_data in the session) specific to + the driver. + The field data (field sess_data in + the session) is the state of the session, + the internal data structure used by the driver. + It is called when creating the + mailsession structure with + mailsession_new(). + + + + + + sess_uninitialize() frees the structure + created with sess_initialize() + + + + + + sess_parameters() implements + functions specific to the given mail access. + + + + + + sess_connect_stream() connects a + stream to the session. + + + + + + sess_connect_path() notify a main + path to the session. + + + + + + sess_starttls() changes the current + stream to a TLS stream + (see ). + + + + + + sess_login() notifies the user and + the password to authenticate to the session. + + + + + + sess_logout() exits the session and + closes the stream. + + + + + + sess_noop() does no operation on the + session, but it can be used to poll for the status of + the connection. + + + + + + sess_build_folder_name() will return an + allocated string with that contains the complete path of + the folder to create. + Use of this method is deprecated. + + + + + + sess_create_folder() creates the + folder that corresponds to the given name. + Use of this method is deprecated. + + + + + + sess_delete_folder() deletes the folder + that corresponds to the given name. + Use of this method is deprecated. + + + + + + sess_rename_folder() change the name + of the folder. + Use of this method is deprecated. + + + + + + sess_check_folder() makes a + checkpoint of the session. + + + + + + sess_examine_folder() selects a mailbox as + readonly. + Use of this method is deprecated. + + + + + + sess_select_folder() selects a mailbox. + + + + + + sess_expunge_folder() deletes all + messages marked \Deleted. + + + + + + sess_status_folder() queries the + status of the folder (number of messages, number of + recent messages, number of unseen messages). + + + + + + sess_messages_number() queries the + number of messages in the folder. + + + + + + sess_recent_number() queries the + number of recent messages in the folder. + + + + + + sess_unseen_number() queries the number of + unseen messages in the folder. + + + + + + sess_list_folders() returns the list of + all sub-mailboxes of the given mailbox. + Use of this method is deprecated. + + + + + + sess_lsub_folders() returns the list of + subscribed sub-mailboxes of the given mailbox. + Use of this method is deprecated. + + + + + + sess_subscribe_folder() subscribes to + the given mailbox. + Use of this method is deprecated. + + + + + + sess_unsubscribe_folder() unsubscribes to + the given mailbox. + Use of this method is deprecated. + + + + + + sess_append_message() adds a RFC 2822 + message to the current given mailbox. + + + + + + sess_copy_message() copies a message + whose number is given to a given mailbox. The mailbox + must be accessible from the same session. + Use of this method is deprecated. + + + + + sess_move_message() moves a message whose + number is given to + a given mailbox. The mailbox must be accessible from the + same session. + Use of this method is deprecated. + + + + + + sess_get_messages_list() returns the list + of message numbers + of the current mailbox + (see ). + + + + + + sess_get_envelopes_list() fills the parsed + fields in the mailmessage structures + (see ) + of the mailmessage_list + (see ). + + + + + + sess_remove_message() removes the given + message from the mailbox. + The message is permanently deleted. + Use of this method is deprecated. + + + + + + sess_get_message() returns a + mailmessage structure + (see ) + that corresponds + to the given message number. + Use of this method is deprecated. + + + + + + sess_get_message_by_uid() returns a + mailmessage structure + (see ) + that corresponds + to the given message unique identifier. + + + + + + mandatory functions are the following : + + + + + + sess_connect_stream() or + connect_path() + + + + + + sess_logout() + + + + + + sess_get_messages_list() + + + + + + sess_get_envelopes_list() + + + + + + we advise you to implement these functions : + + + + + + sess_select_folder() (in case a session + can access several folders). + + + + + + sess_noop() (to check if the server is + responding) + + + + + + sess_check_folder() (to make a checkpoint + of the session) + + + + + + sess_status_folder(), + sess_messages_number(), + sess_recent_number(), + sess_unseen_number() + (to get stat of the folder) + + + + + + sess_append_message() (but can't be done + in the case of POP3 at least). + + + + + + sess_login() in a case of an + authenticated driver. + + + + + + sess_starttls() in a case of a stream + driver, if the procotol supports STARTTLS. + + + + + + sess_get_message_by_uid() so that the + application can remember the messages + by UID and build its own list of messages. + + + + + + Everything that is specific to the driver will be + implemented in sess_parameters(). + + + + + + + Session + + +#include <libetpan/libetpan.h> + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +void mailsession_free(mailsession * session); + + + + This is a session. This is an abstraction used to access the + storage, using the network or the filesystem. + + + + + + sess_data is the state of the + session. This is specific to the driver. + + + + + sess_driver is the driver of the + session. + + + + + + mailsession_new() will create a new session + using the given driver (sess_driver). + + + + mailsession_free() will release the memory + used by the session. + + + + + mailsession_parameters + + +#include <libetpan/libetpan.h> + +int mailsession_parameters(mailsession * session, + int id, void * value); + + + + This function make calls specific to the driver + + + + + mailsession_connect_stream + + +#include <libetpan/libetpan.h> + +int mailsession_connect_stream(mailsession * session, mailstream * s); + + + + There are drivers of two kinds : stream drivers (driver that + connects to servers through TCP or other means of connection) + and file drivers (driver that are based on filesystem) + + This function can only be used by stream drivers and + this connects a stream to the session + + + + + mailsession_connect_path + + +#include <libetpan/libetpan.h> + +int mailsession_connect_path(mailsession * session, char * path); + + + + This function can only be used by file drivers and + selects the main path of the session. + + + + + mailsession_starttls + + +#include <libetpan/libetpan.h> + +int mailsession_starttls(mailsession * session); + + + + This switches the current connection to TLS (secure layer). + This will only work with stream drivers. + + + + + mailsession_login + + +#include <libetpan/libetpan.h> + +int mailsession_login(mailsession * session, + char * userid, char * password); + + + + This notifies the login and the password to authenticate + to the session. + + + + + mailsession_logout + + +#include <libetpan/libetpan.h> + +int mailsession_logout(mailsession * session); + + + + This function disconnects the session and closes the stream. + + + + + mailsession_noop + + +#include <libetpan/libetpan.h> + +int mailsession_noop(mailsession * session); + + + + This function does no operation on the session, but it can be + used to poll for the status of the connection. + + + + + mailsession_check_folder + + +#include <libetpan/libetpan.h> + +int mailsession_check_folder(mailsession * session); + + + + This function makes a checkpoint of the session. + + + + + mailsession_select_folder + + +#include <libetpan/libetpan.h> + +int mailsession_select_folder(mailsession * session, char * mb); + + + + This function selects a mailbox. + + + + + mailsession_expunge_folder + + +#include <libetpan/libetpan.h> + +int mailsession_expunge_folder(mailsession * session); + + + + This function deletes all messages marked for deletion. + + + + + mailsession_status_folder + + +#include <libetpan/libetpan.h> + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + + + This function queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages). + + + + + mailsession_messages_number + + +#include <libetpan/libetpan.h> + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + + + + This function queries the number of messages in the folder. + + + + + mailsession_recent_number + + +#include <libetpan/libetpan.h> + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + + + + This function queries the number of recent messages in the + folder. + + + + + mailsession_unseen_number + + +#include <libetpan/libetpan.h> + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + + + + This function queries the number of unseen messages in the + folder. + + + + + mailsession_append_message + + +#include <libetpan/libetpan.h> + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + + + + This adds a RFC 2822 message to the current mailbox. + + + + + mailsession_get_messages_list + + +#include <libetpan/libetpan.h> + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + + + + This function returns the list of messages + of the current mailbox. + + + + + mailsession_get_envelopes_list + + +#include <libetpan/libetpan.h> + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + + + + This function fills the parsed fields in the + mailmessage structures + (see ) + of the mailmessage_list + (see ). + + + + + mailsession_get_message + + +#include <libetpan/libetpan.h> + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + + + + This function returns a mailmessage + (see ) structure that + corresponds to the given message number. + + + + + mailsession_get_message_by_uid() should + be used instead. + + + + + + mailsession_get_message_by_uid + + +#include <libetpan/libetpan.h> + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + + + + This function returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + + + + That deprecates the use of + mailsession_get_message(). + + + + + + + diff --git a/kmicromail/libetpan/doc/DOCUMENTATION b/kmicromail/libetpan/doc/DOCUMENTATION new file mode 100644 index 0000000..4f66519 --- a/dev/null +++ b/kmicromail/libetpan/doc/DOCUMENTATION @@ -0,0 +1,654 @@ +1/ Introduction +--------------- + +libEtPan! is mainly a library that will handle all kind of mailbox access. +For example: IMAPrev4, POP3, NNTP, mbox, MH. + +You have two kinds of mailbox access, either using low-level functions +with a different interface for each kind of access or using higher-level +functions, using a driver to wrap the higher-level API. + + +2/ Low-level +------------ + +2.1/ IMAP4rev1 - Internet Message Access Protocol - Version 4rev1 +----------------------------------------------------------------- + +Each command of the IMAP4rev1 Standard (RFC 2060) is implemented in +the IMAP4rev1 module. Directory imap/. + +2.1.1/ References + +- RFC 2060 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 +- draft-crispin-imapv-15.txt + +Not yet implemented : + +- draft-crispin-imapv-20.txt + +2.1.2/ Dependencies + +- tools/ + +2.1.3/ Files descriptions + +description of header files : +mailimap.[ch] -- functions that implements each IMAP4rev1 command +mailimap_helper.[ch] -- helper interface for the previous functions +mailimap_types.[ch] -- definition of types and constructors for these + types +mailimap_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use IMAP4rev1 module +mailimap_socket.[ch] -- provides a function to connect to an + IMAP4rev1 server over TCP +mailimap_ssl.[ch] -- provides a function to connect to an + IMAP4rev1 server over TLS layer + +2.1.4/ Interface + +Include for this module is mailimap.h and includes all other headers. + + +The interface of IMAP4rev1 is documented in the following files : + +mailimap.h +mailimap_types.h +mailimap_types_helper.h + + +2.2/ POP3 - Post Office Protocol - Version 3 +-------------------------------------------- + +Each command of the POP3 Standard (RFC 1939 and RFC 2449) is implemented +in the POP3 module. Directory pop3/. + +2.1.1/ References + +- RFC 1939 - Post Office Protocol - Version 3 +- RFC 2449 - POP3 Extension Mechanism (CAPA) + +Not yet implemented : + +- RFC 1734 - POP3 AUTHentication command + +2.1.2/ Dependencies + +- tools/ + +2.2.3/ Files descriptions + +mailpop3.[ch] -- functions that implements each POP3 command +mailpop3_helper.[ch] -- helper interface for the previous functions +mailpop3_socket.[ch] -- provides a function to connect to a + POP3 server over TCP +mailpop3_ssl.[ch] -- provides a function to connect to a + POP3 server over TLS layer + +2.2.4/ Interface + +Include for this module is mailpop3.h and includes all other headers. + +There is not yet documentation for POP3 module. + + +2.3/ NNTP - Network News Transfer Protocol +------------------------------------------ + +Each command of the NNTP Standard (RFC 977 and RFC 2980) is implemented +in the NNTP module. Directory nntp/. + +2.3.1/ References + +- RFC 977 - Network News Transfer Protocol +- RFC 2980 - Common NNTP Extensions + +Not yet implemented : + +- RFC 1036 - Standard for Interchange of USENET Messages +- son of RFC 1036 : FTP://zoo.toronto.edu/pub/news.txt.Z + +2.3.2/ Dependencies + +- tools/ + +2.3.3/ Files descriptions + +newsnntp.[ch] -- functions that implements each NNTP command +newsnntp_socket.[ch] -- provides a function to connect to a + NNTP server over TCP +newsnntp_ssl.[ch] -- provides a function to connect to a + POP3 server over TLS layer + +2.3.4/ Interface + +Include for this module is newsnntp.h and includes all other headers. + +There is not yet documentation for NNTP module. + + +2.4/ mbox +--------- + +The mbox module provides a set of functions to manipulate mbox mailboxes. +These functions make a safe lock on the mailbox they work with. +This module will assign to each message a unique message identifier +so that we can work with message numbers in mbox files without other +programs interfer. +Directory mbox/. + +2.4.1/ References + +- http://wp.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html +- http://www.qmail.org/qmail-manual-html/man5/mbox.html + +2.4.2/ Dependencies + +- tools/ +- imf/ + +2.5.3/ Specific to libEtPan! + +- "X-LibEtPan-UID" header + +2.5.4/ Files descriptions + +mailmbox.[ch] -- functions to manipulate mbox mailboxes. +mailmbox_parse.[ch] -- this module is in charge of parsing the + mbox file content +mailmbox_types.[ch] -- definition of types and constructors for these + types + +2.4.5/ Interface + +Include for this module is mailmbox.h and includes all other headers. + +There is not yet documentation for mbox module. + + +2.5/ MH +------- + +The MH module provides a set of functions to manipulate MH mailboxes. +Directory mh/. + +2.5.1/ References + +- almost none + +2.5.2/ Dependencies + +- tools/ + +2.5.3/ Files descriptions + +mailmh.[ch] -- functions to manipulate MH mailboxes. + + +2.5.4/ Interface + +Include for this module is mailmh.h. + +There is not yet documentation for MH module. + + +2.6/ IMF - Internet Message Format +---------------------------------- + +The IMF module provides functions to parse data given in RFC 2822 +format (Internet Message Format). +Directory imf/. + +2.6.1/ References + +- RFC 2822 - Internet Message Format (Not entirely implemented) +- RFC 2076 - Common Internet Message Headers + +Not yet implemented : + +- RFC 2298 - An Extensible Message Format + for Message Disposition Notifications + +2.6.2/ Dependencies + +- tools/ + +2.6.3/ Files descriptions + +mailimf.[ch] -- functions to parse RFC 2822 messages. +mailimf_types.[ch] -- definition of types and constructors for these + types +mailimf_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use IMF module. +mailimf_write.[ch] -- functions that output RFC 2822 messages or + sub-part of the messages in a (FILE *). + +2.6.4/ Interface + +Include for this module is mailimf.h and includes all other headers. + +The interface of IMAP4rev1 is documented in the following files : + +mailimf.h +mailimf_types.h +mailimf_types_helper.h +mailimf_write.h + + +2.7/ MIME - Multipurpose Internet Mail Extensions +------------------------------------------------- + +The MIME module provides functions to parse structure of MIME messages. +Directory mime/. + +2.7.1/ References + +- RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of + Internet Message Bodies. +- RFC 2047 - MIME (Multipurpose Internet Mail Extensions) Part Three: Message + Header Extensions for Non-ASCII Text. +- RFC 2183 - Communicating Presentation Information in Internet Messages: + The Content-Disposition Header Field + +Not implemented : + +- RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two: Media + Types. + +2.7.2/ Dependencies + +- tools/ +- imf/ + +2.7.3/ Files descriptions + +mailmime.[ch] -- functions to parse the MIME fields (RFC 2045). +mailmime_content.[ch] -- functions to parse the MIME message. You get + the different parts and you can decode them. +mailmime_decode.[ch] -- functions to parse the MIME-encoded fields. +mailmime_disposition.[ch] -- functions to parse the Content-Disposition field + (RFC 2183) +mailmime_types.[ch] -- definition of types and constructors for these + types +mailmime_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use MIME module. +mailmime_write.[ch] -- functions that output MIME messages or + sub-part of the messages in a (FILE *). + +2.7.4/ Interface + +Include for this module is mailmime.h and includes all other headers. + +There is not yet documentation for MIME module. + + +2.8/ SMTP - Simple Mail Transfer Protocol +----------------------------------------- + +Each command of the SMTP Standard (RFC 2821 and RFC 1891) is implemented +in the SMTP module. Directory smtp/. + +2.8.1/ References + +- RFC 2821 - Simple Mail Transfer Protocol (Not entirely implemented) +- RFC 1891 - SMTP Service Extension for Delivery Status Notifications + +2.8.2/ Depencencies + +- tools/ + +2.8.3/ Files descriptions + +mailsmtp.[ch] -- functions that implements each SMTP command +mailsmtp_helper.[ch] -- functions to get an easier use of SMTP module +mailsmtp_socket.[ch] -- provides a function to connect to a + SMTP server over TCP +mailsmtp_ssl.[ch] -- provides a function to connect to a + SMTP server over TLS layer +mailsmtp_types.h -- definition of types + +2.8.4/ Interface + +Include for this module is mailsmtp.h and includes all other headers. + +There is not yet documentation for MIME module. + + +2.9/ Miscellaneous + +2.9.1/ References + +- RFC 2234 - Augmented BNF for Syntax Specifications: ABNF +- RFC 2595 - Using TLS with IMAP, POP3 and ACAP + +2.9.2/ Tools + +tools/ directory contains some tools functions and useful data structures. + +alloc.h -- a wrapper on malloc() +carray.[ch] -- an array, that grows automatically when elements + are added. +charconv.[ch] -- character set converter. For example, it will + translate an iso-8859-1 string to an utf-8 string. +chash.[ch] -- a hash table which keys can be anything +cinthash.[ch] -- a hash table which keys are integers + (should be removed and replaced with chash) +clist.[ch] -- a double-linked list +connect.[ch] -- easy interface to connect a TCP server +hmac_md5.h +md5.[ch] +md5global.h -- MD5 calculation +mail.h -- some constants +maildb_helper.[ch] -- wrappers to DB 2.x 3.x or 4.x +maillock.[ch] -- safely lock a given file +mailstream.[ch] -- stream interface - buffered reading and writing + on files/socket/SSL connection +mailstream_helper.[ch] -- useful functions for stream + (for example: read a line) +mailstream_low.[ch] -- driver interface for a stream +mailstream_socket.[ch] -- stream driver for file descriptors (includes socket) +mailstream_ssl.[ch] -- stream driver for SSL connection +mailstream_types.h -- data structure definition +mapping.[ch] -- map parts of files in memory (no more used) +mmapstring.[ch] -- a string, that grows automatically when data + are added. + + +3/ Higher-level +--------------- + +The higher level will allow us to query folder informations or to get +messages information or content. + +There is four kinds of identities : +- storage +- folders +- session +- messages + +In the higher-level interface, you manipulate data types from IMF and +MIME module, plus additionnal data types of higher-level. + + +3.1/ Objects +------------ + +3.1.1/ Storage + +A storage (struct mail_storage) represents whether a server or +a main path, It can be an IMAP server, the root path of a MH or a mbox file. + + +3.1.2/ Folders + +A folder can be created from a storage. +Folders (struct mail_folder) are the mailboxes we can choose in the +server or as sub-folder of the main path. + +Folders for IMAP are the IMAP mailboxes, for MH this is one of the +folder of the MH storage, for mbox, there is only one folder, the +mbox file content; + + +3.1.3/ Session + +Storage and folders communicate with the lower-layer through the +mail session data structure. + +A mail session (struct mailsession) is a mail access to a server +or a mail access in the local file system. It allow us to send commands +to the mail access. + +A mail storage is using a mail session to communicate. +A folder folder also uses a mail session to get information or to send +information. It can be the same session or not, depdending of the +implementation. + + +3.1.4/ Messages + +From a session, we can get a message (struct mailmessage) to read. + + +3.2/ Drivers +------------ + +For a mail access, three drivers exist. +One for storage, one for session, one for message. +Note that the folder access rely only on session driver. + + +3.2.1/ storage driver interface + + mail_storage_driver is the driver structure for mail storage + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - free_data() frees the data created with mail_storage constructor. + + a constructor for each kind of access has to be implemented. + + +3.2.2/ session driver interface + + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - check_folder() makes a checkpoint of the session + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mail_envelopes_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + +3.2.3/ message driver interface + + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. + + +3.3/ Higher level interface +--------------------------- + +3.3.1/ Files descriptions + +generic_cache.[ch] -- functions that implements cache and + flags storing mechanism +imapdriver.[ch] -- IMAP driver for session +imapdriver_cached.[ch] -- IMAP driver for session, using cache, + IMAP already has flags. +imapdriver_cached_message.[ch] -- IMAP driver for message, using cache + IMAP already has flags. +imapdriver_message.[ch] -- IMAP driver for message +imapdriver_types.[ch] -- tools function for IMAP driver (types + conversion from IMAP module). +imapstorage.[ch] -- IMAP driver for storage +imfcache.[ch] -- implements cache for parsed fields +libetpan.h -- includes all necessary header files to + use libEtPan! +maildriver.[ch] -- wrappers to calls to the session driver +maildriver_tools.[ch] -- default implementation for drivers, + when the driver does not parse the + messages. +maildriver_types.[ch] -- data types declaration and constructors +maildriver_types_helper.[ch] -- easy data creation +mailmessage.[ch] -- wrappers to calls to the message driver +mailstorage.[ch] -- storage creation, calls to the storage + driver and implementation of folders. +mailstorage_tools.[ch] -- tools for storage (connection) +mailthread.[ch] -- threading: collection of the mails + into a treee +mboxdriver.[ch] -- mbox driver for session +mboxdriver_cached.[ch] -- mbox driver for session, using flags + and cache +mboxdriver_cached_message.[ch] -- mbox driver for message, using flags + and cache +mboxdriver_message.[ch] -- mbox driver for message +mboxdriver_tools.[ch] -- mbox driver common functions +mboxstorage.[ch] -- mbox driver for storage +mhdriver.[ch] -- MH driver for session +mhdriver_cached.[ch] -- MH driver for session, using flags + and cache +mhdriver_cached_message.[ch] -- MH driver for message, using flags + and cache. +mhdriver_message.[ch] -- MH driver for message +mhdriver_tools.[ch] -- MH driver common functions +mhstorage.[ch] -- MH driver for storage +nntpdriver.[ch] -- NNTP driver for session +nntpdriver_cached.[ch] -- NNTP driver for session, using flags + and cache +nntpdriver_cached_message.[ch] -- NNTP driver for message, using flags + and cache +nntpdriver_message.[ch] -- NNTP driver for message +nntpdriver_tools.[ch] -- NNTP driver common functions +nntpstorage.[ch] -- NNTP driver for storage +pop3driver.[ch] -- POP3 driver for session +pop3driver_cached.[ch] -- POP3 driver for session, using flags + and cache +pop3driver_cached_message.[ch] -- POP3 driver for message, using flags + and cache +pop3driver_message.[ch] -- POP3 driver for message +pop3driver_tools.[ch] -- POP3 driver common functions +pop3storage.[ch] -- POP3 driver for storage + + +3.3.2/ Interfaces + +Include for this module is libetpan.h and includes all other headers. + + +The interface of higher layer is documented in the following files : + +maildriver.h +maildriver_types.h +maildriver_types_helper.h +mailmessage.h +mailstorage.h +mailstorage_types.[h] +mailthread.h + + +4/ Architecture +--------------- + +(see layer.fig) + + +5/ Example of use +----------------- + +You can find some example in tests/ + + +6/ Constraints +-------------- + +- libEtPan! must run on a system where mmap() is available. + +- for mbox particularly, libEtPan! make assumption on the fact that a + file can be entirely mapped into memory. But if you don't read + mailboxes of 1 Go, it should be fine. + + + diff --git a/kmicromail/libetpan/doc/README.sgml b/kmicromail/libetpan/doc/README.sgml new file mode 100644 index 0000000..1ddbf96 --- a/dev/null +++ b/kmicromail/libetpan/doc/README.sgml @@ -0,0 +1,319 @@ + + + + + 2003-12-03 + libEtPan! + + + Viet Hoa + DINH + + + + 2003 + DINH Viet Hoa + + + + + + Introduction + + + + Description + + The purpose of this mail library is to provide a portable, + efficient middleware for different kinds of mail access + (IMAPrev4, POP3, NNTP, mbox, MH, Maildir). + + + + You have two kinds of mailbox access, either using low-level + functions with a different interface for each kind of access + or using higher-level functions, using a driver to wrap the + higher-level API. The API will be the same for each kind of + mail access using the higher-level API. + + + + + + Author + + Main author + + DINH Viet Hoa hoa@users.sourceforge.net + + + + Contributors + + + + + Wim Delvaux + + + + + Melvin Hadasht + + + + + David Woodhouse + + + + + Juergen Graf + + + + + Zsolt VARGA + + + + + Gael Roualland + + + + + + + + + + + Installation + + + Dependencies + + + + Dependencies for users + + + + + OpenSSL + (optional but recommended) + + + + + Berkeley + DB (optional but recommended) + + + + + POSIX Thread (required) + + + + + + + Dependencies for developers + + + + + + autoconf + + 2.13 + + + + + + automake + + 1.4 + + + + + + libtool + + 1.4.3 + + + + + + + + Existing packages + + + + + Before you try to compile it, you have to know that packages + exist for FreeBSD. (ports/mail/libetpan). + This is currently 0.29 for -stable, 0.30 for -current. + + + + + + + + Compilation + + + Generic installation instructions are in the + INSTALL file + You can pass the following extra options to configure : + + + + + FreeBSD + + + + make sure libiconv is installed from the ports collection (see + pkg_info). + + + + + issue configure with the following parameter: + +$ ./configure --with-libiconv-prefix=/usr/local + + + + + + + + + Mac OS X + + + + You have to configure using the following command line : + CPPFLAGS=-I/sw/include LDFLAGS=-L/sw/lib + ./configure + + + + + in tests/option-parser.c, change the inclusion + of getopt.h to + gnugetopt/getopt.h + + + + + in tests/Makefile, add + -I/sw/include for the + CFLAGS and + -L/sw/lib -lgnugetopt for the LDFLAGS. + + + + + + + + Linux + + + + + Since libEtPan! is making high usage of + mmap() even for + writing, when your mailboxes are on + NFS filesystem with + a Linux server, it is advised to use option + no_subtree_check in + /etc/exports. + This should avoid corruption of data. + + + The problem exist in Linux 2.4.22 and earlier versions. + + + + + + On RedHat systems, you have to configure using the + following command line : + ./configure --with-openssl=/usr/kerberos + + + + + On Debian systems, if the ./autogen + script fails on missing AM_ICONV, you + have to install gettext package. + + + + + + + + configure + + You can use the following options : + + + + + --enable-debug Compiles with + debugging turned on + + + + + --enable-optim Turns on some + optimizations flags for gcc + + + + + --without-openssl Disables OpenSSL (do + not look for it) + + + + + + Compile and install + + Download the package and do the following : + + +$ tar xzvf libetpan-XX.XX.tar.gz # to decompress the package + +$ cd libetpan-XX.XX + +$ ./configure --help # to get options of configure + +$ ./configure # you can specify your own options + +$ make # to compile the package + +$ su + +# make install + +# logout + + + + + diff --git a/kmicromail/libetpan/doc/depend.dot b/kmicromail/libetpan/doc/depend.dot new file mode 100644 index 0000000..b12990f --- a/dev/null +++ b/kmicromail/libetpan/doc/depend.dot @@ -0,0 +1,54 @@ +digraph "etPan! library" { + mime -> imf; + + "session/message" -> imf; + "session/message" -> mime; + + "storage/folder" -> "session/message"; +} + +digraph "imap driver" { + "imap driver" -> imap; + "imap driver" -> imf; + "imap driver" -> mime; + "imap driver" -> "session/message"; + + mime -> imf; +} + +digraph "mbox driver" { + "mbox driver" -> mbox; + "mbox driver" -> imf; + "mbox driver" -> mime; + "mbox driver" -> "session/message"; + "mbox" -> imf; + + mime -> imf; +} + +digraph "mh driver" { + "mh driver" -> mh; + "mh driver" -> imf; + "mh driver" -> mime; + "mh driver" -> "session/message"; + + mime -> imf; +} + +digraph "pop3 driver" { + "pop3 driver" -> pop3; + "pop3 driver" -> imf; + "pop3 driver" -> mime; + "pop3 driver" -> "session/message"; + + mime -> imf; +} + +digraph "nntp driver" { + "nntp driver" -> nntp; + "nntp driver" -> imf; + "nntp driver" -> mime; + "nntp driver" -> "session/message"; + + mime -> imf; +} diff --git a/kmicromail/libetpan/doc/layer.fig b/kmicromail/libetpan/doc/layer.fig new file mode 100644 index 0000000..ed41783 --- a/dev/null +++ b/kmicromail/libetpan/doc/layer.fig @@ -0,0 +1,39 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 3150 12150 3150 12150 3825 900 3825 900 3150 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 3825 12150 3825 12150 4500 900 4500 900 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3150 3150 3150 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 5400 3150 5400 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 7650 3150 7650 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 9900 3150 9900 3825 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 7 + 12150 3150 900 3150 900 2475 12825 2475 12825 4500 12150 4500 + 12150 3150 +2 3 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 7 + 900 2475 900 1800 13500 1800 13500 4500 12825 4500 12825 2475 + 900 2475 +2 3 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 8 + 900 4500 225 4500 225 1125 13500 1125 13500 1800 900 1800 + 900 4500 900 4500 +4 0 0 50 0 16 20 0.0000 4 210 1410 1305 3600 IMAP4rev1\001 +4 0 0 50 0 16 20 0.0000 4 210 450 10800 3600 MH\001 +4 0 0 50 0 16 20 0.0000 4 210 720 8370 3555 mbox\001 +4 0 0 50 0 16 20 0.0000 4 210 795 6120 3600 NNTP\001 +4 0 0 50 0 16 20 0.0000 4 210 765 3870 3600 POP3\001 +4 0 0 50 0 16 20 0.0000 4 270 1620 5670 2880 session layer\001 +4 0 0 50 0 16 20 0.0000 4 270 2730 5085 2250 storage / folders layer\001 +4 0 0 50 0 16 20 0.0000 4 210 1500 5760 4275 IMF / MIME\001 +4 0 0 50 0 16 20 0.0000 4 270 1395 5670 1575 application\001 diff --git a/kmicromail/libetpan/generic/.libs/libmaildriver.a b/kmicromail/libetpan/generic/.libs/libmaildriver.a new file mode 100644 index 0000000..9cbc924 --- a/dev/null +++ b/kmicromail/libetpan/generic/.libs/libmaildriver.a Binary files differ diff --git a/kmicromail/libetpan/generic/TODO b/kmicromail/libetpan/generic/TODO new file mode 100644 index 0000000..fb992cd --- a/dev/null +++ b/kmicromail/libetpan/generic/TODO @@ -0,0 +1,9 @@ +- add UID to non-cached drivers, help clients to recognize messages +- move IMAP UID cache to non-cached driver +- fix message size (put it in cache) +- XXX : fetch body in nntp do not use generic_fetch_body +- add flags prototype to add or remove flags +- change prototype of append_message (add flags) +- cache bodystructures +- search is not implemented +- list of folder new implementation diff --git a/kmicromail/libetpan/generic/data_message_driver.c b/kmicromail/libetpan/generic/data_message_driver.c new file mode 100644 index 0000000..26cb808 --- a/dev/null +++ b/kmicromail/libetpan/generic/data_message_driver.c @@ -0,0 +1,119 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "data_message_driver.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" + +#include +#include +#include +#include +#include +#include +#include + +static int fetch_size(mailmessage * msg, size_t * result) +{ + struct generic_message_t * msg_data; + + msg_data = msg->msg_data; + * result = msg_data->msg_length; + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_data_message_driver = { + .msg_name = "data", + + .msg_initialize = mailmessage_generic_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * data_message_driver = &local_data_message_driver; + + + +mailmessage * data_message_init(char * data, size_t len) +{ + struct generic_message_t * msg_data; + mailmessage * msg; + int r; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, data_message_driver, 0, len); + if (r < 0) + goto free; + + msg_data = msg->msg_data; + msg_data->msg_fetched = 1; + msg_data->msg_message = data; + msg_data->msg_length = len; + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +void data_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} diff --git a/kmicromail/libetpan/generic/data_message_driver.h b/kmicromail/libetpan/generic/data_message_driver.h new file mode 100644 index 0000000..e0ee752 --- a/dev/null +++ b/kmicromail/libetpan/generic/data_message_driver.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef DATA_MESSAGE_DRIVER_H + +#define DATA_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_DATA_MESSAGE + +extern mailmessage_driver * data_message_driver; + +mailmessage * data_message_init(char * data, size_t len); + +void data_message_detach_mime(mailmessage * msg); + +#endif diff --git a/kmicromail/libetpan/generic/generic_cache.c b/kmicromail/libetpan/generic/generic_cache.c new file mode 100644 index 0000000..d23f9cb --- a/dev/null +++ b/kmicromail/libetpan/generic/generic_cache.c @@ -0,0 +1,729 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "generic_cache.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maildriver_types.h" +#include "imfcache.h" +#include "chash.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int generic_cache_create_dir(char * dirname) +{ + struct stat buf; + int r; + + r = stat(dirname, &buf); + if (r != 0) { + r = mkdir(dirname, 0700); + + if (r < 0) + return MAIL_ERROR_FILE; + } + else { + if (!S_ISDIR(buf.st_mode)) + return MAIL_ERROR_FILE; + } + + return MAIL_NO_ERROR; +} + +int generic_cache_store(char * filename, char * content, size_t length) +{ + int fd; + char * str; + + fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd == -1) + return MAIL_ERROR_FILE; + + if (ftruncate(fd, length) < 0) + return MAIL_ERROR_FILE; + + str = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (str == MAP_FAILED) + return MAIL_ERROR_FILE; + + memcpy(str, content, length); + msync(str, length, MS_SYNC); + munmap(str, length); + + close(fd); + + return MAIL_NO_ERROR; +} + +int generic_cache_read(char * filename, char ** result, size_t * result_len) +{ + int fd; + char * str; + struct stat buf; + MMAPString * mmapstr; + char * content; + int res; + + if (stat(filename, &buf) < 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + fd = open(filename, O_RDONLY); + if (fd == -1) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + str = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(str, buf.st_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + content = mmapstr->str; + + munmap(str, buf.st_size); + close(fd); + + * result = content; + * result_len = buf.st_size; + + return MAIL_NO_ERROR; + + free: + mmap_string_free(mmapstr); + unmap: + munmap(str, buf.st_size); + close: + close(fd); + err: + return res; +} + +static int flags_extension_read(MMAPString * mmapstr, size_t * index, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * str; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, str); + if (r < 0) { + free(str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int generic_flags_read(MMAPString * mmapstr, size_t * index, + struct mail_flags ** result) +{ + clist * ext; + int r; + struct mail_flags * flags; + uint32_t value; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &value); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = flags_extension_read(mmapstr, index, &ext); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + flags = mail_flags_new(value, ext); + if (flags == NULL) { + res = r; + goto free; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + clist_foreach(ext, (clist_func) free, NULL); + clist_free(ext); + err: + return res; +} + +static int flags_extension_write(MMAPString * mmapstr, size_t * index, + clist * ext) +{ + int r; + clistiter * cur; + + r = mailimf_cache_int_write(mmapstr, index, clist_count(ext)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(ext) ; cur != NULL ; cur = clist_next(cur)) { + r = mailimf_cache_string_write(mmapstr, index, + clist_content(cur), strlen(clist_content(cur))); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int generic_flags_write(MMAPString * mmapstr, size_t * index, + struct mail_flags * flags) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, + flags->fl_flags & ~MAIL_FLAG_NEW); + if (r != MAIL_NO_ERROR) + return r; + + r = flags_extension_write(mmapstr, index, + flags->fl_extension); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + + + +static struct mail_flags * mail_flags_dup(struct mail_flags * flags) +{ + clist * list; + struct mail_flags * new_flags; + int r; + clistiter * cur; + + list = clist_new(); + if (list == NULL) { + goto err; + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * ext; + + ext = strdup(clist_content(cur)); + if (ext == NULL) { + goto free; + } + + r = clist_append(list, ext); + if (r < 0) { + free(ext); + goto free; + } + } + + new_flags = mail_flags_new(flags->fl_flags, list); + if (new_flags == NULL) { + goto free; + } + + return new_flags; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return NULL; +} + +static mailmessage * mailmessage_build(mailmessage * msg) +{ + mailmessage * new_msg; + + new_msg = malloc(sizeof(* new_msg)); + if (new_msg == NULL) + goto err; + + new_msg->msg_session = msg->msg_session; + new_msg->msg_driver = msg->msg_driver; + new_msg->msg_index = msg->msg_index; + if (msg->msg_uid == NULL) + new_msg->msg_uid = NULL; + else { + new_msg->msg_uid = strdup(msg->msg_uid); + if (new_msg->msg_uid == NULL) + goto free; + } + + new_msg->msg_cached = msg->msg_cached; + new_msg->msg_size = msg->msg_size; + new_msg->msg_fields = NULL; + new_msg->msg_flags = mail_flags_dup(msg->msg_flags); + if (new_msg->msg_flags == NULL) { + free(new_msg->msg_uid); + goto free; + } + + new_msg->msg_mime = NULL; + new_msg->msg_data = NULL; + + return new_msg; + + free: + free(new_msg); + err: + return NULL; +} + +struct mail_flags_store * mail_flags_store_new(void) +{ + struct mail_flags_store * flags_store; + + flags_store = malloc(sizeof(struct mail_flags_store)); + if (flags_store == NULL) + goto err; + + flags_store->fls_tab = carray_new(128); + if (flags_store->fls_tab == NULL) + goto free; + + flags_store->fls_hash = chash_new(128, CHASH_COPYALL); + if (flags_store->fls_hash == NULL) + goto free_tab; + + return flags_store; + + free_tab: + carray_free(flags_store->fls_tab); + free: + free(flags_store); + err: + return NULL; +} + +void mail_flags_store_clear(struct mail_flags_store * flags_store) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + chashdatum key; + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + key.data = &msg->msg_index; + key.len = sizeof(msg->msg_index); + chash_delete(flags_store->fls_hash, &key, NULL); + + mailmessage_free(msg); + } + carray_set_size(flags_store->fls_tab, 0); +} + +void mail_flags_store_free(struct mail_flags_store * flags_store) +{ + mail_flags_store_clear(flags_store); + chash_free(flags_store->fls_hash); + carray_free(flags_store->fls_tab); + free(flags_store); +} + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg) +{ + chashdatum key; + chashdatum value; + unsigned int index; + int res; + int r; + mailmessage * new_msg; + + if (msg->msg_flags == NULL) { + res = MAIL_NO_ERROR; + goto err; + } + + /* duplicate needed message info */ + new_msg = mailmessage_build(msg); + if (new_msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + key.data = &new_msg->msg_index; + key.len = sizeof(new_msg->msg_index); + + r = chash_get(flags_store->fls_hash, &key, &value); + if (r == 0) { + mailmessage * old_msg; + + index = * (unsigned int *) value.data; + old_msg = carray_get(flags_store->fls_tab, index); + mailmessage_free(old_msg); + } + else { + r = carray_set_size(flags_store->fls_tab, + carray_count(flags_store->fls_tab) + 1); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + index = carray_count(flags_store->fls_tab) - 1; + } + + carray_set(flags_store->fls_tab, index, new_msg); + + value.data = &index; + value.len = sizeof(index); + + r = chash_set(flags_store->fls_hash, &key, &value, NULL); + if (r < 0) { + carray_delete(flags_store->fls_tab, index); + res = MAIL_ERROR_MEMORY; + goto free; + } + + return MAIL_NO_ERROR; + + free: + mailmessage_free(new_msg); + err: + return res; +} + +static int msg_index_compare(mailmessage ** msg1, mailmessage ** msg2) +{ + return (* msg1)->msg_index - (* msg2)->msg_index; +} + +void mail_flags_store_sort(struct mail_flags_store * flags_store) +{ + qsort(carray_data(flags_store->fls_tab), + carray_count(flags_store->fls_tab), sizeof(mailmessage *), + (int (*)(const void *, const void *)) msg_index_compare); +} + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index) +{ + struct mail_flags * flags; + chashdatum key; + chashdatum value; + int r; + unsigned int tab_index; + mailmessage * msg; + + key.data = &index; + key.len = sizeof(index); + + r = chash_get(flags_store->fls_hash, &key, &value); + + if (r < 0) + return NULL; + +#if 0 + flags = mail_flags_dup((struct mail_flags *) value.data); +#endif + tab_index = * (unsigned int *) value.data; + msg = carray_get(flags_store->fls_tab, tab_index); + if (msg->msg_flags == NULL) + return NULL; + + flags = mail_flags_dup(msg->msg_flags); + + return flags; +} + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2) +{ + clistiter * cur1; + + if (clist_count(flags1->fl_extension) != clist_count(flags2->fl_extension)) + return -1; + + for(cur1 = clist_begin(flags1->fl_extension) ; cur1 != NULL ; + cur1 = clist_next(cur1)) { + char * flag1; + clistiter * cur2; + int found; + + flag1 = clist_content(cur1); + + found = 0; + for(cur2 = clist_begin(flags2->fl_extension) ; cur2 != NULL ; + cur2 = clist_next(cur2)) { + char * flag2; + + flag2 = clist_content(cur2); + + if (strcasecmp(flag1, flag2) == 0) { + found = 1; + break; + } + } + + if (!found) + return -1; + } + + return flags1->fl_flags - flags2->fl_flags; +} + + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + struct mailimf_fields * fields; + void * data; + size_t data_len; + + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimf_cache_fields_read(mmapstr, &cur_token, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_fields_write(mmapstr, &cur_token, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result) +{ + int r; + int res; + size_t cur_token; + struct mail_flags * flags; + void * data; + size_t data_len; + + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = generic_flags_read(mmapstr, &cur_token, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = generic_flags_write(mmapstr, &cur_token, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int generic_cache_delete(struct mail_cache_db * cache_db, + char * keyname) +{ + int r; + int res; + + r = mail_cache_db_del(cache_db, keyname, strlen(keyname)); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} diff --git a/kmicromail/libetpan/generic/generic_cache.h b/kmicromail/libetpan/generic/generic_cache.h new file mode 100644 index 0000000..7815831 --- a/dev/null +++ b/kmicromail/libetpan/generic/generic_cache.h @@ -0,0 +1,109 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef GENERIC_CACHE_H + +#define GENERIC_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "generic_cache_types.h" +#include "mailmessage_types.h" +#include "chash.h" +#include "carray.h" +#include "mail_cache_db_types.h" + +int generic_cache_create_dir(char * dirname); + +int generic_cache_store(char * filename, char * content, size_t length); +int generic_cache_read(char * filename, char ** result, size_t * result_len); + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname); + +#if 0 +int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(DB * dbp, char * keyname); +#endif + +struct mail_flags_store * mail_flags_store_new(void); + +void mail_flags_store_clear(struct mail_flags_store * flags_store); + +void mail_flags_store_free(struct mail_flags_store * flags_store); + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg); + +void mail_flags_store_sort(struct mail_flags_store * flags_store); + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index); + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/generic_cache_types.h b/kmicromail/libetpan/generic/generic_cache_types.h new file mode 100644 index 0000000..8803a42 --- a/dev/null +++ b/kmicromail/libetpan/generic/generic_cache_types.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef GENERIC_CACHE_TYPE_H + +#define GENERIC_CACHE_TYPE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_flags_store { + carray * fls_tab; + chash * fls_hash; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver.c b/kmicromail/libetpan/generic/imapdriver.c new file mode 100644 index 0000000..0d63319 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver.c @@ -0,0 +1,1130 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapdriver.h" + +#include "mail.h" +#include "imapdriver_tools.h" +#include "mailmessage.h" +#include "imapdriver_message.h" +#include "imapdriver_types.h" +#include "maildriver.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include +#include + +static int imapdriver_initialize(mailsession * session); + +static void imapdriver_uninitialize(mailsession * session); + +static int imapdriver_connect_stream(mailsession * session, mailstream * s); + +static int imapdriver_starttls(mailsession * session); + +static int imapdriver_login(mailsession * session, + char * userid, char * password); + +static int imapdriver_logout(mailsession * session); + +static int imapdriver_noop(mailsession * session); + +static int imapdriver_build_folder_name(mailsession * session, char * mb, + char * name, char ** result); + +static int imapdriver_create_folder(mailsession * session, char * mb); + +static int imapdriver_delete_folder(mailsession * session, char * mb); + +static int imapdriver_rename_folder(mailsession * session, char * mb, + char * new_name); + +static int imapdriver_check_folder(mailsession * session); + +static int imapdriver_examine_folder(mailsession * session, char * mb); + +static int imapdriver_select_folder(mailsession * session, char * mb); +static int imapdriver_expunge_folder(mailsession * session); + +static int imapdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int imapdriver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int imapdriver_recent_number(mailsession * session, char * mb, + uint32_t * result); + +static int imapdriver_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int imapdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result); +static int imapdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); +static int imapdriver_subscribe_folder(mailsession * session, char * mb); +static int imapdriver_unsubscribe_folder(mailsession * session, char * mb); +static int imapdriver_append_message(mailsession * session, + char * message, size_t size); +static int imapdriver_copy_message(mailsession * session, + uint32_t num, char * mb); + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +#if 0 +static int imapdriver_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_imap_session_driver = { + .sess_name = "imap", + + .sess_initialize = imapdriver_initialize, + .sess_uninitialize = imapdriver_uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = imapdriver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = imapdriver_starttls, + .sess_login = imapdriver_login, + .sess_logout = imapdriver_logout, + .sess_noop = imapdriver_noop, + + .sess_build_folder_name = imapdriver_build_folder_name, + .sess_create_folder = imapdriver_create_folder, + .sess_delete_folder = imapdriver_delete_folder, + .sess_rename_folder = imapdriver_rename_folder, + .sess_check_folder = imapdriver_check_folder, + .sess_examine_folder = imapdriver_examine_folder, + .sess_select_folder = imapdriver_select_folder, + .sess_expunge_folder = imapdriver_expunge_folder, + .sess_status_folder = imapdriver_status_folder, + .sess_messages_number = imapdriver_messages_number, + .sess_recent_number = imapdriver_recent_number, + .sess_unseen_number = imapdriver_unseen_number, + .sess_list_folders = imapdriver_list_folders, + .sess_lsub_folders = imapdriver_lsub_folders, + .sess_subscribe_folder = imapdriver_subscribe_folder, + .sess_unsubscribe_folder = imapdriver_unsubscribe_folder, + + .sess_append_message = imapdriver_append_message, + .sess_copy_message = imapdriver_copy_message, + .sess_move_message = NULL, + + .sess_get_messages_list = imapdriver_get_messages_list, + .sess_get_envelopes_list = imapdriver_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = imapdriver_search_messages, +#endif + + .sess_get_message = imapdriver_get_message, + .sess_get_message_by_uid = imapdriver_get_message_by_uid, +}; + +mailsession_driver * imap_session_driver = &local_imap_session_driver; + +static inline struct imap_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailimap * get_imap_session(mailsession * session) +{ + return get_data(session)->imap_session; +} + +static int imapdriver_initialize(mailsession * session) +{ + struct imap_session_state_data * data; + mailimap * imap; + struct mail_flags_store * flags_store; + + imap = mailimap_new(0, NULL); + if (imap == NULL) + goto err; + + flags_store = mail_flags_store_new(); + if (flags_store == NULL) + goto free_session; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free_flags_store; + + data->imap_mailbox = NULL; + data->imap_session = imap; + data->imap_flags_store = flags_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_flags_store: + mail_flags_store_free(flags_store); + free_session: + mailimap_free(imap); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_flags_store_process(mailimap * imap, + struct mail_flags_store * flags_store) +{ + unsigned int i; + int r; + mailmessage * first; + mailmessage * last; + + mail_flags_store_sort(flags_store); + + if (carray_count(flags_store->fls_tab) == 0) + return; + + first = carray_get(flags_store->fls_tab, 0); + last = first; + + for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + if (last->msg_index + 1 == msg->msg_index) { + r = mail_flags_compare(first->msg_flags, msg->msg_flags); + if (r == 0) { + last = msg; + continue; + } + } + + r = imap_store_flags(imap, first->msg_index, + last->msg_index, first->msg_flags); + + first = msg; + last = msg; + } + + r = imap_store_flags(imap, first->msg_index, last->msg_index, + first->msg_flags); + + mail_flags_store_clear(flags_store); +} + +static void imapdriver_uninitialize(mailsession * session) +{ + struct imap_session_state_data * data; + + data = get_data(session); + + imap_flags_store_process(data->imap_session, + data->imap_flags_store); + mail_flags_store_free(data->imap_flags_store); + + mailimap_free(data->imap_session); + if (data->imap_mailbox != NULL) + free(data->imap_mailbox); + free(data); + + session->sess_data = NULL; +} + +static int imapdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailimap_connect(get_imap_session(session), s); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_login(mailsession * session, + char * userid, char * password) +{ + int r; + + r = mailimap_login(get_imap_session(session), userid, password); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_logout(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_logout(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_noop(mailsession * session) +{ + int r; + + r = mailimap_noop(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_build_folder_name(mailsession * session, char * mb, + char * name, char ** result) +{ + char delimiter[2] = "X"; + char * folder_name; + mailimap * imap; + struct mailimap_mailbox_list * mb_list; + int r; + clist * imap_list; + + imap = get_imap_session(session); + + r = mailimap_list(imap, mb, "", &imap_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (clist_begin(imap_list) == NULL) + return MAIL_ERROR_LIST; + + mb_list = clist_begin(imap_list)->data; + delimiter[0] = mb_list->mb_delimiter; + + folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, delimiter); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int imapdriver_create_folder(mailsession * session, char * mb) +{ + int r; + + r = mailimap_create(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_delete_folder(mailsession * session, char * mb) +{ + int r; + + r = mailimap_delete(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_rename_folder(mailsession * session, char * mb, + char * new_name) +{ + int r; + + r = mailimap_rename(get_imap_session(session), mb, new_name); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_check_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_check(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_examine_folder(mailsession * session, char * mb) +{ + int r; + + r = mailimap_examine(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_select_folder(mailsession * session, char * mb) +{ + int r; + char * new_mb; + char * old_mb; + + old_mb = get_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_select(get_imap_session(session), mb); + + switch (r) { + case MAILIMAP_NO_ERROR: + new_mb = strdup(mb); + if (new_mb == NULL) { + if (old_mb != NULL) + free(old_mb); + get_data(session)->imap_mailbox = NULL; + return MAIL_ERROR_MEMORY; + } + + get_data(session)->imap_mailbox = new_mb; + + return MAIL_NO_ERROR; + default: + return imap_error_to_mail_error(r); + } +} + +static int imapdriver_expunge_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_expunge(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int status_selected_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + int res; + mailimap * imap; + uint32_t exists; + uint32_t unseen; + uint32_t recent; + struct mailimap_search_key * search_key; + clist * search_result; + + imap = get_imap_session(session); + + exists = imap->imap_selection_info->sel_exists; + recent = imap->imap_selection_info->sel_recent; + + search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + if (search_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + /* default : use the RECENT count if search fails */ + unseen = recent; + r = mailimap_search(imap, NULL, search_key, &search_result); + mailimap_search_key_free(search_key); + if (r == MAILIMAP_NO_ERROR) { + /* if this succeed, we use the real count */ + unseen = clist_count(search_result); + mailimap_mailbox_data_search_free(search_result); + } + + * result_messages = exists; + * result_unseen = unseen; + * result_recent = recent; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int status_unselected_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailimap_status_att_list * att_list; + struct mailimap_mailbox_data_status * status; + int r; + int res; + clistiter * cur; + mailimap * imap; + + imap = get_imap_session(session); + + att_list = mailimap_status_att_list_new_empty(); + if (att_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status(imap, mb, att_list, &status); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto free; + } + + * result_messages = 0; + * result_recent = 0; + * result_unseen = 0; + + for (cur = clist_begin(status->st_info_list); + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * status_info; + + status_info = clist_content(cur); + switch (status_info->st_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + * result_messages = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + * result_recent = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + * result_unseen = status_info->st_value; + break; + } + } + + mailimap_mailbox_data_status_free(status); + mailimap_status_att_list_free(att_list); + + return MAIL_NO_ERROR; + + free: + mailimap_status_att_list_free(att_list); + err: + return res; +} + +static int imapdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + int current_folder; + char * current_mb; + + if (mb == NULL) { + mb = get_data(session)->imap_mailbox; + if (mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + } + + current_mb = get_data(session)->imap_mailbox; + if (strcmp(mb, current_mb) == 0) + current_folder = 1; + else + current_folder = 0; + + if (current_folder) + return status_selected_folder(session, mb, result_messages, + result_recent, result_unseen); + else + return status_unselected_folder(session, mb, result_messages, + result_recent, result_unseen); + + err: + return res; +} + +/* TODO : more efficient functions */ + +static int imapdriver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int imapdriver_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int imapdriver_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +enum { + IMAP_LIST, IMAP_LSUB +}; + +static int imapdriver_list_lsub_folders(mailsession * session, int type, + char * mb, + struct mail_list ** result) +{ + clist * imap_list; + struct mail_list * resp; + int r; + int res; + + switch (type) { + case IMAP_LIST: + r = mailimap_list(get_imap_session(session), mb, + "*", &imap_list); + break; + case IMAP_LSUB: + r = mailimap_lsub(get_imap_session(session), mb, + "*", &imap_list); + break; + default: + res = MAIL_ERROR_LIST; + goto err; + } + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto err; + } + + r = imap_list_to_list(imap_list, &resp); + if (r != MAIL_NO_ERROR) { + mailimap_list_result_free(imap_list); + res = r; + goto err; + } + + mailimap_list_result_free(imap_list); + + * result = resp; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int imapdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LIST, mb, + result); +} + +static int imapdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb, + result); +} + +static int imapdriver_subscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = mailimap_subscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_unsubscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = mailimap_unsubscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +/* messages operations */ + +static int imapdriver_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + + r = mailimap_append_simple(get_imap_session(session), + get_data(session)->imap_mailbox, + message, size); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_copy_message(mailsession * session, + uint32_t num, char * mb) +{ + int r; + struct mailimap_set * set; + int res; + + set = mailimap_set_new_single(num); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_uid_copy(get_imap_session(session), set, mb); + + mailimap_set_free(set); + + return imap_error_to_mail_error(r); + + err: + return res; +} + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return imap_get_messages_list(get_imap_session(session), + session, imap_message_driver, 1, + result); +} + + + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + uint32_t exists; + clist * msg_list; + + if (get_imap_session(session)->imap_selection_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + exists = get_imap_session(session)->imap_selection_info->sel_exists; + + if (exists == 0) + return MAIL_NO_ERROR; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + mailimap_fetch_type_free(fetch_type); + clist_free(msg_list); + return MAIL_NO_ERROR; + } + + r = msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +#if 0 +static int imapdriver_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + struct mailimap_search_key * imap_key; + int r; + clist * imap_result; + clist * result_list; + struct mail_search_result * search_result; + clistiter * cur; + + r = mail_search_to_imap_search(key, &imap_key); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_search(get_imap_session(session), charset, imap_key, + &imap_result); + + mailimap_search_key_free(imap_key); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + result_list = clist_new(); + if (result_list == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t val = * (uint32_t *) clist_content(cur); + uint32_t * new; + + new = malloc(sizeof(* new)); + if (new == NULL) { + goto free_imap_result; + } + + * new = val; + + r = clist_append(result_list, new); + if (r != 0) { + free(new); + goto free_imap_result; + } + } + + search_result = mail_search_result_new(result_list); + if (search_result == NULL) + goto free_imap_result; + + mailimap_search_result_free(imap_result); + + * result = search_result; + + return MAIL_NO_ERROR; + + free_imap_result: + mailimap_search_result_free(imap_result); + return MAIL_ERROR_MEMORY; +} +#endif + +static int imapdriver_starttls(mailsession * session) +{ + mailimap * imap; + int r; + struct mailimap_capability_data * cap_data; + clistiter * cur; + int starttls; + int fd; + mailstream_low * low; + mailstream_low * new_low; + int capability_available; + + imap = get_imap_session(session); + + capability_available = FALSE; + if (imap->imap_connection_info != NULL) + if (imap->imap_connection_info->imap_capability != NULL) { + capability_available = TRUE; + cap_data = imap->imap_connection_info->imap_capability; + } + + if (!capability_available) { + r = mailimap_capability(imap, &cap_data); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + } + + starttls = FALSE; + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) + if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { + starttls = TRUE; + break; + } + } + + if (!capability_available) + mailimap_capability_data_free(cap_data); + + if (!starttls) + return MAIL_ERROR_NO_TLS; + + r = mailimap_starttls(imap); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + low = mailstream_get_low(imap->imap_stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAIL_ERROR_STREAM; + + new_low = mailstream_low_ssl_open(fd); + if (new_low == NULL) + return MAIL_ERROR_STREAM; + + mailstream_low_free(low); + mailstream_set_low(imap->imap_stream, new_low); + + return MAIL_NO_ERROR; +} + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + + libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + where UIDVALIDITY and UID are decimal representation of + respectively uidvalidity and uid numbers. + + Return value: + MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + MAIL_NO_ERROR if message was found. Result is in result +*/ + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap * imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_get_message(session, num, result); +} diff --git a/kmicromail/libetpan/generic/imapdriver.h b/kmicromail/libetpan/generic/imapdriver.h new file mode 100644 index 0000000..2bf36c7 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_H + +#define IMAPDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * imap_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver_cached.c b/kmicromail/libetpan/generic/imapdriver_cached.c new file mode 100644 index 0000000..e6af8e8 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_cached.c @@ -0,0 +1,1274 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapdriver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "imapdriver_tools.h" +#include "mail_cache_db.h" +#include "mailmessage.h" +#include "imapdriver_cached_message.h" +#include "maildriver.h" +#include "imapdriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maildriver_tools.h" +#include "imapdriver.h" + +static int imapdriver_cached_initialize(mailsession * session); +static void imapdriver_cached_uninitialize(mailsession * session); + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int imapdriver_cached_starttls(mailsession * session); + +static int imapdriver_cached_login(mailsession * session, + char * userid, char * password); +static int imapdriver_cached_logout(mailsession * session); +static int imapdriver_cached_noop(mailsession * session); +static int imapdriver_cached_build_folder_name(mailsession * session, + char * mb, + char * name, char ** result); +static int imapdriver_cached_create_folder(mailsession * session, char * mb); +static int imapdriver_cached_delete_folder(mailsession * session, char * mb); +static int imapdriver_cached_rename_folder(mailsession * session, char * mb, + char * new_name); +static int imapdriver_cached_check_folder(mailsession * session); +static int imapdriver_cached_examine_folder(mailsession * session, + char * mb); +static int imapdriver_cached_select_folder(mailsession * session, char * mb); +static int imapdriver_cached_expunge_folder(mailsession * session); +static int imapdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); +static int imapdriver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result); +static int imapdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); +static int imapdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); +static int imapdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result); +static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); +static int imapdriver_cached_subscribe_folder(mailsession * session, + char * mb); +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + char * mb); +static int imapdriver_cached_append_message(mailsession * session, + char * message, size_t size); +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, char * mb); + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result); +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num); + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result); +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_imap_cached_session_driver = { + .sess_name = "imap-cached", + + .sess_initialize = imapdriver_cached_initialize, + .sess_uninitialize = imapdriver_cached_uninitialize, + + .sess_parameters = imapdriver_cached_parameters, + + .sess_connect_stream = imapdriver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = imapdriver_cached_starttls, + .sess_login = imapdriver_cached_login, + .sess_logout = imapdriver_cached_logout, + .sess_noop = imapdriver_cached_noop, + + .sess_build_folder_name = imapdriver_cached_build_folder_name, + .sess_create_folder = imapdriver_cached_create_folder, + .sess_delete_folder = imapdriver_cached_delete_folder, + .sess_rename_folder = imapdriver_cached_rename_folder, + .sess_check_folder = imapdriver_cached_check_folder, + .sess_examine_folder = imapdriver_cached_examine_folder, + .sess_select_folder = imapdriver_cached_select_folder, + .sess_expunge_folder = imapdriver_cached_expunge_folder, + .sess_status_folder = imapdriver_cached_status_folder, + .sess_messages_number = imapdriver_cached_messages_number, + .sess_recent_number = imapdriver_cached_recent_number, + .sess_unseen_number = imapdriver_cached_unseen_number, + .sess_list_folders = imapdriver_cached_list_folders, + .sess_lsub_folders = imapdriver_cached_lsub_folders, + .sess_subscribe_folder = imapdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder, + + .sess_append_message = imapdriver_cached_append_message, + .sess_copy_message = imapdriver_cached_copy_message, + .sess_move_message = NULL, + + .sess_get_messages_list = imapdriver_cached_get_messages_list, + .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list, + .sess_remove_message = imapdriver_cached_remove_message, +#if 0 + .sess_search_messages = imapdriver_cached_search_messages, +#endif + + .sess_get_message = imapdriver_cached_get_message, + .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid, +}; + +mailsession_driver * imap_cached_session_driver = +&local_imap_cached_session_driver; + +#define CACHE_MESSAGE_LIST + +static inline struct imap_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * s) +{ + return get_cached_data(s)->imap_ancestor; +} + +static inline +struct imap_session_state_data * get_ancestor_data(mailsession * s) +{ + return get_ancestor(s)->sess_data; +} + +static inline mailimap * get_imap_session(mailsession * session) +{ + return get_ancestor_data(session)->imap_session; +} + +static int imapdriver_cached_initialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->imap_ancestor = mailsession_new(imap_session_driver); + if (data->imap_ancestor == NULL) + goto free_data; + data->imap_quoted_mb = NULL; + data->imap_cache_directory[0] = '\0'; + data->imap_uid_list = carray_new(128); + if (data->imap_uid_list == NULL) + goto free_session; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->imap_ancestor); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data) +{ + if (imap_cached_data->imap_quoted_mb != NULL) { + free(imap_cached_data->imap_quoted_mb); + imap_cached_data->imap_quoted_mb = NULL; + } +} + +struct uid_cache_item { + uint32_t uid; + uint32_t size; +}; + +static int update_uid_cache(mailsession * session, + struct mailmessage_list * env_list) +{ + unsigned int i; + int r; + struct imap_cached_session_state_data * data; + int res; + + data = get_cached_data(session); + + /* free all UID cache */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + + /* build UID cache */ + r = carray_set_size(data->imap_uid_list, + carray_count(env_list->msg_tab)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = malloc(sizeof(* cache_item)); + if (cache_item == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + msg = carray_get(env_list->msg_tab, i); + cache_item->uid = msg->msg_index; + cache_item->size = msg->msg_size; + + carray_set(data->imap_uid_list, i, cache_item); + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void check_for_uid_cache(mailsession * session) +{ +#if 0 + mailsession * imap; +#endif + mailimap * imap; +#if 0 + struct imap_session_state_data * imap_data; +#endif + clist * list; + clistiter * cur; + struct imap_cached_session_state_data * data; + unsigned int i; + unsigned dest; + + data = get_cached_data(session); +#if 0 + imap = get_ancestor(session); + + imap_data = imap->data; +#endif + + imap = get_imap_session(session); + + if (imap->imap_response_info == NULL) + return; + + list = imap->imap_response_info->rsp_expunged; + if (list == NULL) + return; + + dest = 0; + i = 0; + /* remove expunged */ + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t expunged; + + expunged = * (uint32_t *) clist_content(cur); + + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + if (dest + 1 == expunged) { + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + i ++; + break; + } + else { + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + } + } + /* complete list */ + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + carray_set_size(data->imap_uid_list, dest); +} + +static void imapdriver_cached_uninitialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + unsigned int i; + + data = get_cached_data(session); + + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + carray_free(data->imap_uid_list); + free_quoted_mb(data); + mailsession_free(data->imap_ancestor); + free(data); + + session->sess_data = NULL; +} + + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct imap_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->imap_cache_directory, value, PATH_MAX); + data->imap_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->imap_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + check_for_uid_cache(session); + + r = mailsession_connect_stream(get_ancestor(session), s); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_starttls(mailsession * session) +{ + int r; + + r = mailsession_starttls(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_login(mailsession * session, + char * userid, char * password) +{ + int r; + + r = mailsession_login(get_ancestor(session), userid, password); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_logout(mailsession * session) +{ + int r; + + r = mailsession_logout(get_ancestor(session)); + + check_for_uid_cache(session); + + if (r == MAIL_NO_ERROR) { + struct imap_cached_session_state_data * imap_cached_data; + + imap_cached_data = get_cached_data(session); + + free_quoted_mb(imap_cached_data); + } + + return r; +} + +static int imapdriver_cached_noop(mailsession * session) +{ + int r; + + r = mailsession_noop(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_build_folder_name(mailsession * session, + char * mb, + char * name, char ** result) +{ + int r; + + r = mailsession_build_folder_name(get_ancestor(session), mb, + name, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_create_folder(mailsession * session, char * mb) +{ + int r; + + r = mailsession_create_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_delete_folder(mailsession * session, char * mb) +{ + int r; + + r = mailsession_delete_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_rename_folder(mailsession * session, char * mb, + char * new_name) +{ + int r; + + r = mailsession_rename_folder(get_ancestor(session), mb, new_name); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_check_folder(mailsession * session) +{ + int r; + + r = mailsession_check_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_examine_folder(mailsession * session, + char * mb) +{ + int r; + + r = mailsession_examine_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int get_cache_folder(mailsession * session, char ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + char * mb; + char * cache_dir; + char * dirname; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; +#if 0 + struct imap_session_state_data * imap_data; + struct imap_cached_session_state_data * cached_data; +#endif + +#if 0 + imap_session = get_ancestor(session); + imap_data = imap_session->data; + imap = imap_data->session; +#endif + imap = get_imap_session(session); + + mb = get_ancestor_data(session)->imap_mailbox; + + cache_dir = get_cached_data(session)->imap_cache_directory; + + if (imap->imap_state != MAILIMAP_STATE_SELECTED) + return MAIL_ERROR_BAD_STATE; + + if (imap->imap_selection_info == NULL) + return MAIL_ERROR_BAD_STATE; + + quoted_mb = maildriver_quote_mailbox(mb); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb); + + dirname = strdup(key); + if (dirname == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dirname; + } + + free(quoted_mb); + + * result = dirname; + + return MAIL_NO_ERROR; + + free_dirname: + free(dirname); + free_mb: + free(quoted_mb); + err: + return res; +} + +static int imapdriver_cached_select_folder(mailsession * session, char * mb) +{ + int r; + char * quoted_mb; + struct imap_cached_session_state_data * data; + mailsession * imap; + char * old_mb; + + imap = get_ancestor(session); + + old_mb = get_ancestor_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + check_for_uid_cache(session); + + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) + return r; + + data = get_cached_data(session); + if (data->imap_quoted_mb != NULL) + free(data->imap_quoted_mb); + data->imap_quoted_mb = quoted_mb; + + /* clear UID cache */ + carray_set_size(data->imap_uid_list, 0); + + return MAIL_NO_ERROR; +} + +static int imapdriver_cached_expunge_folder(mailsession * session) +{ + int r; + + r = mailsession_expunge_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + + r = mailsession_status_folder(get_ancestor(session), mb, result_messages, + result_recent, result_unseen); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_messages_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_recent_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_unseen_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_list_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_lsub_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_subscribe_folder(mailsession * session, + char * mb) +{ + int r; + + r = mailsession_subscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + char * mb) +{ + int r; + + r = mailsession_unsubscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + + r = mailsession_append_message(get_ancestor(session), message, size); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, char * mb) +{ + int r; + + r = mailsession_copy_message(get_ancestor(session), num, mb); + + check_for_uid_cache(session); + + return r; +} + +static int cmp_uid(uint32_t ** pa, uint32_t ** pb) +{ + uint32_t * a; + uint32_t * b; + + a = * pa; + b = * pb; + + return * a - * b; +} + + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + uint32_t uid_max; + struct imap_cached_session_state_data * data; + struct mailmessage_list * env_list; + unsigned i; + int r; + int res; + carray * tab; + +#if 0 + data = session->data; + imap_session = get_ancestor(session); + imap = ((struct imap_session_state_data *) (imap_session->data))->session; +#endif + data = get_cached_data(session); + imap = get_imap_session(session); + + uid_max = 0; + +#ifdef CACHE_MESSAGE_LIST + /* get UID max */ + uid_max = 0; + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + if (cache_item->uid > uid_max) + uid_max = cache_item->uid; + } +#endif + + r = imap_get_messages_list(imap, session, imap_cached_message_driver, + uid_max + 1, &env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + +#ifdef CACHE_MESSAGE_LIST + /* remove unsollicited message */ + i = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_index < uid_max + 1) + carray_delete(env_list->msg_tab, i); + else + i ++; + } + + tab = carray_new(carray_count(env_list->msg_tab) + + carray_count(data->imap_uid_list)); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + carray_set_size(tab, + carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); + + /* sort cached data before adding them to the list */ + qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list), + sizeof(* carray_data(data->imap_uid_list)), + (int (*)(const void *, const void *)) cmp_uid); + + /* adds cached UID */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = carray_get(data->imap_uid_list, i); + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmessage_init(msg, session, imap_cached_message_driver, + cache_item->uid, cache_item->size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free; + } + + carray_set(tab, i, msg); + } + + /* adds new elements */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + carray_set(tab, carray_count(data->imap_uid_list) + i, msg); + } + + /* replace list of messages in env_list */ + carray_free(env_list->msg_tab); + env_list->msg_tab = tab; + + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } +#endif + + * result = env_list; + + return MAIL_NO_ERROR; + + free: + mailmessage_list_free(env_list); + err: + return res; +} + +static int get_flags_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + clist * msg_list; +#if 0 + struct imap_session_state_data * data; +#endif + unsigned i; + unsigned dest; + +#if 0 + data = session->data; +#endif + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + clist_free(msg_list); + mailimap_fetch_type_free(fetch_type); + return MAIL_NO_ERROR; + } + + r = msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + /* remove messages that don't have flags */ + i = 0; + dest = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_flags != NULL) { + carray_set(env_list->msg_tab, dest, msg); + dest ++; + } + else { + mailmessage_free(msg); + } + i ++; + } + carray_set_size(env_list->msg_tab, dest); + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +#define ENV_NAME "env.db" + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-part"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-envelope"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-rfc822"); + if (p != NULL) + * p = 0; +} + +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + int res; + uint32_t i; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + + data = get_cached_data(session); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + session, msg, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + } + + mail_cache_db_close_unlock(filename, cache_db); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = get_flags_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + +#ifdef CACHE_MESSAGE_LIST + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } +#endif + + /* must write cache */ + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + session, msg, msg->msg_fields); + } + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db, NULL, env_list); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num) +{ + int r; + + r = mailsession_remove_message(get_ancestor(session), num); + + check_for_uid_cache(session); + + return r; +} + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result) +{ + int r; + + r = mailsession_search_messages(get_ancestor(session), charset, key, result); + + check_for_uid_cache(session); + + return r; +} +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + * libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + * where UIDVALIDITY and UID are decimal representation of + * respectively uidvalidity and uid numbers. + * Return value: + * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + * MAIL_NO_ERROR if message was found. Result is in result + */ +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap *imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_cached_get_message(session, num, result); +} diff --git a/kmicromail/libetpan/generic/imapdriver_cached.h b/kmicromail/libetpan/generic/imapdriver_cached.h new file mode 100644 index 0000000..92bb60d --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_CACHED_H + +#define IMAPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * imap_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver_cached_message.c b/kmicromail/libetpan/generic/imapdriver_cached_message.c new file mode 100644 index 0000000..c0542a3 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_cached_message.c @@ -0,0 +1,664 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapdriver_cached_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver_message.h" +#include "imapdriver_cached.h" +#include "imapdriver_types.h" +#include "imapdriver.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "mail_cache_db.h" + +#include +#include + +static int imap_initialize(mailmessage * msg_info); + +static void imap_uninitialize(mailmessage * msg_info); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_imap_cached_message_driver = { + .msg_name = "imap-cached", + + .msg_initialize = imap_initialize, + .msg_uninitialize = imap_uninitialize, + + .msg_flush = imap_flush, + .msg_check = imap_check, + + .msg_fetch_result_free = imap_fetch_result_free, + + .msg_fetch = imap_fetch, + .msg_fetch_header = imap_fetch_header, + .msg_fetch_body = imap_fetch_body, + .msg_fetch_size = imap_fetch_size, + .msg_get_bodystructure = imap_get_bodystructure, + .msg_fetch_section = imap_fetch_section, + .msg_fetch_section_header = imap_fetch_section_header, + .msg_fetch_section_mime = imap_fetch_section_mime, + .msg_fetch_section_body = imap_fetch_section_body, + .msg_fetch_envelope = imap_fetch_envelope, + + .msg_get_flags = imap_get_flags, +}; + +mailmessage_driver * imap_cached_message_driver = +&local_imap_cached_message_driver; + +static inline struct imap_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailmessage * get_ancestor(mailmessage * msg_info) +{ + return msg_info->msg_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return cached_session_get_imap_session(msg->msg_session); +} + +static inline mailsession * get_ancestor_session(mailmessage * msg_info) +{ + return cached_session_get_ancestor(msg_info->msg_session); +} + + +static void generate_key_from_mime_section(char * key, size_t size, + struct mailmime * mime) +{ + clistiter * cur; + MMAPString * gstr; + struct mailmime_section * part; + int r; + + snprintf(key, size, "unvalid"); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + goto err; + + gstr = mmap_string_new("part"); + if (gstr == NULL) + goto free_section; + + for(cur = clist_begin(part->sec_list) ; + cur != NULL ; cur = clist_next(cur)) { + char s[20]; + + snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur)); + if (mmap_string_append(gstr, s) == NULL) + goto free_str; + } + + snprintf(key, size, "%s", gstr->str); + + mmap_string_free(gstr); + mailmime_section_free(part); + + return; + + free_str: + mmap_string_free(gstr); + free_section: + mailmime_section_free(part); + err: +} + +static void generate_key_from_section(char * key, size_t size, + mailmessage * msg_info, + struct mailmime * mime, int type) +{ + char section_str[PATH_MAX]; + + generate_key_from_mime_section(section_str, PATH_MAX, mime); + + switch (type) { + case IMAP_SECTION_MESSAGE: + snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_HEADER: + snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_MIME: + snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_BODY: + snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str); + break; + } +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + } +} + +static void build_cache_name(char * filename, size_t size, + mailmessage * msg, char * key) +{ + char * quoted_mb; + + quoted_mb = get_cached_session_data(msg)->imap_quoted_mb; + + snprintf(filename, size, "%s/%s", quoted_mb, key); +} + +static int imap_initialize(mailmessage * msg_info) +{ + mailmessage * ancestor; + int r; + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + ancestor = mailmessage_new(); + if (ancestor == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(ancestor, get_ancestor_session(msg_info), + imap_message_driver, + msg_info->msg_index, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(ancestor); + return r; + } + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + uid = strdup(key); + if (uid == NULL) { + mailmessage_free(ancestor); + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_data = ancestor; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void imap_uninitialize(mailmessage * msg_info) +{ + mailmessage_free(get_ancestor(msg_info)); + msg_info->msg_data = NULL; +} + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + get_ancestor(msg_info)->msg_flags = msg_info->msg_flags; + mailmessage_check(get_ancestor(msg_info)); + get_ancestor(msg_info)->msg_flags = NULL; +} + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + mailmessage_fetch_result_free(get_ancestor(msg_info), msg); +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch(get_ancestor(msg_info), + result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, strlen(* result)); + + return r; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_header(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_body(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return mailmessage_fetch_size(get_ancestor(msg_info), result); +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + r = mailmessage_get_bodystructure(get_ancestor(msg_info), + result); + if (r == MAIL_NO_ERROR) { + msg_info->msg_mime = get_ancestor(msg_info)->msg_mime; + get_ancestor(msg_info)->msg_mime = NULL; + } + + return r; +} + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MESSAGE); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_header(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MIME); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_mime(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_BODY); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_body(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + r = mailmessage_get_flags(get_ancestor(msg_info), &flags); + if (r != MAIL_NO_ERROR) + return r; + + get_ancestor(msg_info)->msg_flags = NULL; + msg_info->msg_flags = flags; + * result = flags; + + return MAIL_NO_ERROR; +} + +#define ENV_NAME "env.db" + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + struct mailimf_fields * fields; + int r; + struct mail_cache_db * cache_db; + MMAPString * mmapstr; + char filename[PATH_MAX]; + struct imap_cached_session_state_data * data; + int res; + + data = get_cached_session_data(msg_info); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, &fields); + + if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) { + res = r; + goto close_db; + } + + r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, fields); + + * result = fields; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename, cache_db); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, cache_db); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/imapdriver_cached_message.h b/kmicromail/libetpan/generic/imapdriver_cached_message.h new file mode 100644 index 0000000..49d63cb --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_CACHED_MESSAGE_H + +#define IMAPDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver_message.c b/kmicromail/libetpan/generic/imapdriver_message.c new file mode 100644 index 0000000..47c7f78 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_message.c @@ -0,0 +1,1239 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapdriver_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver.h" +#include "imapdriver_types.h" +#include "mailimap.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include +#include + +static int imap_initialize(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static mailmessage_driver local_imap_message_driver = { + .msg_name = "imap", + + .msg_initialize = imap_initialize, + .msg_uninitialize = NULL, + + .msg_flush = imap_flush, + .msg_check = imap_check, + + .msg_fetch_result_free = imap_fetch_result_free, + + .msg_fetch = imap_fetch, + .msg_fetch_header = imap_fetch_header, + .msg_fetch_body = imap_fetch_body, + .msg_fetch_size = imap_fetch_size, + .msg_get_bodystructure = imap_get_bodystructure, + .msg_fetch_section = imap_fetch_section, + .msg_fetch_section_header = imap_fetch_section_header, + .msg_fetch_section_mime = imap_fetch_section_mime, + .msg_fetch_section_body = imap_fetch_section_body, + .msg_fetch_envelope = imap_fetch_envelope, + + .msg_get_flags = imap_get_flags, +}; + +mailmessage_driver * imap_message_driver = &local_imap_message_driver; + +static inline struct imap_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return get_session_data(msg)->imap_session; +} + + + +static int imap_initialize(mailmessage * msg_info) +{ + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + + uid = strdup(key); + if (uid == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg != NULL) { + if (mmap_string_unref(msg) != 0) + free(msg); + } +} + + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new(NULL); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) { + text = msg_att_item->msg_att_static->rfc822; + msg_att_item->msg_att_static->rfc822 = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + /* detach */ + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_header(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), + set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new_header(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_HEADER) { + text = msg_att_item->msg_att_static->rfc822_header; + msg_att_item->msg_att_static->rfc822_header = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_text(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + section = mailimap_section_new_text(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_TEXT) { + text = msg_att_item->msg_att_static->rfc822_text; + msg_att_item->msg_att_static->rfc822_text = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + size_t size; + int res; + clistiter * cur; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + case MAILIMAP_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_RFC822_SIZE) { + size = msg_att_item->att_data.att_static->att_data.att_rfc822_size; + + * result = size; + + mailimap_fetch_list_free(fetch_result); + return MAIL_NO_ERROR; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + return MAIL_ERROR_FETCH; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_body * imap_body; + struct mailmime * body; + int res; + struct mailimf_fields * fields; + struct mailmime * new_body; + struct mailmime_content * content_message; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + clistiter * cur; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_bodystructure(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + uid = 0; + references = NULL; + ref_size = 0; + imap_body = NULL; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, &envelope, &references, &ref_size, NULL, &imap_body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + if (imap_body == NULL) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_body_to_body(imap_body, &body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + + new_body = mailmime_new(MAILMIME_MESSAGE, NULL, + 0, NULL, content_message, + NULL, NULL, NULL, NULL, fields, body); + + if (new_body == NULL) { + mailmime_content_free(content_message); + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + msg_info->msg_mime = new_body; + + mailimap_fetch_list_free(fetch_result); + + * result = new_body; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int +fetch_imap(mailmessage * msg, + struct mailimap_fetch_type * fetch_type, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + clist * fetch_result; + struct mailimap_set * set; + char * text; + size_t text_length; + clistiter * cur; + + set = mailimap_set_new_single(msg->msg_index); + if (set == NULL) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_fetch(get_imap_session(msg), set, + fetch_type, &fetch_result); + + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_HEADER, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return MAIL_ERROR_INVAL; + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_MIME, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_BODY, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + r = imap_fetch_flags(get_imap_session(msg_info), + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + return r; + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + int res; + struct mailimf_fields * fields; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + uid = 0; + references = NULL; + ref_size = 0; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, + &envelope, + &references, + &ref_size, + NULL, + NULL); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + mailimap_fetch_list_free(fetch_result); + + * result = fields; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/imapdriver_message.h b/kmicromail/libetpan/generic/imapdriver_message.h new file mode 100644 index 0000000..9142633 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_MESSAGE_H + +#define IMAPDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver_tools.c b/kmicromail/libetpan/generic/imapdriver_tools.c new file mode 100644 index 0000000..3d737f3 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_tools.c @@ -0,0 +1,3599 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapdriver_tools.h" + +#include "maildriver.h" + +#include +#include + +#include "mail.h" +#include "imapdriver_types.h" +#include "maildriver_tools.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + + + +static inline struct imap_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result); + + +int imap_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMAP_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMAP_NO_ERROR_AUTHENTICATED: + return MAIL_NO_ERROR_AUTHENTICATED; + + case MAILIMAP_NO_ERROR_NON_AUTHENTICATED: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILIMAP_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMAP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMAP_ERROR_FATAL: + return MAIL_ERROR_FATAL; + + case MAILIMAP_ERROR_PROTOCOL: + return MAIL_ERROR_PROTOCOL; + + case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_APPEND: + return MAIL_ERROR_APPEND; + + case MAILIMAP_ERROR_NOOP: + return MAIL_ERROR_NOOP; + + case MAILIMAP_ERROR_LOGOUT: + return MAIL_ERROR_LOGOUT; + + case MAILIMAP_ERROR_CAPABILITY: + return MAIL_ERROR_CAPABILITY; + + case MAILIMAP_ERROR_CHECK: + return MAIL_ERROR_CHECK; + + case MAILIMAP_ERROR_CLOSE: + return MAIL_ERROR_CLOSE; + + case MAILIMAP_ERROR_EXPUNGE: + return MAIL_ERROR_EXPUNGE; + + case MAILIMAP_ERROR_COPY: + case MAILIMAP_ERROR_UID_COPY: + return MAIL_ERROR_COPY; + + case MAILIMAP_ERROR_CREATE: + return MAIL_ERROR_CREATE; + + case MAILIMAP_ERROR_DELETE: + return MAIL_ERROR_DELETE; + + case MAILIMAP_ERROR_EXAMINE: + return MAIL_ERROR_EXAMINE; + + case MAILIMAP_ERROR_FETCH: + case MAILIMAP_ERROR_UID_FETCH: + return MAIL_ERROR_FETCH; + + case MAILIMAP_ERROR_LIST: + return MAIL_ERROR_LIST; + + case MAILIMAP_ERROR_LOGIN: + return MAIL_ERROR_LOGIN; + + case MAILIMAP_ERROR_LSUB: + return MAIL_ERROR_LSUB; + + case MAILIMAP_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILIMAP_ERROR_SEARCH: + case MAILIMAP_ERROR_UID_SEARCH: + return MAIL_ERROR_SEARCH; + + case MAILIMAP_ERROR_SELECT: + return MAIL_ERROR_SELECT; + + case MAILIMAP_ERROR_STATUS: + return MAIL_ERROR_STATUS; + + case MAILIMAP_ERROR_STORE: + case MAILIMAP_ERROR_UID_STORE: + return MAIL_ERROR_STORE; + + case MAILIMAP_ERROR_SUBSCRIBE: + return MAIL_ERROR_SUBSCRIBE; + + case MAILIMAP_ERROR_UNSUBSCRIBE: + return MAIL_ERROR_UNSUBSCRIBE; + + case MAILIMAP_ERROR_STARTTLS: + return MAIL_ERROR_STARTTLS; + + case MAILIMAP_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result); + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result); + + +int imap_list_to_list(clist * imap_list, struct mail_list ** result) +{ + clistiter * cur; + clist * list; + struct mail_list * resp; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_mailbox_list * mb_list; + char * new_mb; + + mb_list = clist_content(cur); + + new_mb = strdup(mb_list->mb_name); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_mb); + if (r != 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + resp = mail_list_new(list); + if (resp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = resp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +int +section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result) +{ + struct mailimap_section_part * section_part; + struct mailimap_section * imap_section; + clist * list; + clistiter * cur; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(section->sec_list) ; cur != NULL ; + cur = clist_next(cur)) { + uint32_t value; + uint32_t * id; + + value = * (uint32_t *) clist_content(cur); + id = malloc(sizeof(* id)); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + * id = value; + r = clist_append(list, id); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + free(id); + goto free_list; + } + } + + section_part = mailimap_section_part_new(list); + if (section_part == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + imap_section = NULL; + + switch (type) { + case IMAP_SECTION_MESSAGE: + imap_section = mailimap_section_new_part(section_part); + break; + case IMAP_SECTION_HEADER: + imap_section = mailimap_section_new_part_header(section_part); + break; + case IMAP_SECTION_MIME: + imap_section = mailimap_section_new_part_mime(section_part); + break; + case IMAP_SECTION_BODY: + imap_section = mailimap_section_new_part_text(section_part); + break; + } + + if (imap_section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_part; + } + + * result = imap_section; + + return MAIL_NO_ERROR; + + free_part: + mailimap_section_part_free(section_part); + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +imap_body_media_basic_to_content_type(struct mailimap_media_basic * + media_basic, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + char * discrete_type_extension; + int discrete_type_type; + int composite_type_type; + int mime_type_type; + char * subtype; + int r; + int res; + + discrete_type = NULL; + composite_type = NULL; + discrete_type_extension = NULL; + subtype = NULL; + discrete_type_type = 0; + composite_type_type = 0; + mime_type_type = 0; + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION; + break; + + case MAILIMAP_MEDIA_BASIC_AUDIO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION; + break; + + case MAILIMAP_MEDIA_BASIC_IMAGE: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE; + break; + + case MAILIMAP_MEDIA_BASIC_MESSAGE: + mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE; + composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + break; + + case MAILIMAP_MEDIA_BASIC_VIDEO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO; + break; + + case MAILIMAP_MEDIA_BASIC_OTHER: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION; + discrete_type_extension = media_basic->med_basic_type; + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (mime_type_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + if (discrete_type_extension != NULL) { + discrete_type_extension = strdup(discrete_type_extension); + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + discrete_type = mailmime_discrete_type_new(discrete_type_type, + discrete_type_extension); + if (discrete_type == NULL) { + if (discrete_type_extension != NULL) + free(discrete_type_extension); + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + composite_type = mailmime_composite_type_new(composite_type_type, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type); + if (mime_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +static int +imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp, + struct mailmime_disposition ** result) +{ + size_t cur_token; + int r; + struct mailmime_disposition_type * dsp_type; + struct mailmime_disposition * dsp; + clist * parameters; + int res; + + cur_token = 0; + r = mailmime_disposition_type_parse(imap_dsp->dsp_type, + strlen(imap_dsp->dsp_type), &cur_token, &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (imap_dsp->dsp_attributes != NULL) { + clistiter * cur; + + for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_disposition_parm * dsp_param; + struct mailmime_parameter * param; + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + int type; + + imap_param = clist_content(cur); + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + param = NULL; + + type = mailmime_disposition_guess_type(imap_param->pa_name, + strlen(imap_param->pa_name), 0); + + switch (type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + if (strcasecmp(imap_param->pa_name, "filename") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + filename = strdup(imap_param->pa_value); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + if (strcasecmp(imap_param->pa_name, "creation-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + creation_date = strdup(imap_param->pa_value); + if (creation_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + if (strcasecmp(imap_param->pa_name, "modification-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + modification_date = strdup(imap_param->pa_value); + if (modification_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + if (strcasecmp(imap_param->pa_name, "read-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + read_date = strdup(imap_param->pa_value); + if (read_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + if (strcasecmp(imap_param->pa_name, "size") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + size = strtoul(imap_param->pa_value, NULL, 10); + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + char * name; + char * value; + + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + res = MAIL_ERROR_MEMORY; + free(name); + goto free_dsp_type; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + } + + dsp_param = mailmime_disposition_parm_new(type, filename, + creation_date, + modification_date, + read_date, + size, param); + if (dsp_param == NULL) { + if (filename != NULL) + free(filename); + if (creation_date != NULL) + free(creation_date); + if (modification_date != NULL) + free(modification_date); + if (read_date != NULL) + free(read_date); + if (param != NULL) + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(parameters, dsp_param); + if (r != 0) { + mailmime_disposition_parm_free(dsp_param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + dsp = mailmime_disposition_new(dsp_type, parameters); + if (dsp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(parameters, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(parameters); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +static int +imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang, + struct mailmime_language ** result) +{ + clist * list; + clistiter * cur; + int res; + char * single; + int r; + struct mailmime_language * lang; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + switch (imap_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + if (imap_lang->lg_data.lg_single != NULL) { + single = strdup(imap_lang->lg_data.lg_single); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(imap_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + single = strdup(clist_content(cur)); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + lang = mailmime_language_new(list); + if (lang == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = lang; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields, + struct mailimap_body_fld_dsp * imap_dsp, + struct mailimap_body_fld_lang * imap_lang, + struct mailmime_fields ** result, + uint32_t * pbody_size) +{ + struct mailmime_field * mime_field; + struct mailmime_fields * mime_fields; + clist * list; + char * id; + struct mailmime_mechanism * encoding; + char * description; + struct mailmime_disposition * dsp; + struct mailmime_language * lang; + int type; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (body_fields != NULL) { + + if (pbody_size != NULL) + * pbody_size = body_fields->bd_size; + + if (body_fields->bd_id != NULL) { + type = MAILMIME_FIELD_ID; + id = strdup(body_fields->bd_id); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, id, NULL, 0, NULL, NULL); + if (mime_field == NULL) { + free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_description != NULL) { + type = MAILMIME_FIELD_DESCRIPTION; + description = strdup(body_fields->bd_description); + if (description == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, description, 0, NULL, NULL); + if (mime_field == NULL) { + free(description); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_encoding != NULL) { + char * encoding_value; + int encoding_type; + + type = MAILMIME_FIELD_TRANSFER_ENCODING; + + encoding_value = NULL; + switch (body_fields->bd_encoding->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + encoding_type = MAILMIME_MECHANISM_7BIT; + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + encoding_type = MAILMIME_MECHANISM_8BIT; + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + encoding_type = MAILMIME_MECHANISM_BINARY; + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + encoding_type = MAILMIME_MECHANISM_BASE64; + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + encoding_type = MAILMIME_MECHANISM_TOKEN; + encoding_value = strdup(body_fields->bd_encoding->enc_value); + if (encoding_value == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + default: + res = MAIL_ERROR_INVAL; + goto free_list; + } + + encoding = mailmime_mechanism_new(encoding_type, encoding_value); + if (encoding == NULL) { + if (encoding_value != NULL) + free(encoding_value); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + encoding, NULL, NULL, 0, NULL, NULL); + if (mime_field == NULL) { + mailmime_mechanism_free(encoding); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_dsp != NULL) { + r = imap_disposition_to_mime_disposition(imap_dsp, &dsp); + if (r != MAIL_ERROR_PARSE) { + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_DISPOSITION; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, dsp, NULL); + if (mime_field == NULL) { + mailmime_disposition_free(dsp); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_lang != NULL) { + r = imap_language_to_mime_language(imap_lang, &lang); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_LANGUAGE; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, NULL, lang); + if (mime_field == NULL) { + mailmime_language_free(lang); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_fields_free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_type_basic_to_body(struct mailimap_body_type_basic * + imap_type_basic, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic, + imap_type_basic->bd_fields->bd_parameter, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part != NULL) + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + &mime_fields, &mime_size); + else + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + NULL, NULL, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_type_text_to_body(struct mailimap_body_type_text * + imap_type_text, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text, + imap_type_text->bd_fields->bd_parameter, + &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part == NULL) { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + NULL, NULL, + &mime_fields, &mime_size); + } + else { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + &mime_fields, &mime_size); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result) +{ + clist * parameters; + char * new_subtype; + struct mailmime_content * content; + int r; + int res; + + new_subtype = strdup(subtype); + if (new_subtype == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subtype; + } + + if (body_parameter != NULL) { + clistiter * cur; + + for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_parameter * param; + char * name; + char * value; + + imap_param = clist_content(cur); + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + r = clist_append(parameters, param); + if (r != 0) { + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + } + } + + content = mailmime_content_new(mime_type, new_subtype, parameters); + if (content == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_parameters: + clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters); + free_subtype: + free(new_subtype); + err: + return res; +} + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + int r; + int res; + + discrete_type = NULL; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) { + mailmime_discrete_type_free(discrete_type); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = imap_body_parameter_to_content(body_parameter, subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + err: + return res; +} + + +static int +imap_body_type_msg_to_body(struct mailimap_body_type_msg * + imap_type_msg, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime * body; + struct mailmime * msg_body; + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailimf_fields * fields; + int r; + int res; + uint32_t mime_size; + + r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields, + body_ext_1part->bd_disposition, body_ext_1part->bd_language, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mime_fields; + } + + r = imap_body_to_body(imap_type_msg->bd_body, &msg_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fields; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter, + "rfc822", mime_type, &content_type); + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + body = mailmime_new(MAILMIME_MESSAGE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, NULL, fields, msg_body); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_content: + mailmime_content_free(content_type); + free_fields: + mailimf_fields_free(fields); + free_mime_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +static int +imap_body_type_1part_to_body(struct mailimap_body_type_1part * + type_1part, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + switch (type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_body_type_mpart_to_body(struct mailimap_body_type_mpart * + type_mpart, + struct mailmime ** result) +{ + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailmime * body; + clistiter * cur; + clist * list; + int r; + int res; + uint32_t mime_size; + + r = imap_body_fields_to_mime_fields(NULL, + type_mpart->bd_ext_mpart->bd_disposition, + type_mpart->bd_ext_mpart->bd_language, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter, + type_mpart->bd_media_subtype, + mime_type, &content_type); + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = r; + goto free_fields; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * imap_body; + struct mailmime * sub_body; + + imap_body = clist_content(cur); + + r = imap_body_to_body(imap_body, &sub_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, sub_body); + if (r != 0) { + mailmime_free(sub_body); + res = r; + goto free_list; + } + } + + body = mailmime_new(MAILMIME_MULTIPLE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, list, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + free_content: + mailmime_content_free(content_type); + free_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + switch (imap_body->bd_type) { + case MAILIMAP_BODY_1PART: + r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMAP_BODY_MPART: + r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + default: + return MAIL_ERROR_INVAL; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int imap_address_to_mailbox(struct mailimap_address * imap_addr, + struct mailimf_mailbox ** result) +{ + char * dsp_name; + char * addr; + struct mailimf_mailbox * mb; + int res; + + if (imap_addr->ad_personal_name == NULL) + dsp_name = NULL; + else { + dsp_name = strdup(imap_addr->ad_personal_name); + if (dsp_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + if (imap_addr->ad_host_name == NULL) { + addr = strdup(imap_addr->ad_mailbox_name); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + } + else { + addr = malloc(strlen(imap_addr->ad_mailbox_name) + + strlen(imap_addr->ad_host_name) + 2); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + strcpy(addr, imap_addr->ad_mailbox_name); + strcat(addr, "@"); + strcat(addr, imap_addr->ad_host_name); + } + + mb = mailimf_mailbox_new(dsp_name, addr); + if (mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_addr; + } + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr); + free_name: + free(dsp_name); + err: + return res; +} + +int imap_address_to_address(struct mailimap_address * imap_addr, + struct mailimf_address ** result) +{ + struct mailimf_address * addr; + struct mailimf_mailbox * mb; + int r; + int res; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + * result = addr; + + return MAIL_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +int +imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list, + struct mailimf_mailbox_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_mailbox_list * mb_list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return MAIL_ERROR_MEMORY; +} + + + +/* + at exit, imap_mb_list will fall on the last element of the group, + where mailbox name will be NIL, so that imap_mailbox_list_to_address_list + can continue +*/ + +static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter, + struct mailimf_group ** result) +{ + clistiter * imap_mailbox_listiter; + clist * list; + struct mailimf_group * group; + struct mailimap_address * imap_addr; + char * group_name; + clistiter * cur; + struct mailimf_mailbox_list * mb_list; + int r; + int res; + + imap_mailbox_listiter = * iter; + + imap_addr = clist_content(imap_mailbox_listiter); + if (imap_addr->ad_mailbox_name == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + group_name = strdup(imap_addr->ad_mailbox_name); + if (group_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) { + break; + } + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + group = mailimf_group_new(group_name, mb_list); + if (group == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + * result = group; + * iter = cur; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + free_group_name: + free(group_name); + err: + return res; +} + +int +imap_mailbox_list_to_address_list(clist * imap_mailbox_list, + struct mailimf_address_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_address_list * addr_list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_address * addr; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + if ((imap_addr->ad_host_name == NULL) && + (imap_addr->ad_mailbox_name != NULL)) { + struct mailimf_group * group; + + r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group); + if (addr == NULL) { + mailimf_group_free(group); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + r = imap_address_to_address(imap_addr, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + r = clist_append(list, addr); + if (r != 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type) +{ + struct mailimap_fetch_att * fetch_att; + int res; + int r; + char * header; + clist * hdrlist; + struct mailimap_header_list * imap_hdrlist; + struct mailimap_section * section; + + fetch_att = mailimap_fetch_att_new_envelope(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + header = strdup("References"); + if (header == NULL) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + hdrlist = clist_new(); + if (hdrlist == NULL) { + free(header); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = clist_append(hdrlist, header); + if (r < 0) { + free(header); + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + imap_hdrlist = mailimap_header_list_new(hdrlist); + if (imap_hdrlist == 0) { + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + section = mailimap_section_new_header_fields(imap_hdrlist); + if (section == NULL) { + mailimap_header_list_free(imap_hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result) +{ + clist * list; + struct mailimf_field * field; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (env->env_date != NULL) { + size_t cur_token; + struct mailimf_date_time * date_time; + + cur_token = 0; + r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), + &cur_token, &date_time); + + if (r == MAILIMF_NO_ERROR) { + struct mailimf_orig_date * orig; + + orig = mailimf_orig_date_new(date_time); + if (orig == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_subject != NULL) { + char * subject; + struct mailimf_subject * subject_field; + + subject = strdup(env->env_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + + subject_field = mailimf_subject_new(subject); + if (subject_field == NULL) { + free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject_field, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (env->env_from != NULL) { + if (env->env_from->frm_list != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_sender != NULL) { + if (env->env_sender->snd_list != NULL) { + struct mailimf_sender * sender; + struct mailimf_mailbox * mb; + + r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + sender, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_sender_free(sender); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_reply_to != NULL) { + if (env->env_reply_to->rt_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, reply_to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_reply_to_free(reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_to != NULL) { + if (env->env_to->to_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, to, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_to_free(to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_cc != NULL) { + if (env->env_cc->cc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, cc, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_cc_free(cc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_bcc != NULL) { + if (env->env_bcc->bcc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, bcc, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_bcc_free(bcc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_in_reply_to != NULL) { + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + + cur_token = 0; + r = mailimf_msg_id_list_parse(env->env_in_reply_to, + strlen(env->env_in_reply_to), &cur_token, &msg_id_list); + + switch (r) { + case MAILIMF_NO_ERROR: + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + in_reply_to, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_in_reply_to_free(in_reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (env->env_message_id != NULL) { + char * id; + struct mailimf_message_id * msg_id; + size_t cur_token; + + cur_token = 0; + r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), + &cur_token, &id); + switch (r) { + case MAILIMF_NO_ERROR: + + msg_id = mailimf_message_id_new(id); + if (msg_id == NULL) { + mailimf_msg_id_free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msg_id, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_message_id_free(msg_id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (ref_str != NULL) { + struct mailimf_references * references; + size_t cur_token; + + cur_token = 0; + r = mailimf_references_parse(ref_str, ref_size, + &cur_token, &references); + switch (r) { + case MAILIMF_NO_ERROR: + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + references, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_references_free(references); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body) +{ + clistiter * item_cur; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + char * references; + size_t ref_size; + struct mailimap_msg_att_dynamic * att_dyn; + struct mailimap_body * imap_body; + + uid = 0; + imap_envelope = NULL; + references = NULL; + ref_size = 0; + att_dyn = NULL; + imap_body = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (imap_body == NULL) + imap_body = item->att_data.att_static->att_data.att_bodystructure; + break; + + case MAILIMAP_MSG_ATT_ENVELOPE: + if (imap_envelope == NULL) { + imap_envelope = item->att_data.att_static->att_data.att_env; + } + break; + + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (references == NULL) { + references = item->att_data.att_static->att_data.att_body_section->sec_body_part; + ref_size = item->att_data.att_static->att_data.att_body_section->sec_length; + } + break; + } + break; + + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + break; + } + } + + if (puid != NULL) + * puid = uid; + if (pimap_envelope != NULL) + * pimap_envelope = imap_envelope; + if (preferences != NULL) + * preferences = references; + if (pref_size != NULL) + * pref_size = ref_size; + if (patt_dyn != NULL) + * patt_dyn = att_dyn; + if (pimap_body != NULL) + * pimap_body = imap_body; + + return MAIL_NO_ERROR; +} + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list) +{ + clistiter * cur; + int r; + unsigned int i; + + i = 0; + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + struct mailimap_msg_att_dynamic * att_dyn; + char * references; + size_t ref_size; + + msg_att = clist_content(cur); + + r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope, + &references, &ref_size, + &att_dyn, + NULL); + + if (r == MAIL_NO_ERROR) { + if (uid != 0) { + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (uid == msg->msg_index) { + struct mailimf_fields * fields; + struct mail_flags * flags; + + if (imap_envelope != NULL) { + r = imap_env_to_fields(imap_envelope, + references, ref_size, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + } + } + + if (att_dyn != NULL) { + r = imap_flags_to_flags(att_dyn, &flags); + + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + + i ++; + break; + } + + i ++; + } + } + } + } + + return MAIL_NO_ERROR; +} + + +int mailimf_date_time_to_imap_date(struct mailimf_date_time * date, + struct mailimap_date ** result) +{ + struct mailimap_date * imap_date; + + imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year); + if (imap_date == NULL) + return MAIL_ERROR_MEMORY; + + * result = imap_date; + + return MAIL_NO_ERROR; +} + + +#if 0 +int mail_search_to_imap_search(struct mail_search_key * key, + struct mailimap_search_key ** result) +{ + struct mailimap_search_key * imap_key; + + char * bcc; + struct mailimap_date * before; + char * body; + char * cc; + char * from; + struct mailimap_date * on; + struct mailimap_date * since; + char * subject; + char * text; + char * to; + char * header_name; + char * header_value; + size_t larger; + struct mailimap_search_key * not; + struct mailimap_search_key * or1; + struct mailimap_search_key * or2; + size_t smaller; + clist * multiple; + int type; + clistiter * cur; + int r; + int res; + + bcc = NULL; + before = NULL; + body = NULL; + cc = NULL; + from = NULL; + on = NULL; + since = NULL; + subject = NULL; + text = NULL; + to = NULL; + header_name = NULL; + header_value = NULL; + not = NULL; + or1 = NULL; + or2 = NULL; + multiple = NULL; + larger = 0; + smaller = 0; + + switch (key->sk_type) { + case MAIL_SEARCH_KEY_ALL: + type = MAILIMAP_SEARCH_KEY_ALL; + break; + + case MAIL_SEARCH_KEY_ANSWERED: + type = MAILIMAP_SEARCH_KEY_ANSWERED; + break; + + case MAIL_SEARCH_KEY_BCC: + type = MAILIMAP_SEARCH_KEY_BCC; + bcc = strdup(key->sk_bcc); + if (bcc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BEFORE: + type = MAILIMAP_SEARCH_KEY_BEFORE; + r = mailimf_date_time_to_imap_date(key->sk_before, &before); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BODY: + type = MAILIMAP_SEARCH_KEY_BODY; + body = strdup(key->sk_body); + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_CC: + type = MAILIMAP_SEARCH_KEY_CC; + cc = strdup(key->sk_cc); + if (cc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_DELETED: + type = MAILIMAP_SEARCH_KEY_DELETED; + break; + + case MAIL_SEARCH_KEY_FLAGGED: + type = MAILIMAP_SEARCH_KEY_FLAGGED; + break; + + case MAIL_SEARCH_KEY_FROM: + type = MAILIMAP_SEARCH_KEY_FROM; + from = strdup(key->sk_from); + if (from == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_NEW: + type = MAILIMAP_SEARCH_KEY_NEW; + break; + + case MAIL_SEARCH_KEY_OLD: + type = MAILIMAP_SEARCH_KEY_OLD; + break; + + case MAIL_SEARCH_KEY_ON: + type = MAILIMAP_SEARCH_KEY_ON; + r = mailimf_date_time_to_imap_date(key->sk_on, &on); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_RECENT: + type = MAILIMAP_SEARCH_KEY_RECENT; + break; + + case MAIL_SEARCH_KEY_SEEN: + type = MAILIMAP_SEARCH_KEY_SEEN; + break; + + case MAIL_SEARCH_KEY_SINCE: + type = MAILIMAP_SEARCH_KEY_SINCE; + r = mailimf_date_time_to_imap_date(key->sk_since, &since); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SUBJECT: + type = MAILIMAP_SEARCH_KEY_SUBJECT; + subject = strdup(key->sk_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TEXT: + type = MAILIMAP_SEARCH_KEY_TEXT; + text = strdup(key->sk_text); + if (text == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TO: + type = MAILIMAP_SEARCH_KEY_TO; + to = strdup(key->sk_to); + if (to == NULL) { + return MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_UNANSWERED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNDELETED: + type = MAILIMAP_SEARCH_KEY_UNFLAGGED; + break; + + case MAIL_SEARCH_KEY_UNFLAGGED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNSEEN: + type = MAILIMAP_SEARCH_KEY_UNSEEN; + break; + + case MAIL_SEARCH_KEY_HEADER: + type = MAILIMAP_SEARCH_KEY_HEADER; + header_name = strdup(key->sk_header_name); + if (header_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + header_value = strdup(key->sk_header_value); + if (header_value == NULL) { + free(header_name); + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_LARGER: + type = MAILIMAP_SEARCH_KEY_LARGER; + larger = key->sk_larger; + break; + + case MAIL_SEARCH_KEY_NOT: + type = MAILIMAP_SEARCH_KEY_NOT; + r = mail_search_to_imap_search(key->sk_not, ¬); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_OR: + type = MAILIMAP_SEARCH_KEY_OR; + r = mail_search_to_imap_search(key->sk_or1, &or1); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + r = mail_search_to_imap_search(key->sk_or2, &or2); + if (r != MAIL_NO_ERROR) { + mailimap_search_key_free(or1); + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SMALLER: + type = MAILIMAP_SEARCH_KEY_SMALLER; + smaller = key->sk_smaller; + break; + + case MAIL_SEARCH_KEY_MULTIPLE: + multiple = clist_new(); + if (multiple == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + type = MAILIMAP_SEARCH_KEY_MULTIPLE; + for(cur = clist_begin(key->sk_multiple) ; cur != NULL ; + cur = clist_next(cur)) { + struct mail_search_key * key_elt; + struct mailimap_search_key * imap_key_elt; + + key_elt = clist_content(cur); + r = mail_search_to_imap_search(key_elt, &imap_key_elt); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(multiple, imap_key_elt); + if (r != 0) { + mailimap_search_key_free(imap_key_elt); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + break; + + free_list: + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + goto err; + + default: + return MAIL_ERROR_INVAL; + } + + imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from, + NULL, on, since, subject, text, + to, NULL, header_name, + header_value, larger, not, or1, or2, + NULL, NULL, NULL, smaller, NULL, + NULL, multiple); + if (imap_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = imap_key; + + return MAIL_NO_ERROR; + + free: + if (bcc != NULL) + free(bcc); + if (before != NULL) + mailimap_date_free(before); + if (body != NULL) + free(body); + if (cc != NULL) + free(cc); + if (from != NULL) + free(from); + if (on != NULL) + mailimap_date_free(on); + if (since != NULL) + mailimap_date_free(since); + if (subject != NULL) + free(subject); + if (text != NULL) + free(text); + if (to != NULL) + free(to); + if (header_name != NULL) + free(header_name); + if (header_value != NULL) + free(header_value); + if (not != NULL) + mailimap_search_key_free(not); + if (or1 != NULL) + mailimap_search_key_free(or1); + if (or2 != NULL) + mailimap_search_key_free(or2); + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + err: + return res; +} +#endif + + +int msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result) +{ + struct mailimap_set * imap_set; + clistiter * cur; + int previous_valid; + uint32_t first_seq; + uint32_t previous; + int r; + int res; + + imap_set = mailimap_set_new_empty(); + if (imap_set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur = clist_begin(msg_list); + previous_valid = FALSE; + first_seq = 0; + previous = 0; + while (1) { + uint32_t * pindex; + + if ((cur == NULL) && (previous_valid)) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + break; + } + + pindex = clist_content(cur); + + if (!previous_valid) { + first_seq = * pindex; + previous_valid = TRUE; + previous = * pindex; + cur = clist_next(cur); + } + else { + if (* pindex != previous + 1) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + previous_valid = FALSE; + } + else { + previous = * pindex; + cur = clist_next(cur); + } + } + } + + * result = imap_set; + + return MAIL_NO_ERROR; + + free: + mailimap_set_free(imap_set); + err: + return res; +} + + +static int +uid_list_to_env_list(clist * fetch_result, + struct mailmessage_list ** result, + mailsession * session, mailmessage_driver * driver) +{ + clistiter * cur; + struct mailmessage_list * env_list; + int r; + int res; + carray * tab; + unsigned int i; + mailmessage * msg; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + size_t size; + + msg_att = clist_content(cur); + + uid = 0; + size = 0; + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + size = item->att_data.att_static->att_data.att_rfc822_size; + break; + } + break; + } + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, uid, size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_msg; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_msg: + mailmessage_free(msg); + free_list: + for(i = 0 ; i < carray_count(tab) ; i++) + mailmessage_free(carray_get(tab, i)); + err: + return res; +} + + +/* + MAILIMAP_FLAG_FETCH_RECENT, + MAILIMAP_FLAG_FETCH_OTHER + + MAILIMAP_FLAG_ANSWERED, + MAILIMAP_FLAG_FLAGGED, + MAILIMAP_FLAG_DELETED, + MAILIMAP_FLAG_SEEN, + MAILIMAP_FLAG_DRAFT, + MAILIMAP_FLAG_KEYWORD, + MAILIMAP_FLAG_EXTENSION +*/ + +static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result) +{ + struct mail_flags * flags; + clist * flag_list; + clistiter * cur; + + flags = mail_flags_new_empty(); + if (flags == NULL) + goto err; + flags->fl_flags = 0; + + flag_list = att_dyn->att_list; + if (flag_list != NULL) { + for(cur = clist_begin(flag_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = clist_content(cur); + if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT) + flags->fl_flags |= MAIL_FLAG_NEW; + else { + char * keyword; + int r; + + switch (flag_fetch->fl_flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + flags->fl_flags |= MAIL_FLAG_ANSWERED; + break; + case MAILIMAP_FLAG_FLAGGED: + flags->fl_flags |= MAIL_FLAG_FLAGGED; + break; + case MAILIMAP_FLAG_DELETED: + flags->fl_flags |= MAIL_FLAG_DELETED; + break; + case MAILIMAP_FLAG_SEEN: + flags->fl_flags |= MAIL_FLAG_SEEN; + break; + case MAILIMAP_FLAG_DRAFT: + keyword = strdup("Draft"); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + break; + case MAILIMAP_FLAG_KEYWORD: + if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, + "$Forwarded") == 0) { + flags->fl_flags |= MAIL_FLAG_FORWARDED; + } + else { + keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + } + break; + case MAILIMAP_FLAG_EXTENSION: + /* do nothing */ + break; + } + } + } + /* + MAIL_FLAG_NEW was set for \Recent messages. + Correct this flag for \Seen messages by unsetting it. + */ + if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) { + flags->fl_flags &= ~MAIL_FLAG_NEW; + } + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + mail_flags_free(flags); + err: + return MAIL_ERROR_MEMORY; +} + +static int flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_store_att_flags ** result) +{ + struct mailimap_flag * flag; + struct mailimap_flag_list * flag_list; + struct mailimap_store_att_flags * att_flags; + int res; + clistiter * cur; + int r; + + flag_list = mailimap_flag_list_new_empty(); + if (flag_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) { + flag = mailimap_flag_new_deleted(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) { + flag = mailimap_flag_new_flagged(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) { + flag = mailimap_flag_new_seen(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) { + flag = mailimap_flag_new_answered(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) { + char * flag_str; + + flag_str = strdup("$Forwarded"); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_str; + + flag_str = clist_content(cur); + + if (strcasecmp(flag_str, "Draft") == 0) { + flag = mailimap_flag_new_draft(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + else { + flag_str = strdup(flag_str); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + } + + att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); + if (att_flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + + * result = att_flags; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} + + +static int +imap_fetch_result_to_flags(clist * fetch_result, uint32_t index, + struct mail_flags ** result) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + struct mailimap_msg_att_dynamic * att_dyn; + + msg_att = clist_content(cur); + + uid = 0; + att_dyn = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + } + } + else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + } + } + + if (uid != 0) { + if (uid == index) { + struct mail_flags * flags; + + if (att_dyn != NULL) { + r = imap_flags_to_flags(att_dyn, &flags); + + if (r == MAIL_NO_ERROR) { + * result = flags; + return MAIL_NO_ERROR; + } + } + } + } + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} + + +int imap_fetch_flags(mailimap * imap, + uint32_t index, struct mail_flags ** result) +{ + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + int r; + int res; + clist * fetch_result; + struct mail_flags * flags; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + set = mailimap_set_new_single(index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_flags(fetch_result, index, &flags); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags) +{ + struct mailimap_store_att_flags * att_flags; + struct mailimap_set * set; + int r; + int res; + + set = mailimap_set_new_interval(first, last); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = flags_to_imap_flags(flags, &att_flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_set; + } + + r = mailimap_uid_store(imap, set, att_flags); + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto free_flag; + } + + mailimap_store_att_flags_free(att_flags); + mailimap_set_free(set); + + return MAIL_NO_ERROR; + + free_flag: + mailimap_store_att_flags_free(att_flags); + free_set: + mailimap_set_free(set); + err: + return res; +} + + + + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + int r; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + clist * fetch_result; + int res; + + set = mailimap_set_new_interval(first_index, 0); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto err; + } + + r = uid_list_to_env_list(fetch_result, &env_list, session, driver); + mailimap_fetch_list_free(fetch_result); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + } +} + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + int r; + struct mailimf_fields * fields; + int res; + char keyname[PATH_MAX]; + +#if 0 + imap_session = cached_session_get_ancestor(session); + imap = ((struct imap_session_state_data *) (imap_session->data))->session; +#endif + imap = cached_session_get_imap_session(session); + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + +err: + return res; +} + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields) +{ + char keyname[PATH_MAX]; + int r; + int res; + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + +err: + return res; +} + diff --git a/kmicromail/libetpan/generic/imapdriver_tools.h b/kmicromail/libetpan/generic/imapdriver_tools.h new file mode 100644 index 0000000..6582a31 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_tools.h @@ -0,0 +1,113 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_TOOLS_H + +#define IMAPDRIVER_TOOLS_H + +#include "mailimap.h" +#include "mailmime.h" +#include "imapdriver_types.h" +#include "mail_cache_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int imap_list_to_list(clist * imap_list, struct mail_list ** result); + +int +section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result); + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body); + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type); + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result); + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list); + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result); + +#if 0 +int mail_search_to_imap_search(struct mail_search_key * key, + struct mailimap_search_key ** result); +#endif + +int msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result); + +int imap_error_to_mail_error(int error); + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags); + +int imap_fetch_flags(mailimap * imap, + uint32_t index, struct mail_flags ** result); + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result); + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result); + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapdriver_types.h b/kmicromail/libetpan/generic/imapdriver_types.h new file mode 100644 index 0000000..d4e216d --- a/dev/null +++ b/kmicromail/libetpan/generic/imapdriver_types.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_TYPES_H + +#define IMAPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IMAP driver for session */ + +struct imap_session_state_data { + mailimap * imap_session; + char * imap_mailbox; + struct mail_flags_store * imap_flags_store; +}; + +enum { + IMAP_SECTION_MESSAGE, + IMAP_SECTION_HEADER, + IMAP_SECTION_MIME, + IMAP_SECTION_BODY +}; + +/* cached IMAP driver for session */ + +enum { + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, +}; + +struct imap_cached_session_state_data { + mailsession * imap_ancestor; + char * imap_quoted_mb; + char imap_cache_directory[PATH_MAX]; + carray * imap_uid_list; +}; + + +/* IMAP storage */ + +/* + imap_mailstorage is the state data specific to the IMAP4rev1 storage. + + - servername this is the name of the IMAP4rev1 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - command, if non-NULL the command used to connect to the + server instead of allowing normal TCP connections to be used. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or + CONNECTION_TYPE_COMMAND. + + - auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + - login is the login of the IMAP4rev1 account. + + - password is the password of the IMAP4rev1 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache +*/ + +struct imap_mailstorage { + char * imap_servername; + uint16_t imap_port; + char * imap_command; + int imap_connection_type; + + int imap_auth_type; + char * imap_login; + char * imap_password; + + int imap_cached; + char * imap_cache_directory; +}; + +/* this is the type of IMAP4rev1 authentication */ + +enum { + IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */ + IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imapstorage.c b/kmicromail/libetpan/generic/imapstorage.c new file mode 100644 index 0000000..e8683d8 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapstorage.c @@ -0,0 +1,297 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imapstorage.h" + +#include +#include + +#include "mail.h" +#include "imapdriver.h" +#include "imapdriver_cached.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* imap storage */ + +#define IMAP_DEFAULT_PORT 143 +#define IMAPS_DEFAULT_PORT 993 + +static int imap_mailstorage_connect(struct mailstorage * storage); +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void imap_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver imap_mailstorage_driver = { + .sto_name = "imap", + .sto_connect = imap_mailstorage_connect, + .sto_get_folder_session = imap_mailstorage_get_folder_session, + .sto_uninitialize = imap_mailstorage_uninitialize, +}; + +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = malloc(sizeof(struct imap_mailstorage)); + if (imap_storage == NULL) + goto err; + + imap_storage->imap_servername = strdup(imap_servername); + if (imap_storage->imap_servername == NULL) + goto free; + + imap_storage->imap_connection_type = imap_connection_type; + + if (imap_port == 0) { + switch (imap_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + imap_port = IMAP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + imap_port = IMAPS_DEFAULT_PORT; + break; + } + } + + imap_storage->imap_port = imap_port; + + if (imap_command != NULL) { + imap_storage->imap_command = strdup(imap_command); + if (imap_storage->imap_command == NULL) + goto free_servername; + } + else + imap_storage->imap_command = NULL; + + imap_storage->imap_auth_type = imap_auth_type; + + if (imap_login != NULL) { + imap_storage->imap_login = strdup(imap_login); + if (imap_storage->imap_login == NULL) + goto free_command; + } + else + imap_storage->imap_login = NULL; + + if (imap_password != NULL) { + imap_storage->imap_password = strdup(imap_password); + if (imap_storage->imap_password == NULL) + goto free_login; + } + else + imap_storage->imap_password = NULL; + + imap_storage->imap_cached = imap_cached; + + if (imap_cached && (imap_cache_directory != NULL)) { + imap_storage->imap_cache_directory = strdup(imap_cache_directory); + if (imap_storage->imap_cache_directory == NULL) + goto free_password; + } + else { + imap_storage->imap_cached = FALSE; + imap_storage->imap_cache_directory = NULL; + } + + storage->sto_data = imap_storage; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_password: + free(imap_storage->imap_password); + free_login: + free(imap_storage->imap_login); + free_command: + free(imap_storage->imap_command); + free_servername: + free(imap_storage->imap_servername); + free: + free(imap_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = storage->sto_data; + + if (imap_storage->imap_cache_directory != NULL) + free(imap_storage->imap_cache_directory); + if (imap_storage->imap_password != NULL) + free(imap_storage->imap_password); + if (imap_storage->imap_login != NULL) + free(imap_storage->imap_login); + if (imap_storage->imap_command != NULL) + free(imap_storage->imap_command); + free(imap_storage->imap_servername); + free(imap_storage); + + storage->sto_data = NULL; +} + +static int imap_connect(struct mailstorage * storage, + mailsession ** result) +{ + struct imap_mailstorage * imap_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + imap_storage = storage->sto_data; + + if (imap_storage->imap_cached) + driver = imap_cached_session_driver; + else + driver = imap_session_driver; + + r = mailstorage_generic_connect(driver, + imap_storage->imap_servername, + imap_storage->imap_port, + imap_storage->imap_command, + imap_storage->imap_connection_type, + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY, + imap_storage->imap_cache_directory, + 0, NULL, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + r = mailstorage_generic_auth(session, r, + imap_storage->imap_connection_type, + imap_storage->imap_login, + imap_storage->imap_password); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int imap_mailstorage_connect(struct mailstorage * storage) +{ + mailsession * session; + int r; + int res; + + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, "INBOX"); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + + storage->sto_session = session; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + mailsession * session; + int r; + int res; + + if (strcasecmp(pathname, "INBOX") == 0) { + session = storage->sto_session; + } + else { + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, pathname); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto free; + } + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/imapstorage.h b/kmicromail/libetpan/generic/imapstorage.h new file mode 100644 index 0000000..ebc42b0 --- a/dev/null +++ b/kmicromail/libetpan/generic/imapstorage.h @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPSTORAGE_H + +#define IMAPSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + imap_mailstorage_init is the constructor for a IMAP4rev1 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the IMAP4rev1 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + @param login is the login of the IMAP4rev1 account. + + @param password is the password of the IMAP4rev1 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache +*/ + +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/imfcache.c b/kmicromail/libetpan/generic/imfcache.c new file mode 100644 index 0000000..64983f4 --- a/dev/null +++ b/kmicromail/libetpan/generic/imfcache.c @@ -0,0 +1,1429 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "imfcache.h" + +#include +#include + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index, + struct mailimf_field * field); +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date * date); +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time * date_time); +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index, + struct mailimf_from * from); +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index, + struct mailimf_sender * sender); +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to * reply_to); +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_to * to); +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_cc * to); +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc * to); +static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id * message_id); +static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index, + clist * list); +static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index, + struct mailimf_references * references); +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index, + struct mailimf_subject * subject); +static int mailimf_cache_address_list_write(MMAPString * mmapstr, + size_t * index, + struct mailimf_address_list * + addr_list); +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address * addr); +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index, + struct mailimf_group * group); +static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr, + size_t * index, + struct mailimf_mailbox_list * mb_list); +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox * mb); + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index, + struct mailimf_field ** result); +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date ** result); +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time ** result); +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index, + struct mailimf_from ** result); +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index, + struct mailimf_sender ** result); +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to ** result); +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_to ** result); +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_cc ** result); +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc ** result); +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id ** result); +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index, + clist ** result); +static int +mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to ** result); + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index, + struct mailimf_references ** result); +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index, + struct mailimf_subject ** result); +static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list ** result); +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address ** result); +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index, + struct mailimf_group ** result); +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list ** result); +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox ** result); + +enum { + CACHE_NULL_POINTER = 0, + CACHE_NOT_NULL = 1, +}; + +int mail_serialize_clear(MMAPString * mmapstr, size_t * index) +{ + if (mmap_string_set_size(mmapstr, 0) == NULL) + return MAIL_ERROR_MEMORY; + + * index = 0; + + return MAIL_NO_ERROR; +} + +int mail_serialize_write(MMAPString * mmapstr, size_t * index, + char * buf, size_t size) +{ + if (mmap_string_append_len(mmapstr, buf, size) == NULL) + return MAIL_ERROR_MEMORY; + + * index = * index + size; + + return MAIL_NO_ERROR; +} + +int mail_serialize_read(MMAPString * mmapstr, size_t * index, + char * buf, size_t size) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + size > mmapstr->len) + return MAIL_ERROR_STREAM; + + memcpy(buf, mmapstr->str + cur_token, size); + * index = cur_token + size; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index, + uint32_t value) +{ + unsigned char ch; + int r; + int i; + + for(i = 0 ; i < 4 ; i ++) { + ch = value % 256; + + r = mail_serialize_write(mmapstr, index, &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value /= 256; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index, + uint32_t * result) +{ + unsigned char ch; + uint32_t value; + int i; + int r; + + value = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mail_serialize_read(mmapstr, index, &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value = value | ch << (i << 3); + } + + * result = value; + + return MAIL_NO_ERROR; +} + + +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index, + char * str, size_t length) +{ + int r; + + if (str == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, length); + if (r != MAIL_NO_ERROR) + return r; + + if (length != 0) { + r = mail_serialize_write(mmapstr, index, str, length); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FILE; + } + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index, + char ** result) +{ + int r; + uint32_t length; + char * str; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) + return r; + + if (type == CACHE_NULL_POINTER) { + str = NULL; + } + else { + r = mailimf_cache_int_read(mmapstr, index, &length); + if (r != MAIL_NO_ERROR) + return r; + + str = malloc(length + 1); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = mail_serialize_read(mmapstr, index, str, length); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FILE; + + str[length] = 0; + } + + * result = str; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(fields->fld_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + r = mailimf_cache_field_write(mmapstr, index, clist_content(cur)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index, + struct mailimf_fields ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_fields * fields; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_field * field; + + r = mailimf_cache_field_read(mmapstr, index, &field); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index, + struct mailimf_field * field) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, field->fld_type); + if (r != MAIL_NO_ERROR) + return r; + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_write(mmapstr, index, + field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_write(mmapstr, index, + field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_write(mmapstr, index, + field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_write(mmapstr, index, + field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_write(mmapstr, index, + field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_write(mmapstr, index, + field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_write(mmapstr, index, + field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_write(mmapstr, index, + field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_write(mmapstr, index, + field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_write(mmapstr, index, + field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_write(mmapstr, index, + field->fld_data.fld_subject); + break; + default: + r = 0; + break; + } + + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index, + struct mailimf_field ** result) +{ + int r; + uint32_t type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_to * to; + struct mailimf_reply_to * reply_to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_field * field; + int res; + + orig_date = NULL; + from = NULL; + sender = NULL; + to = NULL; + reply_to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + field = NULL; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + switch (type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_read(mmapstr, index, &orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_read(mmapstr, index, &from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_read(mmapstr, index, &sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_read(mmapstr, index, &reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_read(mmapstr, index, &to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_read(mmapstr, index, &cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_read(mmapstr, index, &bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_read(mmapstr, index, &message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_read(mmapstr, index, &in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_read(mmapstr, index, &references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_read(mmapstr, index, &subject); + break; + default: + r = MAIL_ERROR_INVAL; + break; + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, orig_date, from, sender, reply_to, + to, cc, bcc, message_id, + in_reply_to, references, + subject, NULL, NULL, NULL); + if (field == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = field; + + return MAIL_NO_ERROR; + + free: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + err: + return res; +} + +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date * date) +{ + return mailimf_cache_date_time_write(mmapstr, index, date->dt_date_time); +} + +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date ** result) +{ + int r; + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + + r = mailimf_cache_date_time_read(mmapstr, index, &date_time); + if (r != MAIL_NO_ERROR) + return r; + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + return MAIL_ERROR_MEMORY; + } + + * result = orig_date; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time * date_time) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_zone); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time ** result) +{ + int r; + uint32_t day; + uint32_t month; + uint32_t year; + uint32_t hour; + uint32_t min; + uint32_t sec; + uint32_t zone; + struct mailimf_date_time * date_time; + + r = mailimf_cache_int_read(mmapstr, index, &day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &zone); + if (r != MAIL_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAIL_ERROR_MEMORY; + + * result = date_time; + + return MAIL_NO_ERROR; + +} + + +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index, + struct mailimf_from * from) +{ + return mailimf_cache_mailbox_list_write(mmapstr, index, from->frm_mb_list); +} + +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index, + struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + int r; + + r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list); + if (r != MAIL_NO_ERROR) + return r; + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + return MAIL_ERROR_MEMORY; + } + + * result = from; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index, + struct mailimf_sender * sender) +{ + return mailimf_cache_mailbox_write(mmapstr, index, sender->snd_mb); +} + +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index, + struct mailimf_sender ** result) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + r = mailimf_cache_mailbox_read(mmapstr, index, &mb); + if (r != MAIL_NO_ERROR) + return r; + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + return MAIL_ERROR_MEMORY; + } + + * result = sender; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to * reply_to) +{ + return mailimf_cache_address_list_write(mmapstr, index, + reply_to->rt_addr_list); +} + +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_to * to) +{ + return mailimf_cache_address_list_write(mmapstr, index, to->to_addr_list); +} + +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_cc * cc) +{ + return mailimf_cache_address_list_write(mmapstr, index, cc->cc_addr_list); +} + +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_cc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = cc; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc * bcc) +{ + return mailimf_cache_address_list_write(mmapstr, index, bcc->bcc_addr_list); +} + +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = bcc; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id * message_id) +{ + return mailimf_cache_string_write(mmapstr, index, + message_id->mid_value, strlen(message_id->mid_value)); +} + +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id ** result) +{ + struct mailimf_message_id * message_id; + char * str; + int r; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) + return r; + + message_id = mailimf_message_id_new(str); + if (message_id == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = message_id; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index, + clist * list) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, index, clist_count(list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + + msgid = clist_content(cur); + + r = mailimf_cache_string_write(mmapstr, index, msgid, strlen(msgid)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * msgid; + + r = mailimf_cache_string_read(mmapstr, index, &msgid); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = clist_append(list, msgid); + if (r < 0) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to * in_reply_to) +{ + return mailimf_cache_msg_id_list_write(mmapstr, index, + in_reply_to->mid_list); +} + +static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_in_reply_to * in_reply_to; + + r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = in_reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index, + struct mailimf_references * references) +{ + return mailimf_cache_msg_id_list_write(mmapstr, index, + references->mid_list); +} + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index, + struct mailimf_references ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_references * references; + + r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = references; + + return MAIL_NO_ERROR; +} + + +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index, + struct mailimf_subject * subject) +{ + return mailimf_cache_string_write(mmapstr, index, + subject->sbj_value, strlen(subject->sbj_value)); +} + +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index, + struct mailimf_subject ** result) +{ + char * str; + struct mailimf_subject * subject; + int r; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) + return r; + + if (str == NULL) { + str = strdup(""); + if (str == NULL) + return MAIL_ERROR_MEMORY; + } + + subject = mailimf_subject_new(str); + if (subject == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = subject; + + return MAIL_NO_ERROR; +} + + +static int +mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + if (addr_list == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(addr_list->ad_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = mailimf_cache_address_write(mmapstr, index, addr); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list ** result) +{ + struct mailimf_address_list * addr_list; + uint32_t count; + uint32_t i; + int r; + clist * list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_address * addr; + + r = mailimf_cache_address_read(mmapstr, index, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, addr); + if (r < 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address * addr) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, addr->ad_type); + if (r != MAIL_NO_ERROR) + return r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_write(mmapstr, index, addr->ad_data.ad_mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_write(mmapstr, index, addr->ad_data.ad_group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address ** result) +{ + uint32_t type; + int r; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * addr; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) + return r; + + mailbox = NULL; + group = NULL; + + switch (type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_read(mmapstr, index, &mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_read(mmapstr, index, &group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + addr = mailimf_address_new(type, mailbox, group); + if (addr == NULL) + goto free; + + * result = addr; + + return MAIL_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + return MAIL_ERROR_MEMORY; +} + +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index, + struct mailimf_group * group) +{ + int r; + + r = mailimf_cache_string_write(mmapstr, index, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_mailbox_list_write(mmapstr, index, group->grp_mb_list); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index, + struct mailimf_group ** result) +{ + int r; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_group * group; + int res; + + r = mailimf_cache_string_read(mmapstr, index, &display_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dsp_name; + } + + group = mailimf_group_new(display_name, mb_list); + if (group == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb_list; + } + + * result = group; + + return MAIL_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + free_dsp_name: + free(display_name); + err: + return res; +} + +static int +mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + if (mb_list == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(mb_list->mb_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = mailimf_cache_mailbox_write(mmapstr, index, mb); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_mailbox_list * mb_list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_mailbox * mb; + + r = mailimf_cache_mailbox_read(mmapstr, index, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r < 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox * mb) +{ + int r; + + if (mb->mb_display_name) { + r = mailimf_cache_string_write(mmapstr, index, + mb->mb_display_name, strlen(mb->mb_display_name)); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_string_write(mmapstr, index, NULL, 0); + if (r != MAIL_NO_ERROR) + return r; + } + + r = mailimf_cache_string_write(mmapstr, index, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox ** result) +{ + int r; + char * dsp_name; + char * addr_spec; + struct mailimf_mailbox * mb; + + dsp_name = NULL; + + r = mailimf_cache_string_read(mmapstr, index, &dsp_name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_string_read(mmapstr, index, &addr_spec); + if (r != MAIL_NO_ERROR) + goto free_dsp_name; + + mb = mailimf_mailbox_new(dsp_name, addr_spec); + if (mb == NULL) + goto free_addr; + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr_spec); + free_dsp_name: + if (dsp_name != NULL) + free(dsp_name); + return MAIL_ERROR_MEMORY; +} diff --git a/kmicromail/libetpan/generic/imfcache.h b/kmicromail/libetpan/generic/imfcache.h new file mode 100644 index 0000000..31c99c0 --- a/dev/null +++ b/kmicromail/libetpan/generic/imfcache.h @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMFCACHE_H + +#define IMFCACHE_H + +#include +#include "mailimf.h" +#include "maildriver_types.h" +#include "mmapstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mail_serialize_clear(MMAPString * mmapstr, size_t * index); + +int mail_serialize_write(MMAPString * mmapstr, size_t * index, + char * buf, size_t size); + +int mail_serialize_read(MMAPString * mmapstr, size_t * index, + char * buf, size_t size); + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index, + uint32_t value); +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index, + char * str, size_t length); +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index, + uint32_t * result); +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index, + char ** result); + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index, + struct mailimf_fields * fields); +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/libetpan.h b/kmicromail/libetpan/generic/libetpan.h new file mode 100644 index 0000000..3b4a107 --- a/dev/null +++ b/kmicromail/libetpan/generic/libetpan.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef LIBETPAN_H + +#define LIBETPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +/* mbox driver */ +#include +#include +#include +#include +#include + +/* MH driver */ +#include +#include +#include +#include +#include + +/* IMAP4rev1 driver */ +#include +#include +#include +#include +#include + +/* POP3 driver */ +#include +#include +#include +#include +#include + +/* NNTP driver */ +#include +#include +#include +#include +#include + +/* maildir driver */ +#include +#include +#include +#include +#include + +/* message which content is given by a MIME structure */ +#include + +/* message which content given by a string */ +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/libetpan_version.c b/kmicromail/libetpan/generic/libetpan_version.c new file mode 100644 index 0000000..d4ea6ec --- a/dev/null +++ b/kmicromail/libetpan/generic/libetpan_version.c @@ -0,0 +1,18 @@ +#include "libetpan_version.h" + +#ifndef CONFIG_H +#define CONFIG_H +#include "config.h" +#endif + +/* version of libEtPan! at runtime */ + +int libetpan_get_version_major(void) +{ + return LIBETPAN_VERSION_MAJOR; +} + +int libetpan_get_version_minor(void) +{ + return LIBETPAN_VERSION_MINOR; +} diff --git a/kmicromail/libetpan/generic/libetpan_version.h b/kmicromail/libetpan/generic/libetpan_version.h new file mode 100644 index 0000000..5f9e5cf --- a/dev/null +++ b/kmicromail/libetpan/generic/libetpan_version.h @@ -0,0 +1,51 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR 0 +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR 32 +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif diff --git a/kmicromail/libetpan/generic/libetpan_version.h.in b/kmicromail/libetpan/generic/libetpan_version.h.in new file mode 100644 index 0000000..ce1deb2 --- a/dev/null +++ b/kmicromail/libetpan/generic/libetpan_version.h.in @@ -0,0 +1,51 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR @VERSION_MAJOR@ +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR @VERSION_MINOR@ +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver.c b/kmicromail/libetpan/generic/maildirdriver.c new file mode 100644 index 0000000..7830ceb --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver.c @@ -0,0 +1,625 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + + +/* + flags directory MUST be kept so that we can have other flags + than standards +*/ + +#include "maildirdriver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_message.h" +#include "maildirdriver_tools.h" +#include "mailmessage.h" +#include "generic_cache.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int connect_path(mailsession * session, char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + char * message, size_t size); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_session_driver = { + .sess_name = "maildir", + + .sess_initialize = initialize, + .sess_uninitialize = uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = NULL, + .sess_connect_path = connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = expunge_folder, + .sess_status_folder = status_folder, + .sess_messages_number = messages_number, + .sess_recent_number = recent_number, + .sess_unseen_number = unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = get_messages_list, + .sess_get_envelopes_list = get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = NULL, + .sess_get_message_by_uid = get_message_by_uid, +}; + +mailsession_driver * maildir_session_driver = &local_maildir_session_driver; + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store); + + +static inline struct maildir_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_session = NULL; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = get_data(session); + + if (data->md_session != NULL) + flags_store_process(data->md_session, data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + if (data->md_session != NULL) + maildir_free(data->md_session); + + free(data); + + session->sess_data = NULL; +} + + +static int connect_path(mailsession * session, char * path) +{ + struct maildir * md; + int res; + int r; + + if (get_maildir_session(session) != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + md = maildir_new(path); + if (md == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto free; + } + + get_data(session)->md_session = md; + + return MAIL_NO_ERROR; + + free: + maildir_free(md); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + maildir_free(md); + get_data(session)->md_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + struct maildir * md; + unsigned int i; + uint32_t messages; + uint32_t recent; + uint32_t unseen; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + messages = 0; + recent = 0; + unseen = 0; + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) { + struct maildir_msg * msg; + + msg = carray_get(md->mdir_msg_list, i); + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + recent ++; + if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0) + unseen ++; + messages ++; + } + + * result_messages = messages; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; +} + +static int messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + * result = carray_count(md->mdir_msg_list); + + return MAIL_NO_ERROR; +} + +static int unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int append_message(mailsession * session, + char * message, size_t size) +{ + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add(md, message, size); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + return MAIL_NO_ERROR; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + struct maildir * md; + unsigned int i; + int res; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildriver_generic_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + uint32_t driver_flags; + clist * ext; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + continue; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + if (msg->msg_flags == NULL) { + ext = clist_new(); + if (ext == NULL) { + res = MAIL_ERROR_MEMORY; + continue; + } + + msg->msg_flags = mail_flags_new(driver_flags, ext); + if (msg->msg_flags == NULL) { + clist_free(ext); + res = MAIL_ERROR_MEMORY; + continue; + } + + if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) { + mail_flags_store_set(get_data(session)->md_flags_store, msg); + } + } + else { + msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED; + msg->msg_flags->fl_flags |= driver_flags; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int expunge_folder(mailsession * session) +{ + unsigned int i; + int r; + int res; + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + + md_msg = carray_get(md->mdir_msg_list, i); + + if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0) + maildir_message_remove(md, md_msg->msg_uid); + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store) +{ + unsigned int i; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + uint32_t md_flags; + + msg = carray_get(flags_store->fls_tab, i); + md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags); + md_flags &= ~MAILDIR_FLAG_NEW; + + maildir_message_change_flags(md, msg->msg_uid, md_flags); + } + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; +} + + + +static int check_folder(mailsession * session) +{ + struct mail_flags_store * flags_store; + struct maildir_session_state_data * data; + struct maildir * md; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + data = get_data(session); + flags_store = data->md_flags_store; + + return flags_store_process(md, flags_store); +} + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char * msg_filename; + struct stat stat_info; + + md = get_maildir_session(session); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_message_driver, + 0, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + err: + return res; +} diff --git a/kmicromail/libetpan/generic/maildirdriver.h b/kmicromail/libetpan/generic/maildirdriver.h new file mode 100644 index 0000000..f59cf3e --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_H + +#define MAILDIRDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver_cached.c b/kmicromail/libetpan/generic/maildirdriver_cached.c new file mode 100644 index 0000000..503d1c9 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_cached.c @@ -0,0 +1,1080 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildirdriver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_tools.h" +#include "maildirdriver_cached_message.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" +#include "libetpan-config.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int parameters(mailsession * session, + int id, void * value); + +static int connect_path(mailsession * session, char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + char * message, size_t size); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_cached_session_driver = { + .sess_name = "maildir-cached", + + .sess_initialize = initialize, + .sess_uninitialize = uninitialize, + + .sess_parameters = parameters, + + .sess_connect_stream = NULL, + .sess_connect_path = connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = expunge_folder, + .sess_status_folder = status_folder, + .sess_messages_number = messages_number, + .sess_recent_number = recent_number, + .sess_unseen_number = unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = get_messages_list, + .sess_get_envelopes_list = get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = get_message, + .sess_get_message_by_uid = get_message_by_uid, +}; + +mailsession_driver * maildir_cached_session_driver = +&local_maildir_cached_session_driver; + + +static inline struct maildir_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->md_ancestor; +} + +static inline struct maildir_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_ancestor_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_ancestor = mailsession_new(maildir_session_driver); + if (data->md_ancestor == NULL) + goto free; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free_session; + + data->md_quoted_mb = NULL; + data->md_cache_directory[0] = '\0'; + data->md_flags_directory[0] = '\0'; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->md_ancestor); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data) +{ + if (maildir_cached_data->md_quoted_mb != NULL) { + free(maildir_cached_data->md_quoted_mb); + maildir_cached_data->md_quoted_mb = NULL; + } +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + +static int flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, + data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + mailsession_free(data->md_ancestor); + free_quoted_mb(data); + free(data); + + session->sess_data = data; +} + + +static int parameters(mailsession * session, + int id, void * value) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->md_cache_directory, value, PATH_MAX); + data->md_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->md_flags_directory, value, PATH_MAX); + data->md_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->md_ancestor, id, value); + } +} + + +static int get_cache_folder(mailsession * session, char ** result) +{ + struct maildir * md; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(md->mdir_path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free_quoted_mb: + free(quoted_mb); + err: + return res; +} + + +static int connect_path(mailsession * session, char * path) +{ + int r; + int res; + char * quoted_mb; + + r = mailsession_connect_path(get_ancestor(session), path); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto logout; + } + + get_cached_data(session)->md_quoted_mb = quoted_mb; + + return MAILDIR_NO_ERROR; + + logout: + mailsession_logout(get_ancestor(session)); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_quoted_mb(get_cached_data(session)); + + return MAIL_NO_ERROR; +} + +static int status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(get_ancestor(session), mb, + result_messages, result_recent, result_unseen); +} + +static int messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_unseen_number(get_ancestor(session), mb, result); +} + +static int recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_recent_number(get_ancestor(session), mb, result); +} + + +static int append_message(mailsession * session, + char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + + +#define UID_NAME "uid.db" + +static int uid_clean_up(struct mail_cache_db * uid_db, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + unsigned int i; + chashdatum key; + chashdatum value; + char key_str[PATH_MAX]; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + value.data = NULL; + value.len = 0; + + key.data = "max-uid"; + key.len = strlen("max-uid"); + r = chash_set(hash_exist, &key, &value, NULL); + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", + (unsigned long) msg->msg_index); + key.data = key_str; + key.len = strlen(key_str); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + mail_cache_db_clean_up(uid_db, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + uint32_t max_uid; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + void * value; + size_t value_len; + unsigned long i; + struct maildir_cached_session_state_data * data; + char key[PATH_MAX]; + + data = get_cached_data(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + check_folder(session); + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_cached_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* read/write DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + max_uid = 0; + r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1, + &value, &value_len); + if (r == 0) { + memcpy(&max_uid, value, sizeof(max_uid)); + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + uint32_t index; + + msg = carray_get(env_list->msg_tab, i); + + r = mail_cache_db_get(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &value, &value_len); + if (r < 0) { + max_uid ++; + msg->msg_index = max_uid; + mail_cache_db_put(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index)); + + snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index); + mail_cache_db_put(uid_db, key, strlen(key), + msg->msg_uid, strlen(msg->msg_uid)); + } + else { + memcpy(&index, value, sizeof(index)); + msg->msg_index = index; + } + } + + mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1, + &max_uid, sizeof(max_uid)); + + uid_clean_up(uid_db, env_list); + + mail_cache_db_close_unlock(filename, uid_db); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int +get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + char * uid, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + int res; + struct maildir_cached_session_state_data * data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_uid, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_uid, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_uid, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int expunge_folder(mailsession * session) +{ + return mailsession_expunge_folder(get_ancestor(session)); +} + +static int check_folder(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + return mailsession_check_folder(get_ancestor(session)); +} + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + char key_str[PATH_MAX]; + void * value; + size_t value_len; + char uid[PATH_MAX]; + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num); + + r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + if (value_len >= PATH_MAX) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(uid, value, value_len); + uid[value_len] = '\0'; + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + num, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} + + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + void * value; + size_t value_len; + struct maildir_cached_session_state_data * data; + uint32_t index; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(&index, value, sizeof(index)); + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + index, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/maildirdriver_cached.h b/kmicromail/libetpan/generic/maildirdriver_cached.h new file mode 100644 index 0000000..81de3c3 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_cached.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_CACHED_H + +#define MAILDIRDRIVER_CACHED_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver_cached_message.c b/kmicromail/libetpan/generic/maildirdriver_cached_message.c new file mode 100644 index 0000000..51866aa --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_cached_message.c @@ -0,0 +1,248 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildirdriver_message.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" + +#include +#include +#include +#include +#include +#include +#include + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_cached_message_driver = { + .msg_name = "maildir-cached", + + .msg_initialize = initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_header, + .msg_fetch_size = NULL, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * maildir_cached_message_driver = +&local_maildir_cached_message_driver; + +struct maildir_msg_data { + int fd; +}; + +#if 0 +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->session->data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return get_data(session)->session; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->session)->session; +} +#endif +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct maildir_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->md_ancestor; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline struct maildir_session_state_data * +get_session_ancestor_data(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->msg_session); +} + +static inline struct maildir * +cached_session_get_maildir_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->md_session; +} + +static inline struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_maildir_session(msg->msg_session); +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info); + + r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info); + /* ignore errors */ + } +} diff --git a/kmicromail/libetpan/generic/maildirdriver_cached_message.h b/kmicromail/libetpan/generic/maildirdriver_cached_message.h new file mode 100644 index 0000000..399ecaa --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H + +#define MAILDIRDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver_message.c b/kmicromail/libetpan/generic/maildirdriver_message.c new file mode 100644 index 0000000..7cf9dd1 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_message.c @@ -0,0 +1,199 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildirdriver_message.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" + +#include +#include +#include +#include +#include +#include +#include + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_message_driver = { + .msg_name = "maildir", + + .msg_initialize = initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_header, + .msg_fetch_size = NULL, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * maildir_message_driver = &local_maildir_message_driver; + +struct maildir_msg_data { + int fd; +}; + +static inline struct maildir_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return get_session_data(msg)->md_session; +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + if (msg_info->msg_uid == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store, + msg_info); + /* ignore errors */ + } +} diff --git a/kmicromail/libetpan/generic/maildirdriver_message.h b/kmicromail/libetpan/generic/maildirdriver_message.h new file mode 100644 index 0000000..cb378bc --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_MESSAGE_H + +#define MAILDIRDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver_tools.c b/kmicromail/libetpan/generic/maildirdriver_tools.c new file mode 100644 index 0000000..f3e21e4 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_tools.c @@ -0,0 +1,195 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmessage.h" +#include "maildirdriver_tools.h" +#include "maildir.h" +#include "generic_cache.h" +#include +#include +#include +#include + +int maildirdriver_maildir_error_to_mail_error(int error) +{ + switch (error) { + case MAILDIR_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILDIR_ERROR_CREATE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_DIRECTORY: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILDIR_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags) +{ + uint32_t flags; + + flags = 0; + if ((md_flags & MAILDIR_FLAG_NEW) != 0) + flags |= MAIL_FLAG_NEW; + + if ((md_flags & MAILDIR_FLAG_SEEN) != 0) + flags |= MAIL_FLAG_SEEN; + + if ((md_flags & MAILDIR_FLAG_REPLIED) != 0) + flags |= MAIL_FLAG_ANSWERED; + + if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0) + flags |= MAIL_FLAG_FLAGGED; + + if ((md_flags & MAILDIR_FLAG_TRASHED) != 0) + flags |= MAIL_FLAG_DELETED; + + return flags; +} + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags) +{ + uint32_t md_flags; + + md_flags = 0; + if ((flags & MAIL_FLAG_NEW) != 0) + md_flags |= MAILDIR_FLAG_NEW; + + if ((flags & MAIL_FLAG_SEEN) != 0) + md_flags |= MAILDIR_FLAG_SEEN; + + if ((flags & MAIL_FLAG_ANSWERED) != 0) + md_flags |= MAILDIR_FLAG_REPLIED; + + if ((flags & MAIL_FLAG_FLAGGED) != 0) + md_flags |= MAILDIR_FLAG_FLAGGED; + + if ((flags & MAIL_FLAG_DELETED) != 0) + md_flags |= MAILDIR_FLAG_TRASHED; + + return md_flags; +} + + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + char * filename; + struct stat stat_info; + + md_msg = carray_get(md->mdir_msg_list, i); + + filename = maildir_message_get(md, md_msg->msg_uid); + r = stat(filename, &stat_info); + free(filename); + if (r < 0) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, message_driver, + i + 1, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + msg->msg_uid = strdup(md_msg->msg_uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/maildirdriver_tools.h b/kmicromail/libetpan/generic/maildirdriver_tools.h new file mode 100644 index 0000000..3c8931f --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_tools.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_TOOLS_H + +#define MAILDIRDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "maildir.h" + +int maildirdriver_maildir_error_to_mail_error(int error); + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags); + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags); + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result); + +#endif diff --git a/kmicromail/libetpan/generic/maildirdriver_types.h b/kmicromail/libetpan/generic/maildirdriver_types.h new file mode 100644 index 0000000..cb3661f --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirdriver_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_TYPES_H + +#define MAILDIRDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct maildir_session_state_data { + struct maildir * md_session; + struct mail_flags_store * md_flags_store; +}; + +enum { + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct maildir_cached_session_state_data { + mailsession * md_ancestor; + char * md_quoted_mb; + struct mail_flags_store * md_flags_store; + char md_cache_directory[PATH_MAX]; + char md_flags_directory[PATH_MAX]; +}; + +/* maildir storage */ + +/* + maildir_mailstorage is the state data specific to the maildir storage. + + - pathname is the path of the maildir storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct maildir_mailstorage { + char * md_pathname; + + int md_cached; + char * md_cache_directory; + char * md_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildirstorage.c b/kmicromail/libetpan/generic/maildirstorage.c new file mode 100644 index 0000000..7e6b461 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirstorage.c @@ -0,0 +1,192 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildirdriver.h" +#include "maildirdriver_cached.h" +#include "maildriver.h" + +#include +#include + +/* maildir storage */ + +static int maildir_mailstorage_connect(struct mailstorage * storage); +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void maildir_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver maildir_mailstorage_driver = { + .sto_name = "maildir", + .sto_connect = maildir_mailstorage_connect, + .sto_get_folder_session = maildir_mailstorage_get_folder_session, + .sto_uninitialize = maildir_mailstorage_uninitialize, +}; + +int maildir_mailstorage_init(struct mailstorage * storage, + char * md_pathname, int md_cached, + char * md_cache_directory, char * md_flags_directory) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = malloc(sizeof(struct maildir_mailstorage)); + if (maildir_storage == NULL) + goto err; + + maildir_storage->md_pathname = strdup(md_pathname); + if (maildir_storage->md_pathname == NULL) + goto free; + + maildir_storage->md_cached = md_cached; + + if (md_cached && (md_cache_directory != NULL) && + (md_flags_directory != NULL)) { + maildir_storage->md_cache_directory = strdup(md_cache_directory); + if (maildir_storage->md_cache_directory == NULL) + goto free_pathname; + + maildir_storage->md_flags_directory = strdup(md_flags_directory); + if (maildir_storage->md_flags_directory == NULL) + goto free_cache_directory; + } + else { + maildir_storage->md_cached = FALSE; + maildir_storage->md_cache_directory = NULL; + maildir_storage->md_flags_directory = NULL; + } + + storage->sto_data = maildir_storage; + storage->sto_driver = &maildir_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(maildir_storage->md_cache_directory); + free_pathname: + free(maildir_storage->md_pathname); + free: + free(maildir_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void maildir_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = storage->sto_data; + if (maildir_storage->md_flags_directory != NULL) + free(maildir_storage->md_flags_directory); + if (maildir_storage->md_cache_directory != NULL) + free(maildir_storage->md_cache_directory); + free(maildir_storage->md_pathname); + free(maildir_storage); + + storage->sto_data = NULL; +} + +static int maildir_mailstorage_connect(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + maildir_storage = storage->sto_data; + + if (maildir_storage->md_cached) + driver = maildir_cached_session_driver; + else + driver = maildir_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (maildir_storage->md_cached) { + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY, + maildir_storage->md_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, + maildir_storage->md_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, maildir_storage->md_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/kmicromail/libetpan/generic/maildirstorage.h b/kmicromail/libetpan/generic/maildirstorage.h new file mode 100644 index 0000000..d17ea2c --- a/dev/null +++ b/kmicromail/libetpan/generic/maildirstorage.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRSTORAGE_H + +#define MAILDIRSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + maildir_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int maildir_mailstorage_init(struct mailstorage * storage, + char * md_pathname, int md_cached, + char * md_cache_directory, char * md_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildriver.c b/kmicromail/libetpan/generic/maildriver.c new file mode 100644 index 0000000..01e3e34 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver.c @@ -0,0 +1,373 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildriver.h" +#include +#include +#include + +/* *********************************************************************** */ +/* mail session */ + +mailsession * mailsession_new(mailsession_driver * sess_driver) +{ + mailsession * session; + int r; + + session = malloc(sizeof(* session)); + + session->sess_data = NULL; + + if (sess_driver->sess_initialize != NULL) { + r = sess_driver->sess_initialize(session); + if (r != MAIL_NO_ERROR) + goto free; + } + + session->sess_driver = sess_driver; + + return session; + + free: + free(session); + return NULL; +} + +void mailsession_free(mailsession * session) +{ + if (session->sess_driver->sess_uninitialize != NULL) + session->sess_driver->sess_uninitialize(session); + free(session); +} + +int mailsession_parameters(mailsession * session, + int id, void * value) +{ + if (session->sess_driver->sess_parameters == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_parameters(session, id, value); +} + +int mailsession_connect_stream(mailsession * session, mailstream * s) +{ + if (session->sess_driver->sess_connect_stream == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_stream(session, s); +} + +int mailsession_connect_path(mailsession * session, char * path) +{ + if (session->sess_driver->sess_connect_path == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_path(session, path); +} + +int mailsession_starttls(mailsession * session) +{ + if (session->sess_driver->sess_starttls == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_starttls(session); +} + +int mailsession_login(mailsession * session, + char * userid, char * password) +{ + if (session->sess_driver->sess_login == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_login(session, userid, password); +} + +int mailsession_logout(mailsession * session) +{ + if (session->sess_driver->sess_logout == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_logout(session); +} + +int mailsession_noop(mailsession * session) +{ + if (session->sess_driver->sess_noop == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_noop(session); +} + +/* folders operations */ + +int mailsession_build_folder_name(mailsession * session, char * mb, + char * name, char ** result) +{ + if (session->sess_driver->sess_build_folder_name == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_build_folder_name(session, + mb, name, result); +} + +int mailsession_create_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_create_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_create_folder(session, mb); +} + +int mailsession_delete_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_delete_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_delete_folder(session, mb); +} + +int mailsession_rename_folder(mailsession * session, + char * mb, char * new_name) +{ + if (session->sess_driver->sess_rename_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_rename_folder(session, mb, new_name); +} + +int mailsession_check_folder(mailsession * session) +{ + if (session->sess_driver->sess_check_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_check_folder(session); +} + +int mailsession_examine_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_examine_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_examine_folder(session, mb); +} + +int mailsession_select_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_select_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_select_folder(session, mb); +} + +int mailsession_expunge_folder(mailsession * session) +{ + if (session->sess_driver->sess_expunge_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_expunge_folder(session); +} + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + if (session->sess_driver->sess_status_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_status_folder(session, mb, + result_messages, result_recent, result_unseen); +} + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_messages_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_messages_number(session, mb, result); +} + +int mailsession_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_recent_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_recent_number(session, mb, result); +} + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_unseen_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_recent_number(session, mb, result); +} + +int mailsession_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_list_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_list_folders(session, mb, result); +} + +int mailsession_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_lsub_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_lsub_folders(session, mb, result); +} + +int mailsession_subscribe_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_subscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_subscribe_folder(session, mb); +} + +int mailsession_unsubscribe_folder(mailsession * session, char * mb) +{ + if (session->sess_driver->sess_unsubscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_unsubscribe_folder(session, mb); +} + +/* message */ + +int mailsession_append_message(mailsession * session, + char * message, size_t size) +{ + if (session->sess_driver->sess_append_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message(session, message, size); +} + +int mailsession_copy_message(mailsession * session, + uint32_t num, char * mb) +{ + if (session->sess_driver->sess_copy_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_copy_message(session, num, mb); +} + +int mailsession_move_message(mailsession * session, + uint32_t num, char * mb) +{ + if (session->sess_driver->sess_move_message == NULL) { + int r; + + if ((session->sess_driver->sess_copy_message == NULL) && + (session->sess_driver->sess_remove_message == NULL)) + return MAIL_ERROR_NOT_IMPLEMENTED; + + r = mailsession_copy_message(session, num, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = mailsession_remove_message(session, num); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return session->sess_driver->sess_move_message(session, num, mb); +} + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + if (session->sess_driver->sess_get_envelopes_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_envelopes_list(session, env_list); +} + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + if (session->sess_driver->sess_get_messages_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_messages_list(session, result); +} + +int mailsession_remove_message(mailsession * session, uint32_t num) +{ + if (session->sess_driver->sess_remove_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_remove_message(session, num); +} + +#if 0 +int mailsession_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + if (session->sess_driver->sess_search_messages == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_search_messages(session, + charset, key, result); +} +#endif + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message(session, num, result); +} + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message_by_uid == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message_by_uid(session, uid, result); +} diff --git a/kmicromail/libetpan/generic/maildriver.h b/kmicromail/libetpan/generic/maildriver.h new file mode 100644 index 0000000..7da9aea --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver.h @@ -0,0 +1,543 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_H + +#define MAILDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mailsession */ + +/* + mailsession_new creates a new session, using the given driver + + @return the created session is returned +*/ + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +/* + mailsession_free release the memory used by the session +*/ + +void mailsession_free(mailsession * session); + +/* + mailsession_parameters is used to make calls specific to the driver + + @param id is the command to send to the driver, + usually, commands can be found in the header of the driver + + @param value is the parameter of the specific call + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_parameters(mailsession * session, + int id, void * value); + +/* + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) + + The following function can only be used by stream drivers. + mailsession_connect_stream connects a stream to the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_connect_stream(mailsession * session, mailstream * s); + +/* + The following function can only be used by file drivers. + mailsession_connect_path selects the main path of the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_connect_path(mailsession * session, char * path); + +/* + NOTE: works only on stream drivers + + mailsession_starttls switches the current connection to TLS (secure layer) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_starttls(mailsession * session); + +/* + mailsession_login notifies the login and the password to authenticate + to the session + + @param userid the given string is only needed at this function call + (it will be duplicated if necessary) + @param password the given string is only needed at this function call + (it will be duplicated if necessary) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_login(mailsession * session, + char * userid, char * password); + +/* + NOTE: this function doesn't often work on filsystem drivers + + mailsession_logout deconnects the session and closes the stream. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_logout(mailsession * session); + +/* + mailsession_noop does no operation on the session, but it can be + used to poll for the status of the connection. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_noop(mailsession * session); + +/* + NOTE: driver's specific should be used + + mailsession_build_folder_name will return an allocated string with + that contains the complete path of the folder to create + + @param session the sesion + @param mb is the parent mailbox + @param name is the name of the folder to create + @param result the complete path of the folder to create will be + stored in (* result), this name have to be freed with free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_build_folder_name(mailsession * session, char * mb, + char * name, char ** result); + +/* + NOTE: driver's specific should be used + + mailsession_create_folder creates the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_create_folder(mailsession * session, char * mb); + + +/* + NOTE: driver's specific should be used + + mailsession_delete_folder deletes the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_delete_folder(mailsession * session, char * mb); + + +/* + mailsession_rename_folder changes the name of the folder + + @param session the session + @param mb is the name of the mailbox whose name has to be changed + @param new_name is the destination name (the parent + of the new folder folder can be other) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_rename_folder(mailsession * session, + char * mb, char * new_name); + +/* + mailsession_check_folder makes a checkpoint of the session + + @param session the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_check_folder(mailsession * session); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_examine_folder selects a mailbox as readonly + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_examine_folder(mailsession * session, char * mb); + + +/* + mailsession_select_folder selects a mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_select_folder(mailsession * session, char * mb); + + +/* + mailsession_expunge_folder deletes all messages marked \Deleted + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_expunge_folder(mailsession * session); + + +/* + mailsession_status_folder queries the status of the folder + (number of messages, number of recent messages, number of unseen messages) + + @param session the session + @param mb mailbox to query + @param result_messages the number of messages is stored + in (* result_messages) + @param result_recent the number of messages is stored + in (* result_recent) + @param result_unseen the number of messages is stored + in (* result_unseen) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + +/* + mailsession_messages_number queries the number of messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + +/* + mailsession_recent_number queries the number of recent messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of recent messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + +/* + mailsession_unseen_number queries the number of unseen messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of unseen messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +/* + NOTE: driver's specific should be used + + mailsession_list_folders returns the list of all sub-mailboxes + of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_lsub_folders returns the list of subscribed + sub-mailboxes of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_subscribe_folder subscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_subscribe_folder(mailsession * session, char * mb); + +/* + NOTE: driver's specific should be used + + mailsession_unsubscribe_folder unsubscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_unsubscribe_folder(mailsession * session, char * mb); + +/* + mailsession_append_message adds a RFC 2822 message to the current + given mailbox + + @param session the session + @param message is a string that contains the RFC 2822 message + @param size this is the size of the message + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + +/* + NOTE: some drivers does not implement this + + mailsession_copy_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_copy_message(mailsession * session, + uint32_t num, char * mb); + +/* + NOTE: some drivers does not implement this + + mailsession_move_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_move_message(mailsession * session, + uint32_t num, char * mb); + +/* + mailsession_get_messages_list returns the list of message numbers + of the current mailbox. + + @param session the session + @param result the list of message numbers will be stored in (* result), + this structure have to be freed with mailmessage_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +/* + mailsession_get_envelopes_list fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + @param session the session + @param result this is the list of mailmessage structures + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + +/* + NOTE: some drivers does not implement this + + mailsession_remove_message removes the given message from the mailbox. + The message is permanently deleted. + + @param session the session + @param num is the message number + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_remove_message(mailsession * session, uint32_t num); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_search_message returns a list of message numbers that + corresponds to the given criteria. + + @param session the session + @param charset is the charset to use (it can be NULL) + @param key is the list of criteria + @param result the search result is stored in (* result), + this structure have to be freed with mail_search_result_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +#if 0 +int mailsession_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +/* + mailsession_get_message returns a mailmessage structure that corresponds + to the given message number. + * WARNING * mailsession_get_message_by_uid() should be used instead. + + @param session the session + @param num the message number + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +/* + mailsession_get_message_by_uid returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + * WARNING * That will deprecates the use of mailsession_get_message() + + @param session the session + @param uid the message unique identifier + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildriver_errors.h b/kmicromail/libetpan/generic/maildriver_errors.h new file mode 100644 index 0000000..118b259 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_errors.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_ERRORS_H + +#define MAILDRIVER_ERRORS_H + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + +#endif diff --git a/kmicromail/libetpan/generic/maildriver_tools.c b/kmicromail/libetpan/generic/maildriver_tools.c new file mode 100644 index 0000000..105fd9f --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_tools.c @@ -0,0 +1,841 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildriver_tools.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include + +#include "maildriver.h" +#include "mailmessage.h" +#include "mailstream.h" +#include "mailmime.h" +#include "mail_cache_db.h" + +/* ********************************************************************* */ +/* tools */ + + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned i; +#if 0 + uint32_t j; + uint32_t last_msg; + + last_msg = 0; +#endif + +#if 0 + j = 0; + i = 0; + while (i < env_list->tab->len) { + mailmessage * msg; + uint32_t index; + + msg = carray_get(env_list->tab, i); + + index = msg->index; + + if (msg->fields == NULL) { + struct mailimf_fields * fields; + + r = mailmessage_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) { + /* do nothing */ + } + else { + msg->fields = fields; + + carray_set(env_list->tab, j, msg); + + j ++; + last_msg = i + 1; + } + mailmessage_flush(msg); + } + else { + j ++; + last_msg = i + 1; + } + + i ++; + } + + for(i = last_msg ; i < env_list->tab->len ; i ++) { + mailmessage_free(carray_get(env_list->tab, i)); + carray_set(env_list->tab, i, NULL); + } + + r = carray_set_size(env_list->tab, j); + if (r < 0) + return MAIL_ERROR_MEMORY; +#endif + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + struct mailimf_fields * fields; + + r = mailmessage_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) { + /* do nothing */ + } + else { + msg->msg_fields = fields; + } + mailmessage_flush(msg); + } + } + + return MAIL_NO_ERROR; +} + + +#if 0 +static int is_search_header_only(struct mail_search_key * key) +{ + clistiter * cur; + int result; + + switch (key->type) { + case MAIL_SEARCH_KEY_ANSWERED: + case MAIL_SEARCH_KEY_BCC: + case MAIL_SEARCH_KEY_BEFORE: + case MAIL_SEARCH_KEY_CC: + case MAIL_SEARCH_KEY_DELETED: + case MAIL_SEARCH_KEY_FLAGGED: + case MAIL_SEARCH_KEY_FROM: + case MAIL_SEARCH_KEY_NEW: + case MAIL_SEARCH_KEY_OLD: + case MAIL_SEARCH_KEY_ON: + case MAIL_SEARCH_KEY_RECENT: + case MAIL_SEARCH_KEY_SEEN: + case MAIL_SEARCH_KEY_SINCE: + case MAIL_SEARCH_KEY_SUBJECT: + case MAIL_SEARCH_KEY_TO: + case MAIL_SEARCH_KEY_UNANSWERED: + case MAIL_SEARCH_KEY_UNDELETED: + case MAIL_SEARCH_KEY_UNFLAGGED: + case MAIL_SEARCH_KEY_UNSEEN: + case MAIL_SEARCH_KEY_HEADER: + case MAIL_SEARCH_KEY_LARGER: + case MAIL_SEARCH_KEY_NOT: + case MAIL_SEARCH_KEY_SMALLER: + case MAIL_SEARCH_KEY_ALL: + return TRUE; + + case MAIL_SEARCH_KEY_BODY: + case MAIL_SEARCH_KEY_TEXT: + return FALSE; + + case MAIL_SEARCH_KEY_OR: + return (is_search_header_only(key->or1) && + is_search_header_only(key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + result = TRUE; + for (cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) + result = result && is_search_header_only(clist_content(cur)); + return result; + + default: + return TRUE; + } +} + +static int match_header(struct mailimf_fields * fields, + char * name, char * value) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == + (char) toupper((unsigned char) name[0])) { + if (strcasecmp(opt_field->name, name) == 0) + if (strstr(opt_field->value, value) != NULL) + return TRUE; + } + } + return FALSE; +} + +static int comp_date(struct mailimf_fields * fields, + struct mailimf_date_time * ref_date) +{ + clistiter * cur; + struct mailimf_date_time * date; + int r; + + date = NULL; + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == 'D') { + if (strcasecmp(opt_field->name, "Date") == 0) { + size_t cur_token; + + cur_token = 0; + r = mailimf_date_time_parse(opt_field->value, strlen(opt_field->value), + &cur_token, &date); + if (r == MAILIMF_NO_ERROR) + break; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + break; + } + } + } + + if (date == NULL) + return 0; + + return mailimf_date_time_comp(date, ref_date); +} + +static int match_messages(char * message, + size_t size, + struct mailimf_fields * fields, + int32_t flags, + char * charset, + struct mail_search_key * key) +{ + clistiter * cur; + size_t length; + size_t cur_token; + int r; + + switch (key->type) { + + /* flags */ + case MAIL_SEARCH_KEY_ANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) != 0); + + case MAIL_SEARCH_KEY_FLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) != 0); + + case MAIL_SEARCH_KEY_DELETED: + return ((flags & MAIL_FLAG_DELETED) != 0); + + case MAIL_SEARCH_KEY_RECENT: + return ((flags & MAIL_FLAG_NEW) != 0) && + ((flags & MAIL_FLAG_SEEN) == 0); + + case MAIL_SEARCH_KEY_SEEN: + return ((flags & MAIL_FLAG_SEEN) != 0); + + case MAIL_SEARCH_KEY_NEW: + return ((flags & MAIL_FLAG_NEW) != 0); + + case MAIL_SEARCH_KEY_OLD: + return ((flags & MAIL_FLAG_NEW) == 0); + + case MAIL_SEARCH_KEY_UNANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) == 0); + + case MAIL_SEARCH_KEY_UNDELETED: + return ((flags & MAIL_FLAG_DELETED) == 0); + + case MAIL_SEARCH_KEY_UNFLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) == 0); + + case MAIL_SEARCH_KEY_UNSEEN: + return ((flags & MAIL_FLAG_SEEN) == 0); + + /* headers */ + case MAIL_SEARCH_KEY_BCC: + return match_header(fields, "Bcc", key->bcc); + + case MAIL_SEARCH_KEY_CC: + return match_header(fields, "Cc", key->cc); + + case MAIL_SEARCH_KEY_FROM: + return match_header(fields, "From", key->from); + + case MAIL_SEARCH_KEY_SUBJECT: + return match_header(fields, "Subject", key->subject); + + case MAIL_SEARCH_KEY_TO: + return match_header(fields, "To", key->to); + + case MAIL_SEARCH_KEY_HEADER: + return match_header(fields, key->header_name, key->header_value); + + /* date */ + case MAIL_SEARCH_KEY_BEFORE: + return (comp_date(fields, key->before) <= 0); + + case MAIL_SEARCH_KEY_ON: + return (comp_date(fields, key->before) == 0); + + case MAIL_SEARCH_KEY_SINCE: + return (comp_date(fields, key->before) >= 0); + + /* boolean */ + case MAIL_SEARCH_KEY_NOT: + return (!match_messages(message, size, fields, flags, charset, key->not)); + case MAIL_SEARCH_KEY_OR: + return (match_messages(message, size, fields, flags, charset, key->or1) || + match_messages(message, size, fields, flags, charset, key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + for(cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) { + if (!match_messages(message, size, fields, flags, charset, + clist_content(cur))) + return FALSE; + } + + return TRUE; + + /* size */ + case MAIL_SEARCH_KEY_SMALLER: + return (size <= key->smaller); + + case MAIL_SEARCH_KEY_LARGER: + return (size >= key->larger); + + case MAIL_SEARCH_KEY_BODY: + length = strlen(message); + + cur_token = 0; + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + return (strstr(message + cur_token, key->body) != NULL); + + case MAIL_SEARCH_KEY_TEXT: + return (strstr(message, key->body) != NULL); + + case MAIL_SEARCH_KEY_ALL: + default: + return TRUE; + } +} + +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + int header; + clist * list; + struct mail_search_result * search_result; + int r; + struct mailmessage_list * env_list; + int res; + unsigned int i; + + header = is_search_header_only(key); + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) + return r; + + list = NULL; + for(i = 0 ; i < carray_count(env_list->tab) ; i ++) { + char * message; + size_t length; + struct mail_info * info; + uint32_t flags; + struct mailimf_fields * fields; + size_t cur_token; + + info = carray_get(env_list->tab, i); + + if (!header) { + r = mailsession_fetch_message(session, info->index, &message, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cur_token = 0; + r = mailimf_optional_fields_parse(message, length, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + } + else { + char * msg_header; + int r; + size_t cur_token; + size_t header_len; + + r = mailsession_fetch_message_header(session, info->index, &msg_header, + &header_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + message = NULL; + cur_token = 0; + r = mailimf_optional_fields_parse(msg_header, header_len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + + mailsession_fetch_result_free(session, msg_header); + } + + r = mailsession_get_message_flags(session, info->index, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (match_messages(message, info->size, fields, flags, + charset, key)) { + uint32_t * pnum; + + pnum = malloc(sizeof(* pnum)); + if (pnum == NULL) { + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * pnum = info->index; + + r = clist_append(list, pnum); + if (r < 0) { + free(pnum); + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (message != NULL) + mailsession_fetch_result_free(session, message); + } + + search_result = mail_search_result_new(list); + if (search_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = search_result; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + mailmessage_list_free(env_list); + return res; +} +#endif + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + return MAIL_ERROR_NOT_IMPLEMENTED; +} +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + + +int maildriver_imf_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMF_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMF_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMF_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMF_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILIMF_ERROR_FILE: + return MAIL_ERROR_FILE; + + default: + return MAIL_ERROR_INVAL; + } +} + +char * maildriver_quote_mailbox(char * mb) +{ + MMAPString * gstr; + char * str; + + gstr = mmap_string_new(""); + if (gstr == NULL) + return NULL; + + while (* mb != 0) { + char hex[3]; + + if (((* mb >= 'a') && (* mb <= 'z')) || + ((* mb >= 'A') && (* mb <= 'Z')) || + ((* mb >= '0') && (* mb <= '9'))) + mmap_string_append_c(gstr, * mb); + else { + if (mmap_string_append_c(gstr, '%') == NULL) + goto free; + snprintf(hex, 3, "%02x", (unsigned char) (* mb)); + if (mmap_string_append(gstr, hex) == NULL) + goto free; + } + mb ++; + } + + str = strdup(gstr->str); + if (str == NULL) + goto free; + + mmap_string_free(gstr); + + return str; + + free: + mmap_string_free(gstr); + return NULL; +} + + + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + char keyname[PATH_MAX]; + unsigned int i; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + if (cache_db_env != NULL) { + snprintf(keyname, PATH_MAX, "%s-envelope", msg->msg_uid); + + key.data = keyname; + key.len = strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + if (cache_db_flags != NULL) { + snprintf(keyname, PATH_MAX, "%s-flags", msg->msg_uid); + + key.data = keyname; + key.len = strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + /* clean up */ + if (cache_db_env != NULL) + mail_cache_db_clean_up(cache_db_env, hash_exist); + if (cache_db_flags != NULL) + mail_cache_db_clean_up(cache_db_flags, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + + +/* + maildriver_message_cache_clean_up() + + remove files in cache_dir that does not correspond to a message. + + get_uid_from_filename() modifies the given filename so that it + is a uid when returning from the function. If get_uid_from_filename() + clears the content of file (set to empty string), this means that + this file should not be deleted. +*/ + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)) +{ + chash * hash_exist; + DIR * d; + char cached_filename[PATH_MAX]; + struct dirent * ent; + char keyname[PATH_MAX]; + unsigned int i; + int res; + int r; + + /* remove files */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + value.data = NULL; + value.len = 0; + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + d = opendir(cache_dir); + while ((ent = readdir(d)) != NULL) { + chashdatum key; + chashdatum value; + + if (strcmp(ent->d_name, ".") == 0) + continue; + + if (strcmp(ent->d_name, "..") == 0) + continue; + + if (strstr(ent->d_name, ".db") != NULL) + continue; + + strncpy(keyname, ent->d_name, sizeof(keyname)); + keyname[sizeof(keyname) - 1] = '\0'; + + get_uid_from_filename(keyname); + + if (* keyname == '\0') + continue; + + key.data = keyname; + key.len = strlen(keyname); + + r = chash_get(hash_exist, &key, &value); + if (r < 0) { + snprintf(cached_filename, sizeof(cached_filename), + "%s/%s", cache_dir, ent->d_name); + unlink(cached_filename); + } + } + closedir(d); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/maildriver_tools.h b/kmicromail/libetpan/generic/maildriver_tools.h new file mode 100644 index 0000000..eaddc5d --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_tools.h @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_TOOLS_H + +#define MAILDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_imf_error_to_mail_error(int error); + +char * maildriver_quote_mailbox(char * mb); + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list); + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildriver_types.c b/kmicromail/libetpan/generic/maildriver_types.c new file mode 100644 index 0000000..7b3b348 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_types.c @@ -0,0 +1,340 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildriver_types.h" +#include +#include +#include "mailmessage.h" + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab) +{ + struct mailmessage_list * env_list; + + env_list = malloc(sizeof(* env_list)); + if (env_list == NULL) + return NULL; + + env_list->msg_tab = msg_tab; + + return env_list; +} + +void mailmessage_list_free(struct mailmessage_list * env_list) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg != NULL) + mailmessage_free(msg); + } + carray_free(env_list->msg_tab); + free(env_list); +} + +struct mail_list * mail_list_new(clist * list) +{ + struct mail_list * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + resp->mb_list = list; + + return resp; +} + +void mail_list_free(struct mail_list * resp) +{ + clist_foreach(resp->mb_list, (clist_func) free, NULL); + clist_free(resp->mb_list); + free(resp); +} + +static int32_t mailimf_date_time_to_int(struct mailimf_date_time * date) +{ + return date->dt_year * 12 * 30 * 24 * 60 * 60 + + date->dt_month * 30 * 24 * 60 * 60 + date->dt_day * 24 * 60 * 60 + + (date->dt_hour - date->dt_zone) * 60 * 60 + + date->dt_min * 60 + date->dt_sec; +} + +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2) +{ + return mailimf_date_time_to_int(date1) - mailimf_date_time_to_int(date2); +} + + + + + + + +#if 0 +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, + struct mailimf_date_time * sk_before, + char * sk_body, + char * sk_cc, + char * sk_from, + struct mailimf_date_time * sk_on, + struct mailimf_date_time * sk_since, + char * sk_subject, + char * sk_text, + char * sk_to, + char * sk_header_name, + char * sk_header_value, + size_t sk_larger, + struct mail_search_key * sk_not, + struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, + size_t sk_smaller, + clist * sk_multiple) +{ + struct mail_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + key->sk_bcc = sk_bcc; + key->sk_before = sk_before; + key->sk_body = sk_body; + key->sk_cc = sk_cc; + key->sk_from = sk_from; + key->sk_on = sk_on; + key->sk_since = sk_since; + key->sk_subject = sk_subject; + key->sk_text = sk_text; + key->sk_to = sk_to; + key->sk_header_name = sk_header_name; + key->sk_header_value = sk_header_value; + key->sk_larger = sk_larger; + key->sk_not = sk_not; + key->sk_or1 = sk_or1; + key->sk_or2 = sk_or2; + key->sk_smaller = sk_smaller; + key->sk_multiple = sk_multiple; + + return key; +} + + +void mail_search_key_free(struct mail_search_key * key) +{ + if (key->sk_bcc) + free(key->sk_bcc); + if (key->sk_before) + mailimf_date_time_free(key->sk_before); + if (key->sk_body) + free(key->sk_body); + if (key->sk_cc) + free(key->sk_cc); + if (key->sk_from) + free(key->sk_from); + if (key->sk_on) + mailimf_date_time_free(key->sk_on); + if (key->sk_since) + mailimf_date_time_free(key->sk_since); + if (key->sk_subject) + free(key->sk_subject); + if (key->sk_text) + free(key->sk_text); + if (key->sk_to) + free(key->sk_to); + if (key->sk_header_name) + free(key->sk_header_name); + if (key->sk_header_value) + free(key->sk_header_value); + if (key->sk_not) + mail_search_key_free(key->sk_not); + if (key->sk_or1) + mail_search_key_free(key->sk_or1); + if (key->sk_or2) + mail_search_key_free(key->sk_or2); + if (key->sk_multiple) { + clist_foreach(key->sk_multiple, (clist_func) mail_search_key_free, NULL); + clist_free(key->sk_multiple); + } + + free(key); +} + + +struct mail_search_result * mail_search_result_new(clist * list) +{ + struct mail_search_result * search_result; + + search_result = malloc(sizeof(* search_result)); + if (search_result == NULL) + return NULL; + search_result->list = list; + + return search_result; +} + +void mail_search_result_free(struct mail_search_result * search_result) +{ + clist_foreach(search_result->list, (clist_func) free, NULL); + clist_free(search_result->list); + free(search_result); +} +#endif + +struct error_message { + int code; + char * message; +}; + +static struct error_message message_tab[] = { +{ MAIL_NO_ERROR, "no error" }, +{ MAIL_NO_ERROR_AUTHENTICATED, "no error - authenticated" }, +{ MAIL_NO_ERROR_NON_AUTHENTICATED, "no error - not authenticated" }, +{ MAIL_ERROR_NOT_IMPLEMENTED, "not implemented" }, +{ MAIL_ERROR_UNKNOWN, "unknown"}, +{ MAIL_ERROR_CONNECT, "connect"}, +{ MAIL_ERROR_BAD_STATE, "bad state"}, +{ MAIL_ERROR_FILE, "file error - file could not be accessed" }, +{ MAIL_ERROR_STREAM, "stream error - socket could not be read or written" }, +{ MAIL_ERROR_LOGIN, "login error" }, +{ MAIL_ERROR_CREATE, "create error" }, +{ MAIL_ERROR_DELETE, /* 10 */ "delete error" }, +{ MAIL_ERROR_LOGOUT, "logout error" }, +{ MAIL_ERROR_NOOP, "noop error" }, +{ MAIL_ERROR_RENAME, "rename error" }, +{ MAIL_ERROR_CHECK, "check error" }, +{ MAIL_ERROR_EXAMINE, "examine error" }, +{ MAIL_ERROR_SELECT, "select error - folder does not exist" }, +{ MAIL_ERROR_MEMORY, "not enough memory" }, +{ MAIL_ERROR_STATUS, "status error" }, +{ MAIL_ERROR_SUBSCRIBE, "subscribe error" }, +{ MAIL_ERROR_UNSUBSCRIBE, /* 20 */ "unsubscribe error" }, +{ MAIL_ERROR_LIST, "list error" }, +{ MAIL_ERROR_LSUB, "lsub error" }, +{ MAIL_ERROR_APPEND, "append error - mail could not be appended" }, +{ MAIL_ERROR_COPY, "copy error" }, +{ MAIL_ERROR_FETCH, "fetch error" }, +{ MAIL_ERROR_STORE, "store error" }, +{ MAIL_ERROR_SEARCH, "search error" }, +{ MAIL_ERROR_DISKSPACE, " error: not enough diskspace" }, +{ MAIL_ERROR_MSG_NOT_FOUND, "message not found" }, +{ MAIL_ERROR_PARSE, /* 30 */ "parse error" }, +{ MAIL_ERROR_INVAL, "invalid parameter for the function" }, +{ MAIL_ERROR_PART_NOT_FOUND, "mime part of the message is not found" }, +{ MAIL_ERROR_REMOVE, "remove error - the message did not exist" }, +{ MAIL_ERROR_FOLDER_NOT_FOUND, "folder not found" }, +{ MAIL_ERROR_MOVE, "move error" }, +{ MAIL_ERROR_STARTTLS, "starttls error" }, +{ MAIL_ERROR_CACHE_MISS, "mail cache missed" }, +{ MAIL_ERROR_NO_TLS, "no starttls" }, +{ MAIL_ERROR_EXPUNGE, "expunge error" }, +{ MAIL_ERROR_PROTOCOL, "protocol error - server did not respect the protocol" }, +{ MAIL_ERROR_CAPABILITY, "capability error" }, +{ MAIL_ERROR_CLOSE, "close error" }, +{ MAIL_ERROR_FATAL, "fatal error" }, +{ MAIL_ERROR_READONLY, "mailbox is readonly" }, +{ MAIL_ERROR_NO_APOP, "pop3 error - no apop" }, +{ MAIL_ERROR_COMMAND_NOT_SUPPORTED, "nntp error - command not supported" }, +{ MAIL_ERROR_NO_PERMISSION, "nntp error - no permission" }, +{ MAIL_ERROR_PROGRAM_ERROR, "nntp error - program error" }, +{ MAIL_ERROR_SUBJECT_NOT_FOUND, "internal threading error - subject not found" }}; + +const char * maildriver_strerror(int err) +{ + int count; + int i; + + count = sizeof(message_tab) / sizeof(struct error_message); + + for(i = 0 ; i < count ; i++) { + if (message_tab[i].code == err) { + return message_tab[i].message; + } + } + + return "unknown error"; +} + + +struct mail_flags * mail_flags_new_empty(void) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = MAIL_FLAG_NEW; + flags->fl_extension = clist_new(); + if (flags->fl_extension == NULL) + goto free; + + return flags; + + free: + free(flags); + err: + return NULL; +} + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_extension) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = fl_flags; + flags->fl_extension = fl_extension; + + return flags; + +err: + return NULL; +} + +void mail_flags_free(struct mail_flags * flags) +{ + clist_foreach(flags->fl_extension, (clist_func) free, NULL); + clist_free(flags->fl_extension); + free(flags); +} + diff --git a/kmicromail/libetpan/generic/maildriver_types.h b/kmicromail/libetpan/generic/maildriver_types.h new file mode 100644 index 0000000..3ff9440 --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_types.h @@ -0,0 +1,793 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_TYPES_H + +#define MAILDRIVER_TYPES_H + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mailsession_driver mailsession_driver; + +typedef struct mailsession mailsession; + +typedef struct mailmessage_driver mailmessage_driver; + +typedef struct mailmessage mailmessage; + + +/* + mailmessage_list is a list of mailmessage + + - tab is an array of mailmessage structures +*/ + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); +void mailmessage_list_free(struct mailmessage_list * env_list); + +/* + mail_list is a list of mailbox names + + - list is a list of mailbox names +*/ + +struct mail_list { + clist * mb_list; /* elements are (char *) */ +}; + +struct mail_list * mail_list_new(clist * mb_list); +void mail_list_free(struct mail_list * resp); + +/* + This is a flag value. + Flags can be combined with OR operation +*/ + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +/* + mail_flags is the value of a flag related to a message. + + - flags is the standard flags value + + - extension is a list of unknown flags for libEtPan! +*/ + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); +void mail_flags_free(struct mail_flags * flags); + +/* + This function creates a flag for a new message +*/ + +struct mail_flags * mail_flags_new_empty(void); + + +/* + mailimf_date_time_comp compares two dates + + +*/ + +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2); + +/* + this is type type of the search criteria +*/ + +enum { + MAIL_SEARCH_KEY_ALL, /* all messages correspond */ + MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */ + MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains + a given string */ + MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier + than the specified date */ + MAIL_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAIL_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAIL_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAIL_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAIL_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAIL_SEARCH_KEY_NOT, /* not operation of the condition */ + MAIL_SEARCH_KEY_OR, /* or operation between two conditions */ + MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mail_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAIL_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAIL_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAIL_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAIL_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAIL_SEARCH_KEY_FROM, should be allocated with malloc() + + - on is a date when type is MAIL_SEARCH_KEY_ON + + - since is a date when type is MAIL_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +#if 0 +struct mail_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimf_date_time * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + struct mailimf_date_time * sk_on; + struct mailimf_date_time * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_header_name; + char * sk_header_value; + size_t sk_larger; + struct mail_search_key * sk_not; + struct mail_search_key * sk_or1; + struct mail_search_key * sk_or2; + size_t sk_smaller; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + + +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, struct mailimf_date_time * sk_before, + char * sk_body, char * sk_cc, char * sk_from, + struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_header_name, char * sk_header_value, size_t sk_larger, + struct mail_search_key * sk_not, struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, size_t sk_smaller, + clist * sk_multiple); + +void mail_search_key_free(struct mail_search_key * key); +#endif + +/* + mail_search_result is a list of message numbers that is returned + by the mailsession_search_messages function() +*/ + +#if 0 +struct mail_search_result { + clist * sr_list; /* list of (uint32_t *) */ +}; + +struct mail_search_result * mail_search_result_new(clist * sr_list); + +void mail_search_result_free(struct mail_search_result * search_result); +#endif + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - build_folder_name() will return an allocated string with + that contains the complete path of the folder to create + + - create_folder() creates the folder that corresponds to the + given name + + - delete_folder() deletes the folder that corresponds to the + given name + + - rename_folder() change the name of the folder + + - check_folder() makes a checkpoint of the session + + - examine_folder() selects a mailbox as readonly + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - messages_number() queries the number of messages in the folder + + - recent_number() queries the number of recent messages in the folder + + - unseen_number() queries the number of unseen messages in the folder + + - list_folders() returns the list of all sub-mailboxes + of the given mailbox + + - lsub_folders() returns the list of subscribed + sub-mailboxes of the given mailbox + + - subscribe_folder() subscribes to the given mailbox + + - unsubscribe_folder() unsubscribes to the given mailbox + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - copy_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from + the same session. + + - move_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the + same session. + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - search_message() returns a list of message numbers that + corresponds to the given criteria. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + - get_message_by_uid returns a mailmessage structure that corresponds + to the given message unique identifier. + + * mandatory functions are the following : + + - connect_stream() of connect_path() + - logout() + - get_messages_list() + - get_envelopes_list() + + * we advise you to implement these functions : + + - select_folder() (in case a session can access several folders) + - noop() (to check if the server is responding) + - check_folder() (to make a checkpoint of the session) + - status_folder(), messages_number(), recent_number(), unseen_number() + (to get stat of the folder) + - append_message() (but can't be done in the case of POP3 at least) + - login() in a case of an authenticated driver. + - starttls() in a case of a stream driver, if the procotol supports + STARTTLS. + - get_message_by_uid() so that the application can remember the message + by UID and build its own list of messages. + + * drivers' specific : + + Everything that is specific to the driver will be implemented in this + function : + + - parameters() +*/ + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +#if 0 + int (* sess_search_messages)(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif +}; + + +/* + session is the data structure for a mail session. + + - data is the internal data structure used by the driver + It is called when initializing the mailsession structure. + + - driver is the driver used for the session +*/ + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + + + + +/* + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. +*/ + +#define LIBETPAN_MAIL_MESSAGE_CHECK + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + +/* + mailmessage is a data structure to get information from messages + + - session is the session linked to the given message, it can be NULL + + - driver is the message driver + + - index is the message number + + - uid, when it is not NULL, it means that the folder + the folder has persistant message numbers, the string is + the unique message number in the folder. + uid should be implemented if possible. + for drivers where we cannot generate real uid, + a suggestion is "AAAA-IIII" where AAAA is some + random session number and IIII the content of index field. + + - size, when it is not 0, is the size of the message content. + + - fields, when it is not NULL, are the header fields of the message. + + - flags, when it is not NULL, are the flags related to the message. + + - single_fields, when resolved != 0, is filled with the data of fields. + + - mime, when it is not NULL + + - cached is != 0 when the header fields were read from the cache. + + - data is data specific to the driver, this is internal data structure, + some state of the message. +*/ + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + +/* + mailmessage_tree is a node in the messages tree (thread) + + - parent is the parent of the message, it is NULL if the message + is the root of the message tree. + + - date is the date of the message in number of second elapsed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + + - msg is the message structure that is stored referenced by the node. + is msg is NULL, this is a dummy node. + + - children is an array that contains all the children of the node. + children are mailmessage_tree structures. + + - is_reply is != 0 when the message is a reply or a forward + + - base_subject is the extracted subject of the message. + + - index is the message number. +*/ + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +/* + mailmessage_tree_free_recursive + + if you want to release memory of the given tree and all the sub-trees, + you can use this function. +*/ + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + +struct generic_message_t { + int (* msg_prefetch)(mailmessage * msg_info); + void (* msg_prefetch_free)(struct generic_message_t * msg); + int msg_fetched; + char * msg_message; + size_t msg_length; + void * msg_data; +}; + + +const char * maildriver_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/maildriver_types_helper.c b/kmicromail/libetpan/generic/maildriver_types_helper.c new file mode 100644 index 0000000..580af7d --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_types_helper.c @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildriver_types_helper.h" + +#include "mail.h" + +#include "clist.h" +#include +#include + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag) +{ + char * str; + int r; + + if (mail_flags_has_extension(flags, ext_flag)) + return MAIL_NO_ERROR; + + str = strdup(ext_flag); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = clist_append(flags->fl_extension, str); + if (r < 0) { + free(str); + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + cur = clist_begin(flags->fl_extension); + while (cur != NULL) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) { + free(flag_name); + cur = clist_delete(flags->fl_extension, cur); + } + else + cur = clist_next(cur); + } + + return MAIL_NO_ERROR; +} + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) + return TRUE; + } + + return FALSE; +} diff --git a/kmicromail/libetpan/generic/maildriver_types_helper.h b/kmicromail/libetpan/generic/maildriver_types_helper.h new file mode 100644 index 0000000..2e74dea --- a/dev/null +++ b/kmicromail/libetpan/generic/maildriver_types_helper.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_TYPES_HELPER_H + +#define MAILDRIVER_TYPES_HELPER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_flags_add_extension adds the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is duplicated and is no more needed after + the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_remove_extension removes the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_has_extension returns 1 if the flags is in the given flags, + 0 is returned otherwise. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailfolder.c b/kmicromail/libetpan/generic/mailfolder.c new file mode 100644 index 0000000..2ddc37d --- a/dev/null +++ b/kmicromail/libetpan/generic/mailfolder.c @@ -0,0 +1,96 @@ +#include "mailfolder.h" + +#include "maildriver.h" + +int mailfolder_noop(struct mailfolder * folder) +{ + return mailsession_noop(folder->fld_session); +} + +int mailfolder_check(struct mailfolder * folder) +{ + return mailsession_check_folder(folder->fld_session); +} + +int mailfolder_expunge(struct mailfolder * folder) +{ + return mailsession_expunge_folder(folder->fld_session); +} + +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(folder->fld_session, + folder->fld_pathname, result_messages, + result_recent, result_unseen); +} + +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size) +{ + return mailsession_append_message(folder->fld_session, message, size); +} + +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result) +{ + int r; + struct mailmessage_list * msg_list; + unsigned int i; + + r = mailsession_get_messages_list(folder->fld_session, &msg_list); + if (r != MAIL_NO_ERROR) + return r; + + for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(msg_list->msg_tab, i); + msg->msg_folder = folder; + } + + * result = msg_list; + + return MAIL_NO_ERROR; +} + +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result) +{ + return mailsession_get_envelopes_list(folder->fld_session, result); +} + +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message(folder->fld_session, num, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} + +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/mailfolder.h b/kmicromail/libetpan/generic/mailfolder.h new file mode 100644 index 0000000..3ecad23 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailfolder.h @@ -0,0 +1,32 @@ +#ifndef MAILFOLDER_H + +#define MAILFOLDER_H + +#include "mailstorage_types.h" + +int mailfolder_noop(struct mailfolder * folder); + +int mailfolder_check(struct mailfolder * folder); + +int mailfolder_expunge(struct mailfolder * folder); + +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + +#endif diff --git a/kmicromail/libetpan/generic/mailmessage.c b/kmicromail/libetpan/generic/mailmessage.c new file mode 100644 index 0000000..9d3884f --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage.c @@ -0,0 +1,240 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmessage.h" + +#include "mail.h" + +#include + +int mailmessage_init(mailmessage * msg_info, + mailsession * msg_session, + mailmessage_driver * msg_driver, + uint32_t msg_index, size_t msg_size) +{ + int r; + int res; + + msg_info->msg_driver = msg_driver; + msg_info->msg_session = msg_session; + msg_info->msg_index = msg_index; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = msg_size; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, 0, + sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + if (msg_driver->msg_initialize != NULL) { + r = msg_driver->msg_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + return res; +} + +int mailmessage_flush(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_flush == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_flush(msg_info); + + return MAIL_NO_ERROR; +} + +int mailmessage_check(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_check == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_check(msg_info); + + return MAIL_NO_ERROR; +} + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg_info->msg_driver->msg_fetch_result_free == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch(msg_info, result, result_len); +} + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_header(msg_info, result, result_len); +} + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_body(msg_info, result, result_len); +} + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result) +{ + if (msg_info->msg_driver->msg_fetch_size == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_size(msg_info, result); +} + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_driver->msg_get_bodystructure == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_get_bodystructure(msg_info, result); +} + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section(msg_info, mime, result, result_len); +} + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_header(msg_info, mime, + result, result_len); +} + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_mime == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_mime(msg_info, mime, + result, result_len); +} + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_body(msg_info, mime, + result, result_len); +} + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + if (msg_info->msg_driver->msg_fetch_envelope == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_envelope(msg_info, result); +} + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_flags * dummy; + + if (msg_info->msg_driver->msg_get_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + if (result != NULL) + return msg_info->msg_driver->msg_get_flags(msg_info, result); + else + return msg_info->msg_driver->msg_get_flags(msg_info, &dummy); +} + +void mailmessage_resolve_single_fields(mailmessage * msg_info) +{ + if (!msg_info->msg_resolved) { + if (msg_info->msg_fields != NULL) { + mailimf_single_fields_init(&msg_info->msg_single_fields, + msg_info->msg_fields); + msg_info->msg_resolved = TRUE; + } + } +} diff --git a/kmicromail/libetpan/generic/mailmessage.h b/kmicromail/libetpan/generic/mailmessage.h new file mode 100644 index 0000000..df9b790 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage.h @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include + +#ifndef MAILMESSAGE_H + +#define MAILMESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailmessage_new + + This function will initializes a new empty message. + + @return a new empty message will be returned. +*/ + +mailmessage * mailmessage_new(void); + +/* + mailmessage_free + + This function will release the memory used by this message. +*/ + +void mailmessage_free(mailmessage * info); + +/* + mailmessage_init + + This function will initializes a mailmessage structure + with a message from a given session. + + @param msg_info This is the message to initialize. + + @param session This is the source session of the message. It + can be NULL if the message does not get the information + through the session. + + @param driver This is the driver to use for the message. + + @param index This is the message number in the session. 0 can + be given if the message is not attached to a session. + + @param size is an optional parameter, 0 can be given. + This is informational. This is the size of message content. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + +/* + mailmessage_flush + + This function will release all the temporary resources that are not + necessary to use the mailmessage structure from memory. These + resources are for example cached information, such as the MIME + structure. + + @param info is the message to clean. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_flush(mailmessage * info); + +/* + mailmessage_check + + This function will notify the new value of the flags to the session, + it must be called before mailsession_check_folder() in case the flags have + been changed. + + @param info is the message to checkpoint. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_check(mailmessage * info); + +/* + mailmessage_fetch_result_free + + This function releases the memory used by a message returned + by any of the fetch function that returns a (char *). + + @param msg_info is the message which the given buffer is from. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + +/* + mailmessage_fetch + + This function returns the content of the message (headers and text). + + @param msg_info is the message from which we want to fetch information. + + @param result The content of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_header + + This function returns the header of the message as a string. + + @param msg_info is the message from which we want to fetch information. + + @param result The header of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_body + + This function returns the content of the message (without headers). + + @param msg_info is the message from which we want to fetch information. + @param result The message text (without headers) is returned + in (* result) + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_size + + This function returns the size of the message content. + + @param msg_info is the message from which we want to fetch information. + + @param result The length of the message content is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + +/* + mailmessage_get_bodystructure + + This functions returns the MIME structure of the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The MIME structure is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +/* + mailmessage_fetch_section + + This function returns the content of a MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The content is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_section_header + + This function returns the header of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_mime + + This function returns the MIME header of the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The MIME header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_body + + This function returns the text part of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The message text is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_envelope + + This function returns a list of parsed fields of the message, + chosen by the driver. + The returned structure must be freed with mailimf_fields_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The headers list is returned in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + +/* + mailmessage_get_flags + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The flags are stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +/* + mailmessage_resolve_single_fields + + This function will use the fields information to fill the single_fields + structure in the mailmessage structure. + + @param msg_info This is the msg_info to process. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailmessage_tools.c b/kmicromail/libetpan/generic/mailmessage_tools.c new file mode 100644 index 0000000..e66f6ba --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage_tools.c @@ -0,0 +1,600 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmessage_tools.h" +#include "mailmessage.h" + +#include + +#include "maildriver.h" +#include "maildriver_tools.h" + +int +mailmessage_generic_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + msg = malloc(sizeof(* msg)); + + if (msg == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg->msg_fetched = 0; + msg->msg_message = NULL; + msg->msg_length = 0; + + msg->msg_prefetch = NULL; + msg->msg_prefetch_free = NULL; + msg->msg_data = NULL; + + msg_info->msg_data = msg; + + return MAIL_NO_ERROR; +} + +void mailmessage_generic_flush(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } + msg = msg_info->msg_data; + if (msg != NULL) { + if (msg->msg_prefetch_free != NULL) + msg->msg_prefetch_free(msg); + msg->msg_fetched = 0; + } +} + +void mailmessage_generic_uninitialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + mailmessage_generic_flush(msg_info); + + msg = msg_info->msg_data; + msg_info->msg_data = NULL; + free(msg); +} + +static inline int +mailmessage_generic_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_fetched) + return MAIL_NO_ERROR; + +#if 0 + if (msg->message != NULL) + return MAIL_NO_ERROR; +#endif + + r = msg->msg_prefetch(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_fetched = 1; + + return MAIL_NO_ERROR; +} + +static int +mailmessage_generic_prefetch_bodystructure(mailmessage * msg_info) +{ + size_t length; + char * message; + size_t cur_token; + struct mailmime * mime; + int r; + int res; + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + /* it has already been fetched */ + return MAIL_NO_ERROR; + } + +#if 0 + msg = msg_info->data; + if (msg->message == NULL) { + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } +#endif + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + msg = msg_info->msg_data; + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + r = mailmime_parse(message, length, &cur_token, &mime); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + msg_info->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +void +mailmessage_generic_fetch_result_free(mailmessage * msg_info, char * msg) +{ + int r; + + r = mmap_string_unref(msg); +} + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + size_t length; + MMAPString * mmapstr; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + mmapstr = mmap_string_new_len(message, length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + size_t length; + MMAPString * mmapstr; + char * headers; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + headers = mmapstr->str; + + * result = headers; + * result_len = cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + MMAPString * mmapstr; + size_t length; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + + + + +int +mailmessage_generic_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + + r = mailmessage_generic_prefetch_bodystructure(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + + + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + /* skip mime */ + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_mime_start, + mime->mm_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_mime_start, mime->mm_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + mmapstr = mmap_string_new_len(mime->mm_mime_start, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data + + cur_token, mime->mm_body->dt_data.dt_text.dt_length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + char * header; + size_t length; + struct mailimf_fields * fields; + + r = mailmessage_fetch_header(msg_info, &header, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cur_token = 0; + + r = mailimf_envelope_fields_parse(header, length, &cur_token, + &fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + /* do nothing */ + } + + mailmessage_fetch_result_free(msg_info, header); + + * result = fields; + + return MAIL_NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, header); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/mailmessage_tools.h b/kmicromail/libetpan/generic/mailmessage_tools.h new file mode 100644 index 0000000..a4f9b1e --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage_tools.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMESSAGE_TOOLS_H + +#define MAILMESSAGE_TOOLS_H + +#include "mailmessage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +mailmessage_generic_initialize(mailmessage * + msg_info); + +void mailmessage_generic_uninitialize(mailmessage * + msg_info); + +void mailmessage_generic_flush(mailmessage * msg_info); + +void mailmessage_generic_fetch_result_free(mailmessage * msg_info, + char * msg); + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +int mailmessage_generic_get_bodystructure(mailmessage * + msg_info, + struct mailmime ** result); + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailmessage_types.c b/kmicromail/libetpan/generic/mailmessage_types.c new file mode 100644 index 0000000..9f8c355 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage_types.c @@ -0,0 +1,92 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmessage_types.h" + +#include "mail.h" + +#include +#include + +mailmessage * mailmessage_new(void) +{ + mailmessage * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + goto err; + + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + msg_info->msg_index = 0; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = 0; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, + 0, sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + return msg_info; + + err: + return NULL; +} + +void mailmessage_free(mailmessage * msg_info) +{ + if (msg_info->msg_driver != NULL) { + if (msg_info->msg_driver->msg_uninitialize != NULL) + msg_info->msg_driver->msg_uninitialize(msg_info); + } + + if (msg_info->msg_fields != NULL) + mailimf_fields_free(msg_info->msg_fields); + if (msg_info->msg_mime != NULL) + mailmime_free(msg_info->msg_mime); + if (msg_info->msg_flags != NULL) + mail_flags_free(msg_info->msg_flags); + if (msg_info->msg_uid != NULL) + free(msg_info->msg_uid); + free(msg_info); +} diff --git a/kmicromail/libetpan/generic/mailmessage_types.h b/kmicromail/libetpan/generic/mailmessage_types.h new file mode 100644 index 0000000..655ed2c --- a/dev/null +++ b/kmicromail/libetpan/generic/mailmessage_types.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMESSAGE_TYPES_H + +#define MAILMESSAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailstorage.c b/kmicromail/libetpan/generic/mailstorage.c new file mode 100644 index 0000000..25e561e --- a/dev/null +++ b/kmicromail/libetpan/generic/mailstorage.c @@ -0,0 +1,334 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstorage.h" + +#include "maildriver.h" + +#include +#include + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result); + +struct mailfolder * mailfolder_new(struct mailstorage * storage, + char * pathname, char * virtual_name) +{ + struct mailfolder * folder; + + folder = malloc(sizeof(struct mailfolder)); + if (folder == NULL) + goto err; + + if (pathname != NULL) { + folder->fld_pathname = strdup(pathname); + if (folder->fld_pathname == NULL) + goto free; + } + else + folder->fld_pathname = NULL; + + if (virtual_name != NULL) { + folder->fld_virtual_name = strdup(virtual_name); + if (folder->fld_virtual_name == NULL) + goto free_pathname; + } + else + folder->fld_virtual_name = NULL; + + folder->fld_storage = storage; + + folder->fld_session = NULL; + folder->fld_shared_session = 0; + folder->fld_pos = NULL; + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + folder->fld_children = carray_new(128); + if (folder->fld_children == NULL) + goto free_virtualname; + + return folder; + +free_virtualname: + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); +free_pathname: + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); +free: + free(folder); +err: + return NULL; +} + +void mailfolder_free(struct mailfolder * folder) +{ + if (folder->fld_parent != NULL) + mailfolder_detach_parent(folder); + + while (carray_count(folder->fld_children) > 0) { + struct mailfolder * child; + + child = carray_get(folder->fld_children, 0); + mailfolder_detach_parent(child); + } + + carray_free(folder->fld_children); + + if (folder->fld_session != NULL) + mailfolder_disconnect(folder); + + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); + free(folder); +} + +int mailfolder_connect(struct mailfolder * folder) +{ + mailsession * session; + int res; + int r; + + if (folder->fld_storage == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (folder->fld_storage->sto_session == NULL) { + r = mailstorage_connect(folder->fld_storage); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (folder->fld_session != NULL) { + if ((folder->fld_pathname != NULL) && (folder->fld_shared_session)) { + if (folder->fld_session->sess_driver->sess_select_folder != NULL) { + r = mailsession_select_folder(folder->fld_session, + folder->fld_pathname); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + } + + r = mailstorage_get_folder(folder->fld_storage, folder->fld_pathname, + &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + folder->fld_session = session; + folder->fld_shared_session = (session == folder->fld_storage->sto_session); + if (folder->fld_shared_session) { + r = clist_append(folder->fld_storage->sto_shared_folders, folder); + if (r < 0) { + folder->fld_session = NULL; + res = MAIL_ERROR_MEMORY; + goto err; + } + folder->fld_pos = clist_end(folder->fld_storage->sto_shared_folders); + } + + return MAIL_NO_ERROR; + +err: + return res; +} + +void mailfolder_disconnect(struct mailfolder * folder) +{ + if (folder->fld_session == NULL) + return; + + if (folder->fld_shared_session) { + clist_delete(folder->fld_storage->sto_shared_folders, folder->fld_pos); + folder->fld_pos = NULL; + } + else { + mailsession_logout(folder->fld_session); + mailsession_free(folder->fld_session); + } + + folder->fld_session = NULL; +} + +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child) +{ + unsigned int index; + int r; + + r = carray_add(parent->fld_children, child, &index); + if (r < 0) + return MAIL_ERROR_MEMORY; + + child->fld_sibling_index = index; + child->fld_parent = parent; + + return MAIL_NO_ERROR; +} + +int mailfolder_detach_parent(struct mailfolder * folder) +{ + unsigned int i; + int r; + + if (folder->fld_parent == NULL) + return MAIL_ERROR_INVAL; + + r = carray_delete_slow(folder->fld_parent->fld_children, + folder->fld_sibling_index); + if (r < 0) + return MAIL_ERROR_INVAL; + + for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) { + struct mailfolder * child; + + child = carray_get(folder->fld_parent->fld_children, i); + child->fld_sibling_index = i; + } + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + + return MAIL_NO_ERROR; +} + +struct mailstorage * mailstorage_new(char * sto_id) +{ + struct mailstorage * storage; + + storage = malloc(sizeof(struct mailstorage)); + if (storage == NULL) + goto err; + + if (sto_id != NULL) { + storage->sto_id = strdup(sto_id); + if (storage->sto_id == NULL) + goto free; + } + else + storage->sto_id = NULL; + + storage->sto_data = NULL; + storage->sto_session = NULL; + storage->sto_driver = NULL; + storage->sto_shared_folders = clist_new(); + if (storage->sto_shared_folders == NULL) + goto free_id; + + return storage; + + free_id: + if (storage->sto_id != NULL) + free(storage->sto_id); + free: + free(storage); + err: + return NULL; +} + +void mailstorage_free(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + mailstorage_disconnect(storage); + + if (storage->sto_driver != NULL) { + if (storage->sto_driver->sto_uninitialize != NULL) + storage->sto_driver->sto_uninitialize(storage); + } + + clist_free(storage->sto_shared_folders); + + if (storage->sto_id != NULL) + free(storage->sto_id); + + free(storage); +} + +int mailstorage_connect(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + return MAIL_NO_ERROR; + + if (!clist_isempty(storage->sto_shared_folders)) + return MAIL_ERROR_BAD_STATE; + + if (storage->sto_driver->sto_connect == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_connect(storage); +} + + +void mailstorage_disconnect(struct mailstorage * storage) +{ + int r; + clistiter * cur; + + while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) { + struct mailfolder * folder; + + folder = cur->data; + mailfolder_disconnect(folder); + } + + if (storage->sto_session == NULL) + return; + + r = mailsession_logout(storage->sto_session); + + mailsession_free(storage->sto_session); + storage->sto_session = NULL; +} + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + if (storage->sto_driver->sto_get_folder_session == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_get_folder_session(storage, + pathname, result); +} diff --git a/kmicromail/libetpan/generic/mailstorage.h b/kmicromail/libetpan/generic/mailstorage.h new file mode 100644 index 0000000..d56aef1 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailstorage.h @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_STORAGE_H + +#define MAIL_STORAGE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* storage */ + +/* + mailstorage_new + + This function creates an empty storage. This storage have to be initialized. + The "driver" and "data" fields should be initialized. + + @param id is the name of the storage. It can be NULL. + The given parameter is no more needed when the creation is finished. + The given string is duplicated. + + @return The mail storage is returned. +*/ + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + +/* + session will be initialized on success. +*/ + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + + +/* folder */ + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child); + +int mailfolder_detach_parent(struct mailfolder * folder); + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/kmicromail/libetpan/generic/mailstorage_tools.c b/kmicromail/libetpan/generic/mailstorage_tools.c new file mode 100644 index 0000000..92e2657 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailstorage_tools.c @@ -0,0 +1,372 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstorage_tools.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver.h" + +/* tools */ + +/* connection to TCP/IP server */ + +static int tcp_connect(char * server, uint16_t port) +{ + struct hostent * remotehost; + struct sockaddr_in sa; + int s; + int r; + + s = socket(PF_INET, SOCK_STREAM, 0); + if (s == -1) + goto err; + + remotehost = gethostbyname(server); + if (remotehost == NULL) + goto close_socket; + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length); + + r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); + if (r == -1) + goto close_socket; + + return s; + + close_socket: + close(s); + err: + return -1; +} + + +/* connection through a shell command */ + +static void do_exec_command(int fd, const char *command, + char *servername, uint16_t port) +{ + int i, maxopen; + + if (fork() > 0) { + /* Fork again to become a child of init rather than + the etpan client. */ + exit(0); + } + + if (servername) + setenv("ETPANSERVER", servername, 1); + else + unsetenv("ETPANSERVER"); + + if (port) { + char porttext[20]; + + snprintf(porttext, sizeof(porttext), "%d", port); + setenv("ETPANPORT", porttext, 1); + } + else { + unsetenv("ETPANPORT"); + } + + /* Not a lot we can do if there's an error other than bail. */ + if (dup2(fd, 0) == -1) + exit(1); + if (dup2(fd, 1) == -1) + exit(1); + + /* Should we close stderr and reopen /dev/null? */ + + maxopen = sysconf(_SC_OPEN_MAX); + for (i=3; i < maxopen; i++) + close(i); + +#ifdef TIOCNOTTY + /* Detach from the controlling tty if we have one. Otherwise, + SSH might do something stupid like trying to use it instead + of running $SSH_ASKPASS. Doh. */ + fd = open("/dev/tty", O_RDONLY); + if (fd != -1) { + ioctl(fd, TIOCNOTTY, NULL); + close(fd); + } +#endif /* TIOCNOTTY */ + + execl("/bin/sh", "/bin/sh", "-c", command, NULL); + + /* Eep. Shouldn't reach this */ + exit(1); +} + +static int subcommand_connect(char *command, char *servername, uint16_t port) +{ + int sockfds[2]; + pid_t childpid; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) + return -1; + + childpid = fork(); + if (!childpid) { + do_exec_command(sockfds[1], command, servername, port); + } + else if (childpid == -1) { + close(sockfds[0]); + close(sockfds[1]); + return -1; + } + + close(sockfds[1]); + + /* Reap child, leaving grandchild process to run */ + waitpid(childpid, NULL, 0); + + return sockfds[0]; +} + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result) +{ + int r; + int res; + mailstream * stream; + int fd; + mailsession * session; + int connect_result; + + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_TLS: + fd = tcp_connect(servername, port); + if (fd == -1) { + res = MAIL_ERROR_CONNECT; + goto err; + } + break; + + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + case CONNECTION_TYPE_COMMAND_TLS: + fd = subcommand_connect(command, servername, port); + break; + + default: + fd = -1; + break; + } + + if (fd == -1) { + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + stream = mailstream_socket_open(fd); + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + stream = mailstream_ssl_open(fd); + break; + + default: + stream = NULL; + break; + } + + if (stream == NULL) { + res = MAIL_ERROR_STREAM; + close(fd); + goto err; + } + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_stream; + } + + if (cache_directory != NULL) { + char cache_directory_server[PATH_MAX]; + + snprintf(cache_directory_server, PATH_MAX, "%s/%s", + cache_directory, servername); + + r = mailsession_parameters(session, + cache_function_id, + cache_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + if (flags_directory != NULL) { + char flags_directory_server[PATH_MAX]; + + snprintf(flags_directory_server, PATH_MAX, "%s/%s", + flags_directory, servername); + + r = mailsession_parameters(session, + flags_function_id, + flags_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + r = mailsession_connect_stream(session, stream); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + connect_result = r; + + switch (connection_type) { + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + r = mailsession_starttls(session); + if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) { + res = r; + goto free; + } + break; + + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + r = mailsession_starttls(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + * result = session; + + return connect_result; + + close_stream: + mailstream_close(stream); + free: + mailsession_free(session); + err: + return res; +} + + + + + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password) +{ + int must_auth; + int r; + int res; + + r = connect_result; + + must_auth = FALSE; + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + must_auth = TRUE; + break; + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + if ((login == NULL) || (password == NULL)) + must_auth = FALSE; + + if (must_auth) { + r = mailsession_login(session, login, password); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} diff --git a/kmicromail/libetpan/generic/mailstorage_tools.h b/kmicromail/libetpan/generic/mailstorage_tools.h new file mode 100644 index 0000000..280b214 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailstorage_tools.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstorage.h" + +#ifndef MAILSTORAGE_TOOLS_H + +#define MAILSTORAGE_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailstorage_types.h b/kmicromail/libetpan/generic/mailstorage_types.h new file mode 100644 index 0000000..5e08f80 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailstorage_types.h @@ -0,0 +1,203 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTORAGE_TYPES_H + +#define MAILSTORAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailstorage; + +typedef struct mailstorage_driver mailstorage_driver; + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + mailstorage_driver is the driver structure for mail storages + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - uninitialize() frees the data created with mailstorage constructor. +*/ + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + +/* + mailstorage is the data structure for a storage + + - id is the name of the storage, it can be NULL. + + - data is the data specific to the driver. + This is the internal state of the storage. + + - session is the session related to the storage. + + - driver is the driver for the storage. + + - shared_folders is the list of folders returned by the storage. +*/ + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + +/* + mailfolder is the data structure for a mailbox + + - pathname is the path of the mailbox on the storage + + - virtual_name is the folder identifier, it can be a path, + a name or NULL. + + - storage is the storage to which the folder belongs to. + + - session is the session related to the folder. It can be + different of the session of the storage. + + - shared_session is != 0 if the session is the same as the + session of the storage. + + - pos is the position of the folder in the "shared_folders" field + of the storage. + + folders can be chained into a tree. + + - parent is the parent of the folder. + + - sibling_index is the index of the folder in the list of children + of the parent. + + - children is the folder. +*/ + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + +/* + this is the type of socket connection +*/ + +enum { + CONNECTION_TYPE_PLAIN, /* when the connection is plain text */ + CONNECTION_TYPE_STARTTLS, /* when the connection is first plain, + then, we want to switch to + TLS (secure connection) */ + CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain, + then, we will try to switch to TLS */ + CONNECTION_TYPE_TLS, /* the connection is over TLS */ + CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */ + CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell + command and STARTTLS will be used */ + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over + a shell command and STARTTLS will + be tried */ + CONNECTION_TYPE_COMMAND_TLS, /* the connection is over a shell + command in TLS */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailthread.c b/kmicromail/libetpan/generic/mailthread.c new file mode 100644 index 0000000..1dca70d --- a/dev/null +++ b/kmicromail/libetpan/generic/mailthread.c @@ -0,0 +1,1631 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailthread.h" +#include "mailthread_types.h" + +#include +#include +#include +#include + +#include "mail.h" +#include "chash.h" +#include "carray.h" +#include "clist.h" +#include "mailmessage.h" + +static inline char * get_msg_id(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_message_id != NULL) + return msg->msg_single_fields.fld_message_id->mid_value; + else + return NULL; +} + +static inline clist * get_ref(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_references != NULL) + return msg->msg_single_fields.fld_references->mid_list; + else + return NULL; +} + +static inline clist * get_in_reply_to(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_in_reply_to != NULL) + return msg->msg_single_fields.fld_in_reply_to->mid_list; + else + return NULL; +} + +static inline int skip_subj_blob(char * subj, size_t * begin, + size_t length) +{ + /* subj-blob = "[" *BLOBCHAR "]" *WSP */ + size_t cur_token; + + cur_token = * begin; + + if (subj[cur_token] != '[') + return FALSE; + + cur_token ++; + + while (1) { + if (cur_token >= length) + return FALSE; + + if (subj[cur_token] == '[') + return FALSE; + + if (subj[cur_token] == ']') + break; + + cur_token ++; + } + + cur_token ++; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_refwd(char * subj, size_t * begin, + size_t length) +{ + /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */ + size_t cur_token; + int prefix; + + cur_token = * begin; + + prefix = FALSE; + if (length >= 3) { + if (strncasecmp(subj + cur_token, "fwd", 3) == 0) { + cur_token += 3; + prefix = TRUE; + } + } + if (!prefix) { + if (length >= 2) { + if (strncasecmp(subj + cur_token, "fw", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + else if (strncasecmp(subj + cur_token, "re", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + } + } + + if (!prefix) + return FALSE; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + skip_subj_blob(subj, &cur_token, length); + + if (subj[cur_token] != ':') + return FALSE; + + cur_token ++; + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_leader(struct mailmessage_tree * tree, + char * subj, size_t * begin, + size_t length) +{ + size_t cur_token; + + cur_token = * begin; + + /* subj-leader = (*subj-blob subj-refwd) / WSP */ + + if (subj[cur_token] == ' ') { + cur_token ++; + } + else { + while (cur_token < length) { + if (!skip_subj_blob(subj, &cur_token, length)) + break; + } + if (!skip_subj_refwd(subj, &cur_token, length)) + return FALSE; + tree->node_is_reply = TRUE; + } + + * begin = cur_token; + + return TRUE; +} + + +static char * extract_subject(char * default_from, + struct mailmessage_tree * tree, + char * str) +{ + char * subj; + char * cur; + char * write_pos; + size_t len; + size_t begin; + + char * decoded; + size_t cur_token; + + int do_repeat_5; + int do_repeat_6; + int r; + + /* + (1) Convert any RFC 2047 encoded-words in the subject to + UTF-8. + */ + + decoded = NULL; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(default_from, str, strlen(str), + &cur_token, "utf-8", + &decoded); + + if (r == MAILIMF_NO_ERROR) { + subj = decoded; + } + else + subj = strdup(str); + + len = strlen(subj); + + /* + Convert all tabs and continuations to space. + Convert all multiple spaces to a single space. + */ + + cur = subj; + write_pos = subj; + while (* cur != '\0') { + int cont; + + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + + cur ++; + while (* cur && cont) { + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + break; + default: + cont = FALSE; + break; + } + cur ++; + } + + * write_pos = ' '; + write_pos ++; + + break; + + default: + * write_pos = * cur; + write_pos ++; + + cur ++; + + break; + } + } + * write_pos = '\0'; + + begin = 0; + + do { + do_repeat_6 = FALSE; + + /* + (2) Remove all trailing text of the subject that matches + the subj-trailer ABNF, repeat until no more matches are + possible. + */ + + while (len > 0) { + int chg; + + chg = FALSE; + + /* subj-trailer = "(fwd)" / WSP */ + if (subj[len - 1] == ' ') { + subj[len - 1] = '\0'; + len --; + } + else { + if (len < 5) + break; + + if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0) + break; + + subj[len - 5] = '\0'; + len -= 5; + tree->node_is_reply = TRUE; + } + } + + do { + size_t saved_begin; + + do_repeat_5 = FALSE; + + /* + (3) Remove all prefix text of the subject that matches the + subj-leader ABNF. + */ + + if (skip_subj_leader(tree, subj, &begin, len)) + do_repeat_5 = TRUE; + + /* + (4) If there is prefix text of the subject that matches the + subj-blob ABNF, and removing that prefix leaves a non-empty + subj-base, then remove the prefix text. + */ + + saved_begin = begin; + if (skip_subj_blob(subj, &begin, len)) { + if (begin == len) { + /* this will leave a empty subject base */ + begin = saved_begin; + } + else + do_repeat_5 = TRUE; + } + + /* + (5) Repeat (3) and (4) until no matches remain. + Note: it is possible to defer step (2) until step (6), + but this requires checking for subj-trailer in step (4). + */ + + } + while (do_repeat_5); + + /* + (6) If the resulting text begins with the subj-fwd-hdr ABNF + and ends with the subj-fwd-trl ABNF, remove the + subj-fwd-hdr and subj-fwd-trl and repeat from step (2). + */ + + if (len >= 5) { + size_t saved_begin; + + saved_begin = begin; + if (strncasecmp(subj + begin, "[fwd:", 5) == 0) { + begin += 5; + + if (subj[len - 1] != ']') + saved_begin = begin; + else { + tree->node_is_reply = TRUE; + + subj[len - 1] = '\0'; + len --; + do_repeat_6 = TRUE; + } + } + } + + } + while (do_repeat_6); + + /* + (7) The resulting text is the "base subject" used in + threading. + */ + + /* convert to upper case */ + + cur = subj + begin; + write_pos = subj; + + while (* cur != '\0') { + * write_pos = (char) toupper((unsigned char) * cur); + cur ++; + write_pos ++; + } + * write_pos = '\0'; + + return subj; +} + +static int get_extracted_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + if (tree->node_msg->msg_single_fields.fld_subject != NULL) { + char * subj; + + subj = extract_subject(default_from, + tree, tree->node_msg->msg_single_fields.fld_subject->sbj_value); + if (subj == NULL) + return MAIL_ERROR_MEMORY; + + * result = subj; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + +static int get_thread_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + char * thread_subject; + int r; + unsigned int i; + + if (tree->node_msg != NULL) { + if (tree->node_msg->msg_fields != NULL) { + r = get_extracted_subject(default_from, tree, &thread_subject); + + if (r != MAIL_NO_ERROR) + return r; + + * result = thread_subject; + return MAIL_NO_ERROR; + } + } + + for(i = 0 ; i < carray_count(tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + r = get_thread_subject(default_from, child, &thread_subject); + + switch (r) { + case MAIL_NO_ERROR: + * result = thread_subject; + return MAIL_NO_ERROR; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + /* do nothing */ + break; + + default: + return r; + } + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + + + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + mytm = gmtime(&t); + dir = tmcomp(mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} + +static inline time_t get_date(mailmessage * msg) +{ + struct tm tmval; + time_t timeval; + struct mailimf_date_time * date_time; + + if (msg->msg_single_fields.fld_orig_date == NULL) + return (time_t) -1; + + date_time = msg->msg_single_fields.fld_orig_date->dt_date_time; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_sec = date_time->dt_sec; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + tmval.tm_year = date_time->dt_year - 1900; + + timeval = mkgmtime(&tmval); + + timeval -= date_time->dt_zone * 36; + + return timeval; +} + +static inline int is_descendant(struct mailmessage_tree * node, + struct mailmessage_tree * maybe_child) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(node->node_children) ; i++) { + struct mailmessage_tree * tree; + + tree = carray_get(node->node_children, i); + if (tree == maybe_child) + return TRUE; + if (carray_count(tree->node_children) != 0) + if (is_descendant(tree, maybe_child)) + return TRUE; + } + + return FALSE; +} + +static int delete_dummy(carray * rootlist, carray * sibling_list, + unsigned int cur, unsigned int * pnext) +{ + struct mailmessage_tree * env_tree; + int res; + int r; + unsigned int cur_child; + unsigned int next; + + env_tree = carray_get(sibling_list, cur); + + cur_child = 0; + while (cur_child < carray_count(env_tree->node_children)) { + delete_dummy(rootlist, env_tree->node_children, cur_child, &cur_child); + } + + if (env_tree->node_msg == NULL) { + if (carray_count(env_tree->node_children) == 0) { + + /* If it is a dummy message with NO children, delete it. */ + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else { + /* If it is a dummy message with children, delete it, but + promote its children to the current level. */ + + /* + Do not promote the children if doing so would make them + children of the root, unless there is only one child. + */ + + cur_child = 0; + if ((sibling_list != rootlist) || + (carray_count(env_tree->node_children) == 1)) { + while (cur_child < carray_count(env_tree->node_children)) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, cur_child); + r = carray_add(sibling_list, child, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + /* set new parent of the children */ + child->node_parent = env_tree->node_parent; + + carray_delete(env_tree->node_children, cur_child); + } + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else + next = cur + 1; + } + } + else + next = cur + 1; + + * pnext = next; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static inline time_t tree_get_date(struct mailmessage_tree * tree) +{ + if (tree->node_msg != NULL) { + return tree->node_date; + } + else { + struct mailmessage_tree * subtree; + + if (carray_count(tree->node_children) == 0) + return (time_t) -1; + + subtree = carray_get(tree->node_children, 0); + + return subtree->node_date; + } +} + +static inline uint32_t tree_get_index(struct mailmessage_tree * tree) +{ + if (tree->node_msg == NULL) + return 0; + + return tree->node_msg->msg_index; +} + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + time_t date1; + time_t date2; + + date1 = tree_get_date(* ptree1); + date2 = tree_get_date(* ptree2); + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) { + uint32_t index1; + uint32_t index2; + + index1 = tree_get_index(* ptree1); + index2 = tree_get_index(* ptree2); + return (int) ((long) index1 - (long) index2); + } + + return (int) ((long) date1 - (long) date2); +} + +static int tree_subj_time_comp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + char * subj1; + char * subj2; + time_t date1; + time_t date2; + int r; + + subj1 = (* ptree1)->node_base_subject; + subj2 = (* ptree2)->node_base_subject; + + if ((subj1 != NULL) && (subj2 != NULL)) + r = strcmp(subj1, subj2); + else { + if ((subj1 == NULL) && (subj2 == NULL)) + r = 0; + else if (subj1 == NULL) + r = -1; + else /* subj2 == NULL */ + r = 1; + } + + if (r != 0) + return r; + + date1 = (* ptree1)->node_date; + date2 = (* ptree2)->node_date; + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) + return ((int32_t) (* ptree1)->node_msg->msg_index) - + ((int32_t) (* ptree2)->node_msg->msg_index); + + return (int) ((long) date1 - (long) date2); +} + + + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub) +{ + unsigned int cur; + int r; + int res; + + for(cur = 0 ; cur < carray_count(tree->node_children) ; cur ++) { + struct mailmessage_tree * subtree; + + subtree = carray_get(tree->node_children, cur); + + if (sort_sub) { + r = mail_thread_sort(subtree, comp_func, sort_sub); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + qsort(carray_data(tree->node_children), carray_count(tree->node_children), + sizeof(struct mailmessage_tree *), + (int (*)(const void *, const void *)) comp_func); + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int +mail_build_thread_references(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int use_subject, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + int r; + int res; + chash * msg_id_hash; + unsigned int cur; + struct mailmessage_tree * root; + carray * rootlist; + carray * msg_list; + unsigned int i; + chash * subject_hash; + + msg_id_hash = chash_new(128, CHASH_COPYNONE); + if (msg_id_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_hash; + } + rootlist = root->node_children; + + msg_list = carray_new(128); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_root; + } + + /* collect message-ID */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + char * msgid; + struct mailmessage_tree * env_tree; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + msgid = get_msg_id(msg); + + if (msgid == NULL) { + msgid = mailimf_get_message_id(); + } + else { + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + if (chash_get(msg_id_hash, &hashkey, &hashdata) == 0) + msgid = mailimf_get_message_id(); + else + msgid = strdup(msgid); + } + + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + date = get_date(msg); + + env_tree = mailmessage_tree_new(msgid, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + hashdata.data = env_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + /* (1) for all messages */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + mailmessage * msg; + clist * ref; + + env_tree = carray_get(msg_list, cur); + + msg = env_tree->node_msg; + + ref = NULL; + if (msg != NULL) { + ref = get_ref(msg); + if (ref == NULL) + ref = get_in_reply_to(msg); + } + + /* (A) Using the Message IDs in the message's references, link + the corresponding messages (those whose Message-ID header + line contains the given reference Message ID) together as + parent/child. + */ + + if (ref != NULL) { + /* try to start a tree */ + + clistiter * cur_ref; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + struct mailmessage_tree * env_cur_tree; + struct mailmessage_tree * last_env_cur_tree; + + env_cur_tree = NULL; + for(cur_ref = clist_begin(ref) ; cur_ref != NULL ; + cur_ref = clist_next(cur_ref)) { + char * msgid; + + last_env_cur_tree = env_cur_tree; + + msgid = clist_content(cur_ref); + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + r = chash_get(msg_id_hash, &hashkey, &hashdata); + if (r < 0) { + /* not found, create a dummy message */ + msgid = strdup(msgid); + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + env_cur_tree = mailmessage_tree_new(msgid, (time_t) -1, NULL); + if (env_cur_tree == NULL) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_cur_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_cur_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + hashdata.data = env_cur_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + env_cur_tree = hashdata.data; + } + + if (last_env_cur_tree != NULL) { + if (env_cur_tree->node_parent == NULL) { + /* make it one child */ + if (env_cur_tree != last_env_cur_tree) { + if (!is_descendant(env_cur_tree, last_env_cur_tree)) { + /* set parent */ + env_cur_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, + env_cur_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + + /* (B) Create a parent/child link between the last reference + (or NIL if there are no references) and the current message. + If the current message already has a parent, it is probably + the result of a truncated References header line, so break + the current parent/child link before creating the new + correct one. + */ + + last_env_cur_tree = env_cur_tree; + + if (last_env_cur_tree != NULL) { + if (env_tree->node_parent == NULL) { + if (last_env_cur_tree != env_tree) { + if (!is_descendant(env_tree, last_env_cur_tree)) { + /* set parent */ + env_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + } + + chash_free(msg_id_hash); + msg_id_hash = NULL; + + /* (2) Gather together all of the messages that have no parents + and make them all children (siblings of one another) of a dummy + parent (the "root"). + */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(msg_list, cur); + if (env_tree->node_parent == NULL) { + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + /* set parent */ + env_tree->node_parent = root; + } + } + + carray_free(msg_list); + msg_list = NULL; + + /* (3) Prune dummy messages from the thread tree. + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + r = delete_dummy(rootlist, rootlist, cur, &cur); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + /* (4) Sort the messages under the root (top-level siblings only) + by sent date. + */ + + r = mail_thread_sort(root, mailthread_tree_timecomp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (use_subject) { + + /* (5) Gather together messages under the root that have the same + extracted subject text. + + (A) Create a table for associating extracted subjects with + messages. + */ + + subject_hash = chash_new(128, CHASH_COPYVALUE); + if (subject_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + /* + (B) Populate the subject table with one message per + extracted subject. For each child of the root: + */ + + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + char * base_subject; + int r; + + env_tree = carray_get(rootlist, cur); + + /* + (i) Find the subject of this thread by extracting the + base subject from the current message, or its first child + if the current message is a dummy. + */ + + r = get_thread_subject(default_from, env_tree, &base_subject); + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (r == MAIL_ERROR_SUBJECT_NOT_FOUND) { + /* no subject found */ + continue; + } + else if (r == MAIL_NO_ERROR) { + if (* base_subject == '\0') { + /* subject empty */ + free(base_subject); + continue; + } + else { + /* do nothing */ + } + } + else { + res = r; + goto free_subject_hash; + } + + env_tree->node_base_subject = base_subject; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = base_subject; + key.len = strlen(base_subject); + + r = chash_get(subject_hash, &key, &data); + + if (r < 0) { + /* + (iv) If there is no message in the table with this + subject, add the current message and the extracted + subject to the subject table. + */ + + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + else { + /* + Otherwise, replace the message in the table with the + current message if the message in the table is not a + dummy AND either of the following criteria are true: + The current message is a dummy, OR + The message in the table is a reply or forward (its + original subject contains a subj-refwd part and/or a + "(fwd)" subj-trailer) and the current message is not. + */ + struct mailmessage_tree * msg_in_table; + unsigned int * iter_in_table; + int replace; + + iter_in_table = data.data; + msg_in_table = carray_get(rootlist, cur); + + replace = FALSE; + /* message is dummy if info is NULL */ + if (msg_in_table->node_msg != NULL) { + + if (env_tree->node_msg == NULL) + replace = TRUE; + else { + if (env_tree->node_is_reply && !env_tree->node_is_reply) + replace = TRUE; + } + } + + if (replace) { + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + } + } + + /* + (C) Merge threads with the same subject. For each child of + the root: + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + int r; + struct mailmessage_tree * main_tree; + unsigned int * main_cur; + + env_tree = carray_get(rootlist, cur); + + if (env_tree == NULL) + goto next_msg; + + /* + (i) Find the subject of this thread as in step 4.B.i + above. + */ + + /* already done in tree->node_base_subject */ + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (env_tree->node_base_subject == NULL) + goto next_msg; + + if (* env_tree->node_base_subject == '\0') + goto next_msg; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = env_tree->node_base_subject; + key.len = strlen(env_tree->node_base_subject); + + r = chash_get(subject_hash, &key, &data); + if (r < 0) + goto next_msg; + + /* + (iv) If the message in the table is the current message, + skip this message. + */ + + main_cur = data.data; + if (* main_cur == cur) + goto next_msg; + + /* + Otherwise, merge the current message with the one in the + table using the following rules: + */ + + main_tree = carray_get(rootlist, * main_cur); + + /* + If both messages are dummies, append the current + message's children to the children of the message in + the table (the children of both messages become + siblings), and then delete the current message. + */ + + if ((env_tree->node_msg == NULL) && (main_tree->node_msg == NULL)) { + unsigned int old_size; + + old_size = carray_count(main_tree->node_children); + + r = carray_set_size(main_tree->node_children, old_size + + carray_count(env_tree->node_children)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + for(i = 0 ; i < carray_count(env_tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, i); + carray_set(main_tree->node_children, old_size + i, child); + /* set parent */ + child->node_parent = main_tree; + } + carray_set_size(env_tree->node_children, 0); + /* this is the only case where children can be NULL, + this is before freeing it */ + mailmessage_tree_free(env_tree); + carray_delete_fast(rootlist, cur); + } + + /* + If the message in the table is a dummy and the current + message is not, make the current message a child of + the message in the table (a sibling of it's children). + */ + + else if (main_tree->node_msg == NULL) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + If the current message is a reply or forward and the + message in the table is not, make the current message + a child of the message in the table (a sibling of it's + children). + */ + + else if (env_tree->node_is_reply && !main_tree->node_is_reply) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + Otherwise, create a new dummy message and make both + the current message and the message in the table + children of the dummy. Then replace the message in + the table with the dummy message. + Note: Subject comparisons are case-insensitive, as + described under "Internationalization + Considerations." + */ + + else { + struct mailmessage_tree * new_main_tree; + char * base_subject; + unsigned int last; + + new_main_tree = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (new_main_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + /* main_tree->node_base_subject is never NULL */ + + base_subject = strdup(main_tree->node_base_subject); + if (base_subject == NULL) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + new_main_tree->node_base_subject = base_subject; + + r = carray_add(rootlist, new_main_tree, &last); + if (r < 0) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + r = carray_add(new_main_tree->node_children, main_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + main_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, * main_cur); + + r = carray_add(new_main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, cur); + + data.data = &last; + data.len = sizeof(last); + + r = chash_set(subject_hash, &key, &data, NULL); + + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + + continue; + + next_msg: + cur ++; + continue; + } + + i = 0; + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(rootlist, cur); + if (env_tree == NULL) + continue; + + carray_set(rootlist, i, env_tree); + i ++; + } + carray_set_size(rootlist, i); + + chash_free(subject_hash); + } + + /* + (6) Traverse the messages under the root and sort each set of + siblings by sent date. Traverse the messages in such a way + that the "youngest" set of siblings are sorted first, and the + "oldest" set of siblings are sorted last (grandchildren are + sorted before children, etc). + + In the case of an exact match on + sent date or if either of the Date: headers used in a + comparison can not be parsed, use the order in which the + messages appear in the mailbox (that is, by sequence number) to + determine the order. In the case of a dummy message (which can + only occur with top-level siblings), use its first child for + sorting. + */ + + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, TRUE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + * result = root; + + return MAIL_NO_ERROR; + + free_subject_hash: + chash_free(subject_hash); + free_list: + if (msg_list != NULL) { + for(i = 0 ; i < carray_count(msg_list) ; i ++) + mailmessage_tree_free(carray_get(msg_list, i)); + carray_free(msg_list); + } + free_root: + mailmessage_tree_free_recursive(root); + free_hash: + if (msg_id_hash != NULL) + chash_free(msg_id_hash); + err: + return res; +} + + + +static int +mail_build_thread_orderedsubject(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + carray * rootlist; + unsigned int cur; + struct mailmessage_tree * root; + int res; + int r; + struct mailmessage_tree * current_thread; + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + rootlist = root->node_children; + + /* + The ORDEREDSUBJECT threading algorithm is also referred to as + "poor man's threading." + */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailmessage_tree * env_tree; + char * base_subject; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + + date = get_date(msg); + + env_tree = mailmessage_tree_new(NULL, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + /* set parent */ + env_tree->node_parent = root; + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = get_extracted_subject(default_from, env_tree, &base_subject); + switch (r) { + case MAIL_NO_ERROR: + env_tree->node_base_subject = base_subject; + break; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + break; + + default: + res = r; + goto free; + } + } + } + + /* + The searched messages are sorted by + subject and then by the sent date. + */ + + r = mail_thread_sort(root, tree_subj_time_comp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + /* + The messages are then split + into separate threads, with each thread containing messages + with the same extracted subject text. + */ + + current_thread = NULL; + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * cur_env_tree; + + cur_env_tree = carray_get(rootlist, cur); + if (current_thread == NULL) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if ((cur_env_tree->node_base_subject == NULL) || + (current_thread->node_base_subject == NULL)) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if (strcmp(cur_env_tree->node_base_subject, + current_thread->node_base_subject) == 0) { + + /* set parent */ + cur_env_tree->node_parent = current_thread; + r = carray_add(current_thread->node_children, cur_env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + carray_delete(rootlist, cur); + } + else + cur ++; + current_thread = cur_env_tree; + } + + /* + Finally, the threads are + sorted by the sent date of the first message in the thread. + Note that each message in a thread is a child (as opposed to a + sibling) of the previous message. + */ + + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + * result = root; + + return MAIL_NO_ERROR; + + free: + mailmessage_tree_free_recursive(root); + err: + return res; +} + + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) + mailmessage_resolve_single_fields(carray_get(env_list->msg_tab, i)); + + switch (type) { + case MAIL_THREAD_REFERENCES: + return mail_build_thread_references(default_from, + env_list, result, TRUE, comp_func); + + case MAIL_THREAD_REFERENCES_NO_SUBJECT: + return mail_build_thread_references(default_from, + env_list, result, FALSE, comp_func); + + case MAIL_THREAD_ORDEREDSUBJECT: + return mail_build_thread_orderedsubject(default_from, + env_list, result, comp_func); + + default: + return MAIL_ERROR_NOT_IMPLEMENTED; + } +} diff --git a/kmicromail/libetpan/generic/mailthread.h b/kmicromail/libetpan/generic/mailthread.h new file mode 100644 index 0000000..e4e33ff --- a/dev/null +++ b/kmicromail/libetpan/generic/mailthread.h @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILTHREAD_H + +#define MAILTHREAD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_build_thread constructs a tree with the message using the + given style. + + @param type is the type of threading to apply, the value can be + MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT or + MAIL_THREAD_ORDEREDSUBJECT. + + @param default_from is the default charset to use whenever the + subject is not tagged with a charset. "US-ASCII" can be used + if you don't know what to use. + + @param env_list is the message list (with header fields fetched) + to use to build the message tree. + + @param result * result) will contain the resulting message tree. + + @param if comp_func is NULL, no sorting algorithm is used. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)); + +/* + mail_thread_sort sort the messages in the message tree, using the + given sort function. + + @param tree is the message tree to sort. + + @param comp_func is the sort function to use (this is the same kind of + functions than those used for qsort()). mailthread_tree_timecomp can be + used for default sort. + + @param sort_sub if this value is 0, only the children of the root message + are sorted. +*/ + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub); + +/* + mailthread_tree_timecomp is the default sort function. + + The message are compared by date, then by message numbers. + The tree are given in (* ptree1) and (* ptree2). +*/ + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mailthread_types.c b/kmicromail/libetpan/generic/mailthread_types.c new file mode 100644 index 0000000..f1c5d37 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailthread_types.c @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailthread_types.h" + +#include "mail.h" +#include + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg) +{ + struct mailmessage_tree * tree; + carray * array; + + array = carray_new(16); + if (array == NULL) + return NULL; + + tree = malloc(sizeof(* tree)); + tree->node_parent = NULL; + tree->node_date = node_date; + tree->node_msgid = node_msgid; + tree->node_msg = node_msg; + tree->node_children = array; + tree->node_base_subject = NULL; + tree->node_is_reply = FALSE; + + return tree; +} + +void mailmessage_tree_free(struct mailmessage_tree * tree) +{ + if (tree->node_base_subject != NULL) + free(tree->node_base_subject); + + if (tree->node_children != NULL) + carray_free(tree->node_children); + if (tree->node_msgid != NULL) + free(tree->node_msgid); + + free(tree); +} + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(tree->node_children) ; i++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + mailmessage_tree_free_recursive(child); + } + + mailmessage_tree_free(tree); +} diff --git a/kmicromail/libetpan/generic/mailthread_types.h b/kmicromail/libetpan/generic/mailthread_types.h new file mode 100644 index 0000000..5ef7b46 --- a/dev/null +++ b/kmicromail/libetpan/generic/mailthread_types.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILTHREAD_TYPES_H + +#define MAILTHREAD_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + This is the type of tree construction to apply. +*/ + +enum { + MAIL_THREAD_REFERENCES, /* this is threading using + References fields only) */ + MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References + fields, then subject */ + MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver.c b/kmicromail/libetpan/generic/mboxdriver.c new file mode 100644 index 0000000..fa3e2ea --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver.c @@ -0,0 +1,505 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "mboxdriver_tools.h" +#include "maildriver.h" +#include "carray.h" +#include "mboxdriver_message.h" +#include "mailmessage.h" + +static int mboxdriver_initialize(mailsession * session); + +static void mboxdriver_uninitialize(mailsession * session); + +static int mboxdriver_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_connect_path(mailsession * session, char * path); + +static int mboxdriver_logout(mailsession * session); + +static int mboxdriver_expunge_folder(mailsession * session); + +static int mboxdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mboxdriver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int mboxdriver_append_message(mailsession * session, + char * message, size_t size); + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_remove_message(mailsession * session, uint32_t num); + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_session_driver = { + .sess_name = "mbox", + + .sess_initialize = mboxdriver_initialize, + .sess_uninitialize = mboxdriver_uninitialize, + + .sess_parameters = mboxdriver_parameters, + + .sess_connect_path = mboxdriver_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_expunge_folder, + .sess_status_folder = mboxdriver_status_folder, + .sess_messages_number = mboxdriver_messages_number, + .sess_recent_number = mboxdriver_messages_number, + .sess_unseen_number = mboxdriver_messages_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_get_messages_list, + .sess_get_envelopes_list = mboxdriver_get_envelopes_list, + .sess_remove_message = mboxdriver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_get_message, + .sess_get_message_by_uid = mboxdriver_get_message_by_uid, +}; + +mailsession_driver * mbox_session_driver = &local_mbox_session_driver; + +static inline struct mbox_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailsession * session) +{ + return get_data(session)->mbox_folder; +} + +static int mboxdriver_initialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mbox_folder = NULL; + + data->mbox_force_read_only = FALSE; + data->mbox_force_no_uid = TRUE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_session_state_data * mbox_data) +{ + if (mbox_data->mbox_folder != NULL) { + mailmbox_done(mbox_data->mbox_folder); + mbox_data->mbox_folder = NULL; + } +} + +static void mboxdriver_uninitialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + free_state(data); + + free(data); +} + +static int mboxdriver_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + switch (id) { + case MBOXDRIVER_SET_READ_ONLY: + { + int * param; + + param = value; + + data->mbox_force_read_only = * param; + return MAIL_NO_ERROR; + } + + case MBOXDRIVER_SET_NO_UID: + { + int * param; + + param = value; + + data->mbox_force_no_uid = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int mboxdriver_connect_path(mailsession * session, char * path) +{ + struct mbox_session_state_data * mbox_data; + struct mailmbox_folder * folder; + int r; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder != NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_init(path, + mbox_data->mbox_force_read_only, + mbox_data->mbox_force_no_uid, + 0, + &folder); + + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + mbox_data->mbox_folder = folder; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_logout(mailsession * session) +{ + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + free_state(mbox_data); + + mbox_data->mbox_folder = NULL; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_expunge_folder(mailsession * session) +{ + int r; + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_expunge(mbox_data->mbox_folder); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mboxdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + struct mailmbox_folder * folder; + int r; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_STATUS; + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) + return r; + + mailmbox_read_unlock(folder); + + * result = carray_count(folder->mb_tab) - folder->mb_deleted_count; + + return MAILMBOX_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message(folder, message, size); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } +} + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_messages_list(folder, session, mbox_message_driver, result); + + err: + return res; +} + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailmbox_folder * folder; + unsigned int i; + int r; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + char * headers; + size_t headers_len; + size_t cur_token; + + msg = carray_get(env_list->msg_tab, i); + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) + continue; + + r = mailmbox_fetch_msg_headers_no_lock(folder, + msg->msg_index, &headers, &headers_len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + cur_token = 0; + r = mailimf_envelope_fields_parse(headers, headers_len, + &cur_token, &fields); + + if (r != MAILIMF_NO_ERROR) + continue; + + msg->msg_fields = fields; + } + + mailmbox_read_unlock(folder); + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +static int mboxdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmbox_delete_msg(folder, num); + + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/kmicromail/libetpan/generic/mboxdriver.h b/kmicromail/libetpan/generic/mboxdriver.h new file mode 100644 index 0000000..c598026 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver_cached.c b/kmicromail/libetpan/generic/mboxdriver_cached.c new file mode 100644 index 0000000..07871fa --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_cached.c @@ -0,0 +1,1253 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_cached.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mail_cache_db.h" +#include "mboxdriver.h" +#include "mboxdriver_tools.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "maildriver.h" +#include "carray.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mboxdriver_cached_message.h" +#include "libetpan-config.h" + +static int mboxdriver_cached_initialize(mailsession * session); + +static void mboxdriver_cached_uninitialize(mailsession * session); + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_cached_connect_path(mailsession * session, char * path); + +static int mboxdriver_cached_logout(mailsession * session); + +static int mboxdriver_cached_check_folder(mailsession * session); + +static int mboxdriver_cached_expunge_folder(mailsession * session); + +static int mboxdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); +static int mboxdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result); +static int mboxdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); +static int mboxdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int mboxdriver_cached_append_message(mailsession * session, + char * message, size_t size); + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_cached_session_driver = { + .sess_name = "mbox-cached", + + .sess_initialize = mboxdriver_cached_initialize, + .sess_uninitialize = mboxdriver_cached_uninitialize, + + .sess_parameters = mboxdriver_cached_parameters, + + .sess_connect_path = mboxdriver_cached_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_cached_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = mboxdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_cached_expunge_folder, + .sess_status_folder = mboxdriver_cached_status_folder, + .sess_messages_number = mboxdriver_cached_messages_number, + .sess_recent_number = mboxdriver_cached_recent_number, + .sess_unseen_number = mboxdriver_cached_unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_cached_append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_cached_get_messages_list, + .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list, + .sess_remove_message = mboxdriver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_cached_get_message, + .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid, +}; + +mailsession_driver * mbox_cached_session_driver = +&local_mbox_cached_session_driver; + + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static int mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + +static inline struct mbox_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailsession * session) +{ + return get_ancestor_data(session)->mbox_folder; +} + +static int mboxdriver_cached_initialize(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * mbox_data; + + cached_data = malloc(sizeof(* cached_data)); + if (cached_data == NULL) + goto err; + + cached_data->mbox_flags_store = mail_flags_store_new(); + if (cached_data->mbox_flags_store == NULL) + goto free; + + cached_data->mbox_ancestor = mailsession_new(mbox_session_driver); + if (cached_data->mbox_ancestor == NULL) + goto free_store; + + cached_data->mbox_quoted_mb = NULL; + /* + UID must be enabled to take advantage of the cache + */ + mbox_data = cached_data->mbox_ancestor->sess_data; + mbox_data->mbox_force_no_uid = FALSE; + + session->sess_data = cached_data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(cached_data->mbox_flags_store); + free: + free(cached_data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_cached_session_state_data * mbox_data) +{ + if (mbox_data->mbox_quoted_mb) { + free(mbox_data->mbox_quoted_mb); + mbox_data->mbox_quoted_mb = NULL; + } +} + +static int mbox_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mboxdriver_cached_uninitialize(mailsession * session) +{ + struct mbox_cached_session_state_data * data; + + data = get_cached_data(session); + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + mail_flags_store_free(data->mbox_flags_store); + + free_state(data); + mailsession_free(data->mbox_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->mbox_cache_directory, value, PATH_MAX); + data->mbox_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->mbox_flags_directory, value, PATH_MAX); + data->mbox_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_SET_NO_UID: + return MAIL_ERROR_INVAL; + + default: + return mailsession_parameters(data->mbox_ancestor, id, value); + } +} + + +static int get_cache_directory(mailsession * session, + char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + +#if 0 + struct mbox_session_state_data * mbox_data; +#endif + struct mbox_cached_session_state_data * cached_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + struct mailmbox_folder * folder; + + /* expunge the mailbox */ + +#if 0 + mbox_data = get_ancestor(session)->data; +#endif + folder = get_mbox_session(session); + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto unlock; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + folder->mb_written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + fwrite(mmapstr->str, 1, mmapstr->len, f); + + mmap_string_free(mmapstr); + fclose(f); + mailmbox_write_unlock(folder); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +static int read_max_uid_value(mailsession * session, uint32_t * result) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + + struct mbox_cached_session_state_data * cached_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + fclose(f); + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + * result = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int mboxdriver_cached_connect_path(mailsession * session, char * path) +{ + int r; + int res; + char * quoted_mb; + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * ancestor_data; + struct mailmbox_folder * folder; + uint32_t written_uid; + + folder = get_mbox_session(session); + if (folder != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = get_cache_directory(session, path, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cached_data = get_cached_data(session); + free_state(cached_data); + + cached_data->mbox_quoted_mb = quoted_mb; + + written_uid = 0; + r = read_max_uid_value(session, &written_uid); + /* ignore errors */ + + ancestor_data = get_ancestor_data(session); + + r = mailmbox_init(path, + ancestor_data->mbox_force_read_only, + ancestor_data->mbox_force_no_uid, + written_uid, + &folder); + + if (r != MAILMBOX_NO_ERROR) { + cached_data->mbox_quoted_mb = NULL; + + res = mboxdriver_mbox_error_to_mail_error(r); + goto free; + } + + ancestor_data->mbox_folder = folder; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + +static int mboxdriver_cached_logout(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + int r; + + r = write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_state(cached_data); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_check_folder(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmbox_delete_msg(folder, msg_info->msg_uid); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mailmbox_expunge(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + uint32_t recent; + uint32_t unseen; + uint32_t num; + + num = 0; + recent = 0; + unseen = 0; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmbox_read_unlock(folder); + + mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + num ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + + num ++; + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = num; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + + +static int mboxdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_uid_messages_list(folder, + session, mbox_cached_message_driver, result); + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-envelope", num, info->msg_body_len); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-envelope", num, info->msg_body_len); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct mbox_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, + &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->msg_index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int +mboxdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_cached_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/kmicromail/libetpan/generic/mboxdriver_cached.h b/kmicromail/libetpan/generic/mboxdriver_cached.h new file mode 100644 index 0000000..b0d8dbf --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_cached.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver_cached_message.c b/kmicromail/libetpan/generic/mboxdriver_cached_message.c new file mode 100644 index 0000000..6d92b22 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_cached_message.c @@ -0,0 +1,360 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_cached_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "mailmbox.h" +#include "mail_cache_db.h" +#include "generic_cache.h" + +#include +#include +#include +#include +#include +#include +#include + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static void mbox_uninitialize(mailmessage * msg_info); + +static void mbox_flush(mailmessage * msg_info); + +static void mbox_check(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_cached_message_driver = { + .msg_name = "mbox-cached", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mbox_uninitialize, + + .msg_flush = mbox_flush, + .msg_check = mbox_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = mbox_get_flags, +}; + +mailmessage_driver * mbox_cached_message_driver = +&local_mbox_cached_message_driver; + +static inline struct mbox_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mbox_folder; +} + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = (char *) &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = (struct mailmbox_msg_info *) data.data; + + snprintf(static_uid, PATH_MAX, "%u-%u", msg_info->msg_index, info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void mbox_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void mbox_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mbox_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info); + /* ignore errors */ + } +} + + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mbox_cached_session_state_data * cached_data; + MMAPString * mmapstr; + struct mailmbox_folder * folder; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_session_data(msg_info); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + if (msg_info->msg_index > folder->mb_written_uid) { + flags = mail_flags_new_empty(); + } + else { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/kmicromail/libetpan/generic/mboxdriver_cached_message.h b/kmicromail/libetpan/generic/mboxdriver_cached_message.h new file mode 100644 index 0000000..a6673b3 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver_message.c b/kmicromail/libetpan/generic/mboxdriver_message.c new file mode 100644 index 0000000..da9a65d --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_message.c @@ -0,0 +1,225 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver.h" +#include "mailmbox.h" + +#include +#include +#include +#include +#include +#include +#include + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_message_driver = { + .msg_name = "mbox", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * mbox_message_driver = &local_mbox_message_driver; + +static inline struct mbox_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg) +{ + return get_data(msg)->mbox_folder; +} + + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%u", + msg_info->msg_index, info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(msg_info->msg_session, + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/kmicromail/libetpan/generic/mboxdriver_message.h b/kmicromail/libetpan/generic/mboxdriver_message.h new file mode 100644 index 0000000..cdabd23 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver_tools.c b/kmicromail/libetpan/generic/mboxdriver_tools.c new file mode 100644 index 0000000..1e27798 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_tools.c @@ -0,0 +1,434 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxdriver_tools.h" + +#include +#include +#include +#include + +#include "maildriver_types.h" +#include "mailmbox.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +static inline struct mbox_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * +session_get_mbox_session(mailsession * session) +{ + return session_get_data(session)->mbox_folder; +} + +static inline struct mbox_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return cached_session_get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +cached_session_get_mbox_session(mailsession * session) +{ + return session_get_mbox_session(cached_session_get_ancestor(session)); +} + + +int mboxdriver_mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result) +{ + struct mailmbox_folder * folder; + int r; + char * data; + size_t len; + int res; + + folder = session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + mailmbox_read_unlock(folder); + + * result = len; + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = cached_session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-flags", num, info->msg_body_len); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int mbox_get_locked_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + int (* lock)(struct mailmbox_folder *), + int (* unlock)(struct mailmbox_folder *), + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + unsigned int i; + int r; + int res; + carray * tab; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = lock(folder); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + mailmessage * msg; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + r = mailmessage_init(msg, session, driver, msg_info->msg_uid, + msg_info->msg_size - msg_info->msg_start_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlock; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto unlock; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + unlock(folder); + + * result = env_list; + + return MAIL_NO_ERROR; + + unlock: + unlock(folder); + free: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} + +static int release_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_read_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_validate_read_lock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int release_write_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_write_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_write_mbox(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + if (folder->mb_written_uid < folder->mb_max_uid) { + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + } + + return MAIL_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +/* get message list with all valid written UID */ + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_write_mbox, release_write_mbox, result); +} + + +/* get message list */ + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_read_mbox, release_read_mbox, result); +} diff --git a/kmicromail/libetpan/generic/mboxdriver_tools.h b/kmicromail/libetpan/generic/mboxdriver_tools.h new file mode 100644 index 0000000..3ec82ec --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_tools.h @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_TOOLS_H + +#define MBOXDRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "mboxdriver_types.h" +#include "mailmbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mboxdriver_mbox_error_to_mail_error(int error); + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result); + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxdriver_types.h b/kmicromail/libetpan/generic/mboxdriver_types.h new file mode 100644 index 0000000..be31ea3 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxdriver_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID, +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mboxstorage.c b/kmicromail/libetpan/generic/mboxstorage.c new file mode 100644 index 0000000..0a7dc93 --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxstorage.c @@ -0,0 +1,192 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mboxstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "mboxdriver.h" +#include "mboxdriver_cached.h" +#include "maildriver.h" + +#include +#include + +/* mbox storage */ + +static int mbox_mailstorage_connect(struct mailstorage * storage); +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mbox_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mbox_mailstorage_driver = { + .sto_name = "mbox", + .sto_connect = mbox_mailstorage_connect, + .sto_get_folder_session = mbox_mailstorage_get_folder_session, + .sto_uninitialize = mbox_mailstorage_uninitialize, +}; + +int mbox_mailstorage_init(struct mailstorage * storage, + char * mbox_pathname, int mbox_cached, + char * mbox_cache_directory, char * mbox_flags_directory) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = malloc(sizeof(struct mbox_mailstorage)); + if (mbox_storage == NULL) + goto err; + + mbox_storage->mbox_pathname = strdup(mbox_pathname); + if (mbox_storage->mbox_pathname == NULL) + goto free; + + mbox_storage->mbox_cached = mbox_cached; + + if (mbox_cached && (mbox_cache_directory != NULL) && + (mbox_flags_directory != NULL)) { + mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory); + if (mbox_storage->mbox_cache_directory == NULL) + goto free_pathname; + + mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory); + if (mbox_storage->mbox_flags_directory == NULL) + goto free_cache_directory; + } + else { + mbox_storage->mbox_cached = FALSE; + mbox_storage->mbox_cache_directory = NULL; + mbox_storage->mbox_flags_directory = NULL; + } + + storage->sto_data = mbox_storage; + storage->sto_driver = &mbox_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mbox_storage->mbox_cache_directory); + free_pathname: + free(mbox_storage->mbox_pathname); + free: + free(mbox_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mbox_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = storage->sto_data; + if (mbox_storage->mbox_flags_directory != NULL) + free(mbox_storage->mbox_flags_directory); + if (mbox_storage->mbox_cache_directory != NULL) + free(mbox_storage->mbox_cache_directory); + free(mbox_storage->mbox_pathname); + free(mbox_storage); + + storage->sto_data = NULL; +} + +static int mbox_mailstorage_connect(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mbox_storage = storage->sto_data; + + if (mbox_storage->mbox_cached) + driver = mbox_cached_session_driver; + else + driver = mbox_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mbox_storage->mbox_cached) { + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + mbox_storage->mbox_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mbox_storage->mbox_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mbox_storage->mbox_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/kmicromail/libetpan/generic/mboxstorage.h b/kmicromail/libetpan/generic/mboxstorage.h new file mode 100644 index 0000000..e5e83ce --- a/dev/null +++ b/kmicromail/libetpan/generic/mboxstorage.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int mbox_mailstorage_init(struct mailstorage * storage, + char * mb_pathname, int mb_cached, + char * mb_cache_directory, char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver.c b/kmicromail/libetpan/generic/mhdriver.c new file mode 100644 index 0000000..af38d27 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver.c @@ -0,0 +1,866 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_message.h" +#include "mailmessage.h" + +static int mhdriver_initialize(mailsession * session); + +static void mhdriver_uninitialize(mailsession * session); + +static int mhdriver_connect_path(mailsession * session, char * path); +static int mhdriver_logout(mailsession * session); + +static int mhdriver_build_folder_name(mailsession * session, char * mb, + char * name, char ** result); +static int mhdriver_create_folder(mailsession * session, char * mb); + +static int mhdriver_delete_folder(mailsession * session, char * mb); + +static int mhdriver_rename_folder(mailsession * session, char * mb, + char * new_name); + +static int mhdriver_select_folder(mailsession * session, char * mb); + +static int mhdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int mhdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int mhdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int mhdriver_subscribe_folder(mailsession * session, char * mb); + +static int mhdriver_unsubscribe_folder(mailsession * session, char * mb); + +static int mhdriver_append_message(mailsession * session, + char * message, size_t size); +static int mhdriver_copy_message(mailsession * session, + uint32_t num, char * mb); + +static int mhdriver_remove_message(mailsession * session, uint32_t num); + +static int mhdriver_move_message(mailsession * session, + uint32_t num, char * mb); + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_session_driver = { + .sess_name = "mh", + + .sess_initialize = mhdriver_initialize, + .sess_uninitialize = mhdriver_uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = NULL, + .sess_connect_path = mhdriver_connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mhdriver_logout, + .sess_noop = NULL, + + .sess_build_folder_name = mhdriver_build_folder_name, + .sess_create_folder = mhdriver_create_folder, + .sess_delete_folder = mhdriver_delete_folder, + .sess_rename_folder = mhdriver_rename_folder, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = mhdriver_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = mhdriver_status_folder, + .sess_messages_number = mhdriver_messages_number, + .sess_recent_number = mhdriver_messages_number, + .sess_unseen_number = mhdriver_messages_number, + .sess_list_folders = mhdriver_list_folders, + .sess_lsub_folders = mhdriver_lsub_folders, + .sess_subscribe_folder = mhdriver_subscribe_folder, + .sess_unsubscribe_folder = mhdriver_unsubscribe_folder, + + .sess_append_message = mhdriver_append_message, + .sess_copy_message = mhdriver_copy_message, + .sess_move_message = mhdriver_move_message, + + .sess_get_messages_list = mhdriver_get_messages_list, + .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, + .sess_remove_message = mhdriver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mhdriver_get_message, + .sess_get_message_by_uid = mhdriver_get_message_by_uid, +}; + +mailsession_driver * mh_session_driver = &local_mh_session_driver; + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh * get_mh_session(mailsession * session) +{ + return get_data(session)->mh_session; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static int add_to_list(mailsession * session, char * mb) +{ + char * new_mb; + struct mh_session_state_data * data; + int r; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->mh_subscribed_list, new_mb); + if (r < 0) { + free(mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, char * mb) +{ + clistiter * cur; + struct mh_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->mh_subscribed_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->mh_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + +static int mhdriver_initialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_session = NULL; + data->mh_cur_folder = NULL; + + data->mh_subscribed_list = clist_new(); + if (data->mh_subscribed_list == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void mhdriver_uninitialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = get_data(session); + + if (data->mh_session != NULL) + mailmh_free(data->mh_session); + + clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL); + clist_free(data->mh_subscribed_list); + + free(data); + + session->sess_data = NULL; +} + + +static int mhdriver_connect_path(mailsession * session, char * path) +{ + struct mailmh * mh; + + if (get_mh_session(session) != NULL) + return MAIL_ERROR_BAD_STATE; + + mh = mailmh_new(path); + if (mh == NULL) + return MAIL_ERROR_MEMORY; + + get_data(session)->mh_session = mh; + + return MAIL_NO_ERROR; +} + +static int mhdriver_logout(mailsession * session) +{ + struct mailmh * mh; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + mailmh_free(mh); + get_data(session)->mh_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_build_folder_name(mailsession * session, char * mb, + char * name, char ** result) +{ + char * folder_name; + + folder_name = malloc(strlen(mb) + 2 + strlen(name)); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, "/"); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +static int get_parent(mailsession * session, char * mb, + struct mailmh_folder ** result_folder, + char ** result_name) +{ + char * name; + size_t length; + int i; + char * parent_name; + struct mailmh_folder * parent; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + length = strlen(mb); + for(i = length - 1 ; i >= 0 ; i--) + if (mb[i] == '/') + break; + name = mb + i + 1; + + parent_name = malloc(i + 1); + /* strndup(mb, i) */ + if (parent_name == NULL) + return MAIL_ERROR_MEMORY; + + strncpy(parent_name, mb, i); + parent_name[i] = '\0'; + + parent = mailmh_folder_find(mh->mh_main, parent_name); + free(parent_name); + if (parent == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result_folder = parent; + * result_name = name; + + return MAIL_NO_ERROR; +} + +static int mhdriver_create_folder(mailsession * session, char * mb) +{ + int r; + struct mailmh_folder * parent; + char * name; + + r = get_parent(session, mb, &parent, &name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailmh_folder_add_subfolder(parent, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_delete_folder(mailsession * session, char * mb) +{ + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_remove_subfolder(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_rename_folder(mailsession * session, char * mb, + char * new_name) +{ + struct mailmh_folder * src_folder; + struct mailmh_folder * dst_folder; + char * name; + struct mailmh * mh; + int r; + + r = get_parent(session, new_name, &dst_folder, &name); + if (r != MAIL_NO_ERROR) + return r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = mailmh_folder_find(mh->mh_main, mb); + if (src_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == src_folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_select_folder(mailsession * session, char * mb) +{ + struct mailmh_folder * folder; + struct mailmh * mh; + int r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_update(mh->mh_main); + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + get_data(session)->mh_cur_folder = folder; + r = mailmh_folder_update(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mhdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mhdriver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + struct mailmh_folder * folder; + uint32_t count; + struct mailmh * mh; + unsigned int i; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + if (mb != NULL) { + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + } + else { + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + } + + mailmh_folder_update(folder); + count = 0; + for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + count ++; + } + + * result = count; + + return MAIL_NO_ERROR; +} + + +static int get_list_folders(struct mailmh_folder * folder, clist ** result) +{ + unsigned int i; + clist * list; + char * new_filename; + int res; + int r; + + list = * result; + + new_filename = strdup(folder->fl_filename); + if (new_filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmh_folder_update(folder); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto free; + } + + r = clist_append(list, new_filename); + if (r < 0) { + free(new_filename); + res = MAIL_ERROR_MEMORY; + goto free; + } + + if (folder->fl_subfolders_tab != NULL) { + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + + r = get_list_folders(subfolder, &list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return res; +} + + +static int mhdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + clist * list; + int r; + struct mailmh * mh; + struct mail_list * ml; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + list = clist_new(); + if (list == NULL) + return MAIL_ERROR_MEMORY; + + r = get_list_folders(mh->mh_main, &list); + if (r != MAIL_NO_ERROR) + return r; + + ml = mail_list_new(list); + if (ml == NULL) + goto free; + + * result = ml; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int r; + + length = strlen(mb); + + subscribed = get_data(session)->mh_subscribed_list; + + lsub_result = clist_new(); + if (lsub_result == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) + goto free_list; + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) + goto free_list; + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_subscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int mhdriver_unsubscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mhdriver_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message(folder, message, size); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + default: + return mhdriver_mh_error_to_mail_error(r); + } +} + +static int mhdriver_copy_message(mailsession * session, + uint32_t num, char * mb) +{ + int fd; + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + int res; + + mh = get_mh_session(session); + if (mh == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) { + res = MAIL_ERROR_FOLDER_NOT_FOUND; + goto close; + } + + r = mailmh_folder_add_message_file(folder, fd); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_COPY; + goto close; + } + + close(fd); + + return MAIL_NO_ERROR; + + close: + close(fd); + err: + return res; +} + +static int mhdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmh_folder_remove_message(folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_move_message(mailsession * session, + uint32_t num, char * mb) +{ + int r; + struct mailmh_folder * src_folder; + struct mailmh_folder * dest_folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = get_mh_cur_folder(session); + if (src_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + dest_folder = mailmh_folder_find(mh->mh_main, mb); + if (dest_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + r = mailmh_folder_move_message(dest_folder, src_folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmh_folder_update(folder); + return mh_get_messages_list(folder, session, mh_message_driver, result); + + err: + return res; +} + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t index; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mh_session_state_data * mh_data; + chashdatum key; + chashdatum data; + int r; + time_t mtime; + char * mtime_p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + index = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + mh_data = session->sess_data; +#if 0 + mh_msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, index); +#endif + key.data = &index; + key.len = sizeof(index); + r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_get_message(session, index, result); + } + else if (* p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/kmicromail/libetpan/generic/mhdriver.h b/kmicromail/libetpan/generic/mhdriver.h new file mode 100644 index 0000000..a82b9c1 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_H + +#define MHDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver_cached.c b/kmicromail/libetpan/generic/mhdriver_cached.c new file mode 100644 index 0000000..5c35089 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_cached.c @@ -0,0 +1,1232 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver_cached.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mail_cache_db.h" + +#include "generic_cache.h" +#include "imfcache.h" +#include "mhdriver.h" + +#include "mhdriver_cached_message.h" +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mailmessage.h" + +static int mhdriver_cached_initialize(mailsession * session); + +static void mhdriver_cached_uninitialize(mailsession * session); + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mhdriver_cached_connect_path(mailsession * session, char * path); +static int mhdriver_cached_logout(mailsession * session); + +static int mhdriver_cached_build_folder_name(mailsession * session, char * mb, + char * name, char ** result); +static int mhdriver_cached_create_folder(mailsession * session, char * mb); + +static int mhdriver_cached_delete_folder(mailsession * session, char * mb); + +static int mhdriver_cached_rename_folder(mailsession * session, char * mb, + char * new_name); + +static int mhdriver_cached_check_folder(mailsession * session); + +static int mhdriver_cached_select_folder(mailsession * session, char * mb); + +static int mhdriver_cached_expunge_folder(mailsession * session); + +static int mhdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result); +static int mhdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); +static int mhdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int mhdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int mhdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb); + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + char * mb); + +static int mhdriver_cached_append_message(mailsession * session, + char * message, size_t size); +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, char * mb); + +static int mhdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, char * mb); + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_cached_session_driver = { + .sess_name = "mh-cached", + + .sess_initialize = mhdriver_cached_initialize, + .sess_uninitialize = mhdriver_cached_uninitialize, + + .sess_parameters = mhdriver_cached_parameters, + + .sess_connect_stream = NULL, + .sess_connect_path = mhdriver_cached_connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mhdriver_cached_logout, + .sess_noop = NULL, + + .sess_build_folder_name = mhdriver_cached_build_folder_name, + .sess_create_folder = mhdriver_cached_create_folder, + .sess_delete_folder = mhdriver_cached_delete_folder, + .sess_rename_folder = mhdriver_cached_rename_folder, + .sess_check_folder = mhdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = mhdriver_cached_select_folder, + .sess_expunge_folder = mhdriver_cached_expunge_folder, + .sess_status_folder = mhdriver_cached_status_folder, + .sess_messages_number = mhdriver_cached_messages_number, + .sess_recent_number = mhdriver_cached_recent_number, + .sess_unseen_number = mhdriver_cached_unseen_number, + .sess_list_folders = mhdriver_cached_list_folders, + .sess_lsub_folders = mhdriver_cached_lsub_folders, + .sess_subscribe_folder = mhdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder, + + .sess_append_message = mhdriver_cached_append_message, + .sess_copy_message = mhdriver_cached_copy_message, + .sess_move_message = mhdriver_cached_move_message, + + .sess_get_messages_list = mhdriver_cached_get_messages_list, + .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list, + .sess_remove_message = mhdriver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mhdriver_cached_get_message, + .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid, +}; + +mailsession_driver * mh_cached_session_driver = +&local_mh_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct mh_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailsession * session) +{ + return get_ancestor_data(session)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailsession * session) +{ + return get_ancestor_data(session)->mh_cur_folder; +} + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (cached_data->mh_quoted_mb == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + ancestor_data->mh_cur_folder->fl_max_index); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + fwrite(mmapstr->str, 1, mmapstr->len, f); + + mmap_string_free(mmapstr); + fclose(f); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int read_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + fclose(f); + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + if (written_uid > ancestor_data->mh_cur_folder->fl_max_index) + ancestor_data->mh_cur_folder->fl_max_index = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + + +static int mhdriver_cached_initialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_flags_store = mail_flags_store_new(); + if (data->mh_flags_store == NULL) + goto free; + + data->mh_ancestor = mailsession_new(mh_session_driver); + if (data->mh_ancestor == NULL) + goto free_store; + + data->mh_quoted_mb = NULL; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->mh_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mh_cached_session_state_data * mh_data) +{ + if (mh_data->mh_quoted_mb) { + free(mh_data->mh_quoted_mb); + mh_data->mh_quoted_mb = NULL; + } +} + +static int mh_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mhdriver_cached_uninitialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = get_cached_data(session); + + mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb, + data->mh_flags_store); + + mail_flags_store_free(data->mh_flags_store); + + free_state(data); + mailsession_free(data->mh_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mh_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case MHDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->mh_cache_directory, value, PATH_MAX); + cached_data->mh_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->mh_flags_directory, value, PATH_MAX); + cached_data->mh_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + +static int mhdriver_cached_connect_path(mailsession * session, char * path) +{ + return mailsession_connect_path(get_ancestor(session), path); +} + +static int mhdriver_cached_logout(mailsession * session) +{ + int r; + struct mh_cached_session_state_data * cached_data; + + r = write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int mhdriver_cached_check_folder(mailsession * session) +{ + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_cached_build_folder_name(mailsession * session, char * mb, + char * name, char ** result) +{ + return mailsession_build_folder_name(get_ancestor(session), + mb, name, result); +} + +static int mhdriver_cached_create_folder(mailsession * session, char * mb) +{ + return mailsession_create_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_delete_folder(mailsession * session, char * mb) +{ + return mailsession_delete_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_rename_folder(mailsession * session, char * mb, + char * new_name) +{ + return mailsession_rename_folder(get_ancestor(session), mb, new_name); +} + +static int get_cache_directory(mailsession * session, + char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_cache_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_flags_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_select_folder(mailsession * session, char * mb) +{ + int r; + int res; + char * quoted_mb; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + r = get_cache_directory(session, mb, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = write_max_uid_value(session); + + free_state(cached_data); + cached_data->mh_quoted_mb = quoted_mb; + + r = read_max_uid_value(session); + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmh_folder_remove_message(folder, mh_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mailmh_folder_update(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + + +static int mhdriver_cached_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + uint32_t count; + uint32_t recent; + uint32_t unseen; + + r = mhdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + count = 0; + recent = 0; + unseen = 0; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + count ++; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, + &flags); + + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mhdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + +/* messages operations */ + +static int mhdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, char * mb) +{ + return mailsession_copy_message(get_ancestor(session), num, mb); +} + +static int mhdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, char * mb) +{ + return mailsession_move_message(get_ancestor(session), num, mb); +} + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mh_get_messages_list(folder, session, + mh_cached_message_driver, result); + + err: + return res; +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + + folder = get_mh_cur_folder(session); + +#if 0 + msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) + return MAIL_ERROR_CACHE_MISS; +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope", + num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmh_folder * folder; + chashdatum key; + chashdatum data; + struct mailmh_msg_info * msg_info; + + folder = get_mh_cur_folder(session); +#if 0 + msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-%u-envelope", + num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + msg->msg_session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t index; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mailmh_folder * folder; + time_t mtime; + char * mtime_p; + chashdatum key; + chashdatum data; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + index = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mh_cur_folder(session); + + mh_msg_info = NULL; + key.data = &index; + key.len = sizeof(index); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_cached_get_message(session, index, result); + } + else if (*p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/kmicromail/libetpan/generic/mhdriver_cached.h b/kmicromail/libetpan/generic/mhdriver_cached.h new file mode 100644 index 0000000..4a07e7d --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_CACHED_H + +#define MHDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver_cached_message.c b/kmicromail/libetpan/generic/mhdriver_cached_message.c new file mode 100644 index 0000000..f716fb9 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_cached_message.c @@ -0,0 +1,338 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_cached.h" +#include "mailmh.h" +#include "generic_cache.h" + +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include +#include +#include + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void mh_uninitialize(mailmessage * msg_info); + +static void mh_flush(mailmessage * msg_info); + +static void mh_check(mailmessage * msg_info); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_cached_message_driver = { + .msg_name = "mh-cached", + + .msg_initialize = mh_initialize, + .msg_uninitialize = mh_uninitialize, + + .msg_flush = mh_flush, + .msg_check = mh_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mh_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mh_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = mh_get_flags, +}; + +mailmessage_driver * mh_cached_message_driver = +&local_mh_cached_message_driver; + +static inline struct mh_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_cur_folder; +} + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(msg_info); + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu-%u", msg_info->msg_index, + mh_msg_info->msg_mtime, mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void mh_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + + +#define FLAGS_NAME "flags.db" + +static void mh_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mh_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mh_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->mh_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mhdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/kmicromail/libetpan/generic/mhdriver_cached_message.h b/kmicromail/libetpan/generic/mhdriver_cached_message.h new file mode 100644 index 0000000..f3ed089 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_CACHED_MESSAGE_H + +#define MHDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver_message.c b/kmicromail/libetpan/generic/mhdriver_message.c new file mode 100644 index 0000000..2c023e7 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_message.c @@ -0,0 +1,212 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver.h" +#include "mailmh.h" + +#include +#include +#include +#include +#include +#include +#include + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_message_driver = { + .msg_name = "mh", + + .msg_initialize = mh_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mh_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mh_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * mh_message_driver = &local_mh_message_driver; + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static inline struct mh_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg) +{ + return get_data(msg)->mh_cur_folder; +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum value; + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = value.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu-%u", msg_info->msg_index, + mh_msg_info->msg_mtime, mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + + + + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + + r = mailmessage_generic_fetch_header(msg_info, result, result_len); + return r; + } + else { + r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/kmicromail/libetpan/generic/mhdriver_message.h b/kmicromail/libetpan/generic/mhdriver_message.h new file mode 100644 index 0000000..a7cb2cf --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_MESSAGE_H + +#define MHDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver_tools.c b/kmicromail/libetpan/generic/mhdriver_tools.c new file mode 100644 index 0000000..cb863fa --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_tools.c @@ -0,0 +1,475 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhdriver_tools.h" + +#include "mailmessage.h" +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "maildriver_types.h" +#include "mailmh.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include +#include +#include + +int mhdriver_mh_error_to_mail_error(int error) +{ + switch (error) { + case MAILMH_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMH_ERROR_FOLDER: + return MAIL_NO_ERROR; + + case MAILMH_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMH_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMH_ERROR_COULD_NOT_ALLOC_MSG: + return MAIL_ERROR_APPEND; + + case MAILMH_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILMH_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static inline struct mh_cached_session_state_data * +cached_get_data(mailsession * session) +{ + return session->sess_data; +} + + +static inline mailsession * cached_get_ancestor(mailsession * session) +{ + return cached_get_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +cached_get_ancestor_data(mailsession * session) +{ + return get_data(cached_get_ancestor(session)); +} + +static inline struct mailmh_folder * +cached_get_mh_cur_folder(mailsession * session) +{ + return get_mh_cur_folder(cached_get_ancestor(session)); +} + +int mhdriver_fetch_message(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, index, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + /* XXX - called twice, make a function */ + cur_token = 0; + if (strncmp("From ", str, size) == 0) { + cur_token += 5; + + while (str[cur_token] != '\n') { + if (cur_token >= size) + break; + cur_token ++; + } + } + + mmapstr = mmap_string_new_len(str + cur_token, size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + size_t begin; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, index, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + cur_token = 0; + if (size > 5) { + if (strncmp("From ", str, size) == 0) { + cur_token += 5; + + while (str[cur_token] != '\n') { + if (cur_token >= size) + break; + cur_token ++; + } + } + } + + begin = cur_token; + + while (1) { + r = mailimf_ignore_field_parse(str, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(str, size, &cur_token); + + mmapstr = mmap_string_new_len(str + begin, cur_token - begin); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result) +{ + struct mailmh_folder * folder; + int r; + struct stat buf; + char * name; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_FETCH; + + r = mailmh_folder_get_message_filename(folder, index, &name); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + r = stat(name, &buf); + free(name); + if (r == -1) + return MAIL_ERROR_FETCH; + + * result = buf.st_size; + + return MAIL_NO_ERROR; +} + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = cached_get_mh_cur_folder(session); +#if 0 + msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) + return MAIL_ERROR_CACHE_MISS; +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%u-%u-flags", + num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + mailmessage * msg; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + mh_info->msg_index, mh_info->msg_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/mhdriver_tools.h b/kmicromail/libetpan/generic/mhdriver_tools.h new file mode 100644 index 0000000..0d805c1 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_tools.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_TOOLS_H + +#define MHDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" +#include "mailmh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mhdriver_mh_error_to_mail_error(int error); + +int mhdriver_fetch_message(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mhdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mhdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result); + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhdriver_types.h b/kmicromail/libetpan/generic/mhdriver_types.h new file mode 100644 index 0000000..09c6cc6 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhdriver_types.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_TYPES_H + +#define MHDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mh_session_state_data { + struct mailmh * mh_session; + + struct mailmh_folder * mh_cur_folder; + + clist * mh_subscribed_list; +}; + +enum { + MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct mh_cached_session_state_data { + mailsession * mh_ancestor; + char * mh_quoted_mb; + char mh_cache_directory[PATH_MAX]; + char mh_flags_directory[PATH_MAX]; + struct mail_flags_store * mh_flags_store; +}; + +/* mh storage */ + +/* + mh_mailstorage is the state data specific to the MH storage. + + - pathname is the root path of the MH storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mh_mailstorage { + char * mh_pathname; + + int mh_cached; + char * mh_cache_directory; + char * mh_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mhstorage.c b/kmicromail/libetpan/generic/mhstorage.c new file mode 100644 index 0000000..32fc26b --- a/dev/null +++ b/kmicromail/libetpan/generic/mhstorage.c @@ -0,0 +1,192 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mhstorage.h" + +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "mail.h" + +#include +#include + +/* mh storage */ + +static int mh_mailstorage_connect(struct mailstorage * storage); +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mh_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mh_mailstorage_driver = { + .sto_name = "mh", + .sto_connect = mh_mailstorage_connect, + .sto_get_folder_session = mh_mailstorage_get_folder_session, + .sto_uninitialize = mh_mailstorage_uninitialize, +}; + +int mh_mailstorage_init(struct mailstorage * storage, + char * mh_pathname, int mh_cached, + char * mh_cache_directory, char * mh_flags_directory) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = malloc(sizeof(struct mh_mailstorage)); + if (mh_storage == NULL) + goto err; + + mh_storage->mh_pathname = strdup(mh_pathname); + if (mh_storage->mh_pathname == NULL) + goto free; + + mh_storage->mh_cached = mh_cached; + + if (mh_cached && (mh_cache_directory != NULL) && + (mh_flags_directory != NULL)) { + mh_storage->mh_cache_directory = strdup(mh_cache_directory); + if (mh_storage->mh_cache_directory == NULL) + goto free_pathname; + mh_storage->mh_flags_directory = strdup(mh_flags_directory); + if (mh_storage->mh_flags_directory == NULL) + goto free_cache_directory; + } + else { + mh_storage->mh_cached = FALSE; + mh_storage->mh_cache_directory = NULL; + mh_storage->mh_flags_directory = NULL; + } + + storage->sto_data = mh_storage; + storage->sto_driver = &mh_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mh_storage->mh_cache_directory); + free_pathname: + free(mh_storage->mh_pathname); + free: + free(mh_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mh_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = storage->sto_data; + if (mh_storage->mh_flags_directory != NULL) + free(mh_storage->mh_flags_directory); + if (mh_storage->mh_cache_directory != NULL) + free(mh_storage->mh_cache_directory); + free(mh_storage->mh_pathname); + free(mh_storage); + + storage->sto_data = NULL; +} + +static int mh_mailstorage_connect(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mh_storage = storage->sto_data; + + if (mh_storage->mh_cached) + driver = mh_cached_session_driver; + else + driver = mh_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mh_storage->mh_cached) { + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_CACHE_DIRECTORY, + mh_storage->mh_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mh_storage->mh_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mh_storage->mh_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + int r; + + r = mailsession_select_folder(storage->sto_session, pathname); + if (r != MAIL_NO_ERROR) + return r; + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/mhstorage.h b/kmicromail/libetpan/generic/mhstorage.h new file mode 100644 index 0000000..245bc81 --- a/dev/null +++ b/kmicromail/libetpan/generic/mhstorage.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHSTORAGE_H + +#define MHSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mh_mailstorage_init is the constructor for a MH storage + + @param pathname is the filename the root path of the MH storage. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache. + + @param flags_directory is the location of the flags. +*/ + +int mh_mailstorage_init(struct mailstorage * storage, + char * mh_pathname, int mh_cached, + char * mh_cache_directory, char * mh_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/mime_message_driver.c b/kmicromail/libetpan/generic/mime_message_driver.c new file mode 100644 index 0000000..273875e --- a/dev/null +++ b/kmicromail/libetpan/generic/mime_message_driver.c @@ -0,0 +1,689 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mime_message_driver.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "maildriver_tools.h" + +static FILE * get_mime_tmp_file(mailmessage * msg, + char * filename, size_t size) +{ + int fd; + mode_t old_mask; + FILE * f; + + if (msg->msg_data == NULL) + return NULL; + + snprintf(filename, size, "%s/libetpan-mime-XXXXXX", + (char *) msg->msg_data); + + old_mask = umask(0077); + fd = mkstemp(filename); + umask(old_mask); + if (fd == -1) + return NULL; + + f = fdopen(fd, "r+"); + if (f == NULL) { + close(fd); + unlink(filename); + } + + return f; +} + +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir) +{ + if (msg->msg_data != NULL) + free(msg->msg_data); + + msg->msg_data = strdup(tmpdir); + if (msg->msg_data == NULL) + return MAIL_ERROR_MEMORY; + + return MAIL_NO_ERROR; +} + +void mime_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} + +mailmessage * mime_message_init(struct mailmime * mime) +{ + mailmessage * msg; + int r; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0); + if (r != MAIL_NO_ERROR) + goto free; + + if (mime != NULL) { + mailmime_free(msg->msg_mime); + msg->msg_mime = mime; + } + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +static int initialize(mailmessage * msg) +{ + struct mailmime * mime; + int res; + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + msg->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void uninitialize(mailmessage * msg) +{ + /* tmp dir name */ + if (msg->msg_data != NULL) + free(msg->msg_data); + + if (msg->msg_mime != NULL) + mailmime_free(msg->msg_mime); + msg->msg_mime = NULL; +} + +static void flush(mailmessage * msg) +{ + /* do nothing */ +} + +static void check(mailmessage * msg) +{ + /* do nothing */ +} + +static void fetch_result_free(mailmessage * msg_info, char * content) +{ + mmap_string_unref(content); +} + +static int file_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + mmapstr = mmap_string_new_len(data, buf.st_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} + + +static int file_body_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} + +static int file_body_body_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + cur_token = 0; + + /* skip header */ + + /* MIME header */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + /* headers */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} + + + +static int fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + FILE * f; + int res; + int col; + char filename[PATH_MAX]; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto close; + } + + if (mime->mm_parent == NULL) + r = file_to_mmapstr(f, result, result_len); + else + r = file_body_to_mmapstr(f, result, result_len); + + if (r != MAIL_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + unlink(filename); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +static int fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + FILE * f; + int res; + int col; + char filename[PATH_MAX]; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + if (mime->mm_type == MAILMIME_MESSAGE) { + if (mime->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto close; + } + mailimf_string_write(f, &col, "\r\n", 2); + } + } + + r = file_to_mmapstr(f, result, result_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + unlink(filename); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +static int fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + FILE * f; + int res; + int col; + char filename[PATH_MAX]; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + if (mime->mm_content_type != NULL) { + r = mailmime_content_write(f, &col, mime->mm_content_type); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto close; + } + } + if (mime->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, &col, mime->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto close; + } + } + mailimf_string_write(f, &col, "\r\n", 2); + + r = file_to_mmapstr(f, result, result_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + unlink(filename); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + + +static int fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + FILE * f; + int res; + int col; + char filename[PATH_MAX]; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + if (mime->mm_mime_fields != NULL) { + r = mailmime_write(f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto close; + } + } + + if (mime->mm_type == MAILMIME_MESSAGE) + r = file_body_body_to_mmapstr(f, result, result_len); + else + r = file_body_to_mmapstr(f, result, result_len); + + if (r != MAIL_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + unlink(filename); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +static int get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + +static int fetch(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section(msg_info, msg_info->msg_mime, result, result_len); +} + +static int fetch_header(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_header(msg_info, + msg_info->msg_mime, result, result_len); +} + +static int fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len); +} + + +static int fetch_size(mailmessage * msg_info, + size_t * result) +{ + char * msg; + int r; + + r = fetch(msg_info, &msg, result); + if (r != MAIL_NO_ERROR) { + return r; + } + + fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_mime_message_driver = { + .msg_name = "mime", + + .msg_initialize = initialize, + .msg_uninitialize = uninitialize, + + .msg_flush = flush, + .msg_check = check, + + .msg_fetch_result_free = fetch_result_free, + + .msg_fetch = fetch, + .msg_fetch_header = fetch_header, + .msg_fetch_body = fetch_body, + .msg_fetch_size = fetch_size, + .msg_get_bodystructure = get_bodystructure, + .msg_fetch_section = fetch_section, + .msg_fetch_section_header = fetch_section_header, + .msg_fetch_section_mime = fetch_section_mime, + .msg_fetch_section_body = fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * mime_message_driver = &local_mime_message_driver; diff --git a/kmicromail/libetpan/generic/mime_message_driver.h b/kmicromail/libetpan/generic/mime_message_driver.h new file mode 100644 index 0000000..ffcdd5c --- a/dev/null +++ b/kmicromail/libetpan/generic/mime_message_driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MIME_MESSAGE_DRIVER_H + +#define MIME_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_MIME_MESSAGE + +extern mailmessage_driver * mime_message_driver; + +mailmessage * mime_message_init(struct mailmime * mime); + +void mime_message_detach_mime(mailmessage * msg); + +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir); + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver.c b/kmicromail/libetpan/generic/nntpdriver.c new file mode 100644 index 0000000..fde5f1a --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver.c @@ -0,0 +1,1170 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver.h" + +#include +#include + +#include "mail.h" +#include "mailmessage.h" +#include "nntpdriver_tools.h" +#include "maildriver_tools.h" +#include "nntpdriver_message.h" + +static int nntpdriver_initialize(mailsession * session); + +static void nntpdriver_uninitialize(mailsession * session); + +static int nntpdriver_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s); + +static int nntpdriver_login(mailsession * session, + char * userid, char * password); + +static int nntpdriver_logout(mailsession * session); + +static int nntpdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_append_message(mailsession * session, + char * message, size_t size); + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_subscribe_folder(mailsession * session, char * mb); + +static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb); + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int nntpdriver_noop(mailsession * session); + +static mailsession_driver local_nntp_session_driver = { + .sess_name = "nntp", + + .sess_initialize = nntpdriver_initialize, + .sess_uninitialize = nntpdriver_uninitialize, + + .sess_parameters = nntpdriver_parameters, + + .sess_connect_stream = nntpdriver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = NULL, + .sess_login = nntpdriver_login, + .sess_logout = nntpdriver_logout, + .sess_noop = nntpdriver_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = nntpdriver_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = nntpdriver_status_folder, + .sess_messages_number = nntpdriver_messages_number, + .sess_recent_number = nntpdriver_messages_number, + .sess_unseen_number = nntpdriver_messages_number, + .sess_list_folders = nntpdriver_list_folders, + .sess_lsub_folders = nntpdriver_lsub_folders, + .sess_subscribe_folder = nntpdriver_subscribe_folder, + .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder, + + .sess_append_message = nntpdriver_append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = nntpdriver_get_messages_list, + .sess_get_envelopes_list = nntpdriver_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = nntpdriver_get_message, + .sess_get_message_by_uid = nntpdriver_get_message_by_uid, +}; + + +mailsession_driver * nntp_session_driver = &local_nntp_session_driver; + +static inline struct nntp_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_data(session)->nntp_session; +} + +static int nntpdriver_initialize(mailsession * session) +{ + struct nntp_session_state_data * data; + newsnntp * nntp; + + nntp = newsnntp_new(0, NULL); + if (nntp == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->nntp_session = nntp; + + data->nntp_userid = NULL; + data->nntp_password = NULL; + + data->nntp_group_info = NULL; + data->nntp_group_name = NULL; + + data->nntp_subscribed_list = clist_new(); + if (data->nntp_subscribed_list == NULL) + goto free_data; + + data->nntp_max_articles = 0; + + data->nntp_mode_reader = FALSE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_data: + free(data); + free: + newsnntp_free(nntp); + err: + return MAIL_ERROR_MEMORY; +} + +static void nntpdriver_uninitialize(mailsession * session) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL); + clist_free(data->nntp_subscribed_list); + + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + + if (data->nntp_userid != NULL) + free(data->nntp_userid); + + if (data->nntp_password != NULL) + free(data->nntp_password); + + newsnntp_free(data->nntp_session); + free(data); + + session->sess_data = NULL; +} + + +static int nntpdriver_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + switch (id) { + case NNTPDRIVER_SET_MAX_ARTICLES: + { + uint32_t * param; + + param = value; + + data->nntp_max_articles = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int add_to_list(mailsession * session, char * mb) +{ + char * new_mb; + int r; + struct nntp_session_state_data * data; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->nntp_subscribed_list, new_mb); + if (r < 0) { + free(mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, char * mb) +{ + clistiter * cur; + struct nntp_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->nntp_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = newsnntp_connect(get_nntp_session(session), s); + + switch (r) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +static int nntpdriver_login(mailsession * session, + char * userid, char * password) +{ + struct nntp_session_state_data * data; + char * new_userid; + char * new_password; + + data = get_data(session); + + if (userid != NULL) { + new_userid = strdup(userid); + if (new_userid == NULL) + goto err; + } + else + new_userid = NULL; + + if (password != NULL) { + new_password = strdup(password); + if (new_password == NULL) + goto free_uid; + } + else + new_password = NULL; + + data->nntp_userid = new_userid; + data->nntp_password = new_password; + + return MAIL_NO_ERROR; + + free_uid: + if (new_userid != NULL) + free(new_userid); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntpdriver_logout(mailsession * session) +{ + int r; + + r = newsnntp_quit(get_nntp_session(session)); + + return nntpdriver_nntp_error_to_mail_error(r); +} + + +static int nntpdriver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = nntpdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + int r; + struct nntp_session_state_data * data; + + if (mb != NULL) { + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result = data->nntp_group_info->grp_last - + data->nntp_group_info->grp_first + 1; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + int r; + clist * group_list; + newsnntp * nntp; + clistiter * cur; + char * new_mb; + int done; + clist * list; + struct mail_list * ml; + int res; + + nntp = get_nntp_session(session); + + new_mb = NULL; + if ((mb != NULL) && (*mb != '\0')) { + new_mb = malloc(strlen(mb) + 3); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + strcpy(new_mb, mb); + strcat(new_mb, ".*"); + } + + done = FALSE; + do { + if (new_mb != NULL) + r = newsnntp_list_active(nntp, new_mb, &group_list); + else + r = newsnntp_list(nntp, &group_list); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case NEWSNNTP_NO_ERROR: + if (new_mb != NULL) + free(new_mb); + done = TRUE; + break; + + default: + if (new_mb != NULL) + free(new_mb); + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(group_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct newsnntp_group_info * info; + char * new_name; + + info = clist_content(cur); + new_name = strdup(info->grp_name); + if (new_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_name); + if (r < 0) { + free(new_name); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + ml = mail_list_new(list); + if (ml == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + newsnntp_list_free(group_list); + + * result = ml; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + newsnntp_list_free(group_list); + err: + return res; +} + +static int nntpdriver_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int res; + int r; + struct nntp_session_state_data * data; + + length = strlen(mb); + + data = get_data(session); + + subscribed = data->nntp_subscribed_list; + lsub_result = clist_new(); + if (lsub_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + err: + return res; +} + +static int nntpdriver_subscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + + + +/* messages operations */ + +static int nntpdriver_append_message(mailsession * session, + char * message, size_t size) +{ + int r; + struct nntp_session_state_data * data; + + data = get_data(session); + + do { + r = newsnntp_post(get_nntp_session(session), message, size); + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (1); +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result); + + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + newsnntp * nntp; + int r; + struct nntp_session_state_data * data; + clist * list; + int done; + clistiter * cur; + uint32_t first_seq; + unsigned int i; + + nntp = get_nntp_session(session); + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_BAD_STATE; + + first_seq = data->nntp_group_info->grp_first; + + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + + first_seq = msg->msg_index; + } + + if (carray_count(env_list->msg_tab) > 0) { + i = carray_count(env_list->msg_tab) - 1; + while (1) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + first_seq = msg->msg_index + 1; + break; + } + + if (i == 0) + break; + + i --; + } + } + + if (first_seq > data->nntp_group_info->grp_last) { + list = NULL; + } + else { + done = FALSE; + do { + r = newsnntp_xover_range(nntp, first_seq, + data->nntp_group_info->grp_last, &list); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + } + +#if 0 + i = 0; + j = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->fields == NULL) { + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->fields = fields; + } + + info->size = item->ovr_size; + + carray_set(env_list->msg_tab, j, info); + j ++; + i ++; + break; + } + else { + carray_set(env_list->msg_tab, j, info); + j ++; + } + } + else { + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + } + + i ++; + } + } + } + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + + i ++; + } + + r = carray_set_size(env_list->msg_tab, j); + if (r < 0) { + if (list != NULL) + newsnntp_xover_resp_list_free(list); + return MAIL_ERROR_MEMORY; + } +#endif + i = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->msg_fields == NULL) { + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->msg_fields = fields; + } + + info->msg_size = item->ovr_size; + + i ++; + break; + } + } +#if 0 + else if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } +#endif + + i ++; + } + } + } + +#if 0 + while (i < env_list->msg_tab->len) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } + + i ++; + } +#endif + + if (list != NULL) + newsnntp_xover_resp_list_free(list); + + return MAIL_NO_ERROR; +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (item->ovr_subject != NULL) { + char * subject_str; + struct mailimf_subject * subject; + struct mailimf_field * field; + + subject_str = strdup(item->ovr_subject); + if (subject_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + subject = mailimf_subject_new(subject_str); + if (subject == NULL) { + free(subject_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (item->ovr_author != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), + &cur_token, &mb_list); + switch (r) { + case MAILIMF_NO_ERROR: + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_date != NULL) { + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), + &cur_token, &date_time); + switch (r) { + case MAILIMF_NO_ERROR: + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig_date, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig_date); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_message_id != NULL) { + char * msgid_str; + struct mailimf_message_id * msgid; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), + &cur_token, &msgid_str); + + switch (r) { + case MAILIMF_NO_ERROR: + msgid = mailimf_message_id_new(msgid_str); + if (msgid == NULL) { + mailimf_msg_id_free(msgid_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msgid, NULL, + NULL, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_references != NULL) { + clist * msgid_list; + struct mailimf_references * references; + struct mailimf_field * field; + + cur_token = 0; + + r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), + &cur_token, &msgid_list); + + switch (r) { + case MAILIMF_NO_ERROR: + references = mailimf_references_new(msgid_list); + if (references == NULL) { + clist_foreach(msgid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(msgid_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + references, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +/* get messages list with group info */ + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(session, session, nntp_message_driver, result); + +} + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_noop(mailsession * session) +{ + newsnntp * nntp; + int r; + struct tm tm; + + nntp = get_nntp_session(session); + + r = newsnntp_date(nntp, &tm); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_get_message(session, num, result); + } diff --git a/kmicromail/libetpan/generic/nntpdriver.h b/kmicromail/libetpan/generic/nntpdriver.h new file mode 100644 index 0000000..45bfeab --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_H + +#define NNTPDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver_cached.c b/kmicromail/libetpan/generic/nntpdriver_cached.c new file mode 100644 index 0000000..1f8a8af --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_cached.c @@ -0,0 +1,1048 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mail_cache_db.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver_tools.h" +#include "nntpdriver.h" +#include "maildriver.h" +#include "newsnntp.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maillock.h" +#include "nntpdriver_cached_message.h" +#include "nntpdriver_tools.h" + +static int nntpdriver_cached_initialize(mailsession * session); + +static void nntpdriver_cached_uninitialize(mailsession * session); + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int nntpdriver_cached_login(mailsession * session, + char * userid, char * password); + +static int nntpdriver_cached_logout(mailsession * session); + +static int nntpdriver_cached_check_folder(mailsession * session); + +static int nntpdriver_cached_select_folder(mailsession * session, char * mb); + +static int nntpdriver_cached_status_folder(mailsession * session, + char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_cached_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_recent_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +static int nntpdriver_cached_append_message(mailsession * session, + char * message, size_t size); + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + char * mb); + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + char * mb); + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_cached_noop(mailsession * session); + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_nntp_cached_session_driver = { + .sess_name = "nntp-cached", + + .sess_initialize = nntpdriver_cached_initialize, + .sess_uninitialize = nntpdriver_cached_uninitialize, + + .sess_parameters = nntpdriver_cached_parameters, + + .sess_connect_stream = nntpdriver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = NULL, + .sess_login = nntpdriver_cached_login, + .sess_logout = nntpdriver_cached_logout, + .sess_noop = nntpdriver_cached_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = nntpdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = nntpdriver_cached_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = nntpdriver_cached_status_folder, + .sess_messages_number = nntpdriver_cached_messages_number, + .sess_recent_number = nntpdriver_cached_recent_number, + .sess_unseen_number = nntpdriver_cached_unseen_number, + .sess_list_folders = nntpdriver_cached_list_folders, + .sess_lsub_folders = nntpdriver_cached_lsub_folders, + .sess_subscribe_folder = nntpdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder, + + .sess_append_message = nntpdriver_cached_append_message, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = nntpdriver_cached_get_messages_list, + .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = nntpdriver_cached_get_message, + .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid, +}; + + +mailsession_driver * nntp_cached_session_driver = +&local_nntp_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast); + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last); + + +static inline struct nntp_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_ancestor_data(session)->nntp_session; +} + +static int nntpdriver_cached_initialize(mailsession * session) +{ + struct nntp_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->nntp_flags_store = mail_flags_store_new(); + if (data->nntp_flags_store == NULL) + goto free; + + data->nntp_ancestor = mailsession_new(nntp_session_driver); + if (data->nntp_ancestor == NULL) + goto free_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->nntp_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntp_flags_store_process(char * flags_directory, char * group_name, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (group_name == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void nntpdriver_cached_uninitialize(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + mail_flags_store_free(cached_data->nntp_flags_store); + + mailsession_free(cached_data->nntp_ancestor); + free(cached_data); + + session->sess_data = NULL; +} + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->nntp_cache_directory, value, PATH_MAX); + cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->nntp_flags_directory, value, PATH_MAX); + cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(get_ancestor(session), id, value); + } +} + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + return mailsession_connect_stream(get_ancestor(session), s); +} + +static int nntpdriver_cached_login(mailsession * session, + char * userid, char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int nntpdriver_cached_logout(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int nntpdriver_cached_select_folder(mailsession * session, char * mb) +{ + int r; + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + int res; + char key[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + if (ancestor_data->nntp_group_name == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int nntpdriver_cached_check_folder(mailsession * session) +{ + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return MAIL_NO_ERROR; +} + + +static int nntpdriver_cached_status_folder(mailsession * session, + char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + uint32_t i; + int r; + uint32_t recent; + uint32_t unseen; + uint32_t first; + uint32_t last; + uint32_t count; + uint32_t additionnal; + + r = nntpdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + read_article_seq(session, &first, &last); + + count = 0; + recent = 0; + unseen = 0; + + ancestor_data = get_ancestor_data(session); + cached_data = get_cached_data(session); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + if (ancestor_data->nntp_group_info->grp_first > first) + first = ancestor_data->nntp_group_info->grp_first; + if (last < first) + last = ancestor_data->nntp_group_info->grp_last; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = first ; i <= last ; i++) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + i, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) { + continue; + } + + count ++; + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + if ((count == 0) && (first != last)) { + count = last - first + 1; + recent = count; + unseen = count; + } + + additionnal = ancestor_data->nntp_group_info->grp_last - last; + recent += additionnal; + unseen += additionnal; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int nntpdriver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_recent_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_unseen_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_list_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + + + +/* messages operations */ + +static int nntpdriver_cached_append_message(mailsession * session, + char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + char keyname[PATH_MAX]; + int r; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + int res; + char keyname[PATH_MAX]; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +#define SEQ_FILENAME "articles-seq" + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + uint32_t first; + uint32_t last; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + + first = 0; + last = 0; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + f = fopen(seq_filename, "r"); + + if (f != NULL) { + int fd; + + fd = fileno(f); + + r = maillock_read_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t) * 2]; + size_t read_size; + + read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr != NULL) { + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &first); + r = mailimf_cache_int_read(mmapstr, &cur_token, &last); + + mmap_string_free(mmapstr); + } + + maillock_read_unlock(seq_filename, fd); + } + fclose(f); + } + + * pfirst = first; + * plast = last; +} + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + int fd; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + + fd = creat(seq_filename, S_IRUSR | S_IWUSR); + if (fd < 0) + return; + + f = fdopen(fd, "w"); + if (f != NULL) { + r = maillock_write_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr != NULL) { + r = mail_serialize_clear(mmapstr, &cur_token); + if (r == MAIL_NO_ERROR) { + r = mailimf_cache_int_write(mmapstr, &cur_token, first); + r = mailimf_cache_int_write(mmapstr, &cur_token, last); + + fwrite(mmapstr->str, 1, mmapstr->len, f); + } + + mmap_string_free(mmapstr); + } + + maillock_write_unlock(seq_filename, fd); + } + fclose(f); + } + else + close(fd); +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + if (strcmp(filename, SEQ_FILENAME) == 0) + * filename = 0; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct nntp_cached_session_state_data * cached_data; + uint32_t first; + uint32_t last; + struct nntp_session_state_data * ancestor_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + char cache_dir[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* read articles sequence */ + + read_article_seq(session, &first, &last); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if ((msg->msg_index < first) || (msg->msg_index > last)) + continue; + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + msg->msg_cached = TRUE; + } + } + } + + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + else { + msg->msg_flags = mail_flags_new_empty(); + if (msg->msg_fields == NULL) { + msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(msg); + } + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + } + + first = 0; + last = 0; + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + first = msg->msg_index; + + msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1); + last = msg->msg_index; + } + + /* write articles sequence */ + + write_article_seq(session, first, last); + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + /* remove cache files */ + + snprintf(cache_dir, PATH_MAX, "%s/%s", + cached_data->nntp_cache_directory, ancestor_data->nntp_group_name); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + maildriver_message_cache_clean_up(cache_dir, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(get_ancestor(session), session, + nntp_cached_message_driver, result); +} + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_cached_get_message(session, num, result); +} diff --git a/kmicromail/libetpan/generic/nntpdriver_cached.h b/kmicromail/libetpan/generic/nntpdriver_cached.h new file mode 100644 index 0000000..feb576b --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_CACHED_H + +#define NNTPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver_cached_message.c b/kmicromail/libetpan/generic/nntpdriver_cached_message.c new file mode 100644 index 0000000..a2bb6f7 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_cached_message.c @@ -0,0 +1,365 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver_cached_message.h" + +#include +#include + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "nntpdriver.h" +#include "nntpdriver_tools.h" +#include "nntpdriver_cached.h" +#include "nntpdriver_message.h" +#include "generic_cache.h" + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static void nntp_uninitialize(mailmessage * msg_info); + +static void nntp_flush(mailmessage * msg_info); + +static void nntp_check(mailmessage * msg_info); + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_nntp_cached_message_driver = { + .msg_name = "nntp-cached", + + .msg_initialize = nntp_initialize, + .msg_uninitialize = nntp_uninitialize, + + .msg_flush = nntp_flush, + .msg_check = nntp_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = nntp_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = nntp_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = nntp_get_flags, +}; + +mailmessage_driver * nntp_cached_message_driver = +&local_nntp_cached_message_driver; + +static inline struct nntp_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline newsnntp * +get_nntp_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->nntp_session; +} + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_article(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, + &msg_length); + + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void nntp_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void nntp_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + + +static void nntp_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + int r; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i-header", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index); + + if (flags == NULL) { + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/nntpdriver_cached_message.h b/kmicromail/libetpan/generic/nntpdriver_cached_message.h new file mode 100644 index 0000000..c12f479 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include + +#ifndef NNTPDRIVER_CACHED_MESSAGE_H + +#define NNTPDRIVER_CACHED_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * nntp_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver_message.c b/kmicromail/libetpan/generic/nntpdriver_message.c new file mode 100644 index 0000000..47b11ec --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_message.c @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver_message.h" + +#include "mailmessage_tools.h" +#include "nntpdriver_tools.h" +#include "nntpdriver.h" +#include "newsnntp.h" +#include +#include + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_nntp_message_driver = { + .msg_name = "nntp", + + .msg_initialize = nntp_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = nntp_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = nntp_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * nntp_message_driver = &local_nntp_message_driver; + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result); +} diff --git a/kmicromail/libetpan/generic/nntpdriver_message.h b/kmicromail/libetpan/generic/nntpdriver_message.h new file mode 100644 index 0000000..3b12a2d --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_MESSAGE_H + +#define NNTPDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailmessage_driver * nntp_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver_tools.c b/kmicromail/libetpan/generic/nntpdriver_tools.c new file mode 100644 index 0000000..26be916 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_tools.c @@ -0,0 +1,563 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpdriver_tools.h" + +#include "mail.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "newsnntp.h" +#include "maildriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include +#include + +int nntpdriver_nntp_error_to_mail_error(int error) +{ + switch (error) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR; + + case NEWSNNTP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case NEWSNNTP_ERROR_UNEXPECTED: + return MAIL_ERROR_PROGRAM_ERROR; + + case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED: + case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER: + case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE: + case NEWSNNTP_ERROR_INVALID_RESPONSE: + return MAIL_ERROR_PARSE; + + case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED: + return MAIL_ERROR_READONLY; + + case NEWSNNTP_ERROR_POSTING_FAILED: + return MAIL_ERROR_APPEND; + + case NEWSNNTP_ERROR_PROGRAM_ERROR: + return MAIL_ERROR_PROGRAM_ERROR; + + case NEWSNNTP_ERROR_NO_PERMISSION: + return MAIL_ERROR_NO_PERMISSION; + + case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD: + case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED: + return MAIL_ERROR_COMMAND_NOT_SUPPORTED; + + case NEWSNNTP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case NEWSNNTP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED: + return MAIL_ERROR_LOGIN; + + case NEWSNNTP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + default: + return MAIL_ERROR_INVAL; + } +} + +static inline struct nntp_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * session_get_nntp_session(mailsession * session) +{ + return session_get_data(session)->nntp_session; +} + +static inline struct nntp_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline newsnntp * cached_session_get_nntp_session(mailsession * session) +{ + return session_get_nntp_session(cached_session_get_ancestor(session)); +} + + +int nntpdriver_authenticate_password(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_password == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_password(session_get_nntp_session(session), + data->nntp_password); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +int nntpdriver_mode_reader(mailsession * session) +{ + int done; + int r; + + done = FALSE; + + do { + r = newsnntp_mode_reader(session_get_nntp_session(session)); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + done = TRUE; + break; + } + } + while (!done); + + return MAIL_NO_ERROR; +} + +int nntpdriver_authenticate_user(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_userid == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_username(session_get_nntp_session(session), + data->nntp_userid); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + return nntpdriver_authenticate_password(session); + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +int nntpdriver_article(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_article(session_get_nntp_session(session), + index, &msg_content, &msg_length); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_head(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_head(session_get_nntp_session(session), + index, &headers, &headers_length); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_size(mailsession * session, uint32_t index, + size_t * result) +{ + newsnntp * nntp; + struct newsnntp_xover_resp_item * item; + int r; + int done; + + nntp = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_xover_single(nntp, index, &item); + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = item->ovr_size; + + xover_resp_item_free(item); + + return MAIL_NO_ERROR; +} + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + + +int nntpdriver_select_folder(mailsession * session, char * mb) +{ + int r; + struct newsnntp_group_info * info; + newsnntp * nntp_session; + struct nntp_session_state_data * data; + char * new_name; + int done; + + data = session_get_data(session); + + if (!data->nntp_mode_reader) { + r = nntpdriver_mode_reader(session); + if (r != MAIL_NO_ERROR) + return r; + + data->nntp_mode_reader = TRUE; + } + + if (data->nntp_group_name != NULL) + if (strcmp(data->nntp_group_name, mb) == 0) + return MAIL_NO_ERROR; + + nntp_session = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_group(nntp_session, mb, &info); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + + } + while (!done); + + new_name = strdup(mb); + if (new_name == NULL) + return MAIL_ERROR_MEMORY; + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + data->nntp_group_name = new_name; + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + data->nntp_group_info = info; + + return MAIL_NO_ERROR; +} + + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * tab; + struct mailmessage_list * env_list; + uint32_t i; + int res; + int r; + struct nntp_session_state_data * data; + struct newsnntp_group_info * group_info; + uint32_t max; + unsigned int cur; + + data = session_get_data(nntp_session); + + if (data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = nntpdriver_select_folder(nntp_session, data->nntp_group_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + group_info = data->nntp_group_info; + + if (group_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + max = group_info->grp_first; + if (data->nntp_max_articles != 0) { + if (group_info->grp_last - data->nntp_max_articles + 1 > max) + max = group_info->grp_last - data->nntp_max_articles + 1; + } + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = max ; i <= group_info->grp_last ; i++) { + mailmessage * msg; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, i, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(cur = 0 ; cur < carray_count(tab) ; cur ++) + mailmessage_free(carray_get(tab, cur)); + carray_free(tab); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/nntpdriver_tools.h b/kmicromail/libetpan/generic/nntpdriver_tools.h new file mode 100644 index 0000000..6b8aca5 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_tools.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_TOOLS_H + +#define NNTPDRIVER_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mail_cache_db_types.h" +#include "nntpdriver_types.h" + +int nntpdriver_nntp_error_to_mail_error(int error); + +int nntpdriver_authenticate_password(mailsession * session); + +int nntpdriver_authenticate_user(mailsession * session); + +int nntpdriver_article(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int nntpdriver_head(mailsession * session, uint32_t index, + char ** result, + size_t * result_len); + +int nntpdriver_size(mailsession * session, uint32_t index, + size_t * result); + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result); + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags); + +int nntpdriver_select_folder(mailsession * session, char * mb); + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int nntpdriver_mode_reader(mailsession * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpdriver_types.h b/kmicromail/libetpan/generic/nntpdriver_types.h new file mode 100644 index 0000000..6492788 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_types.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_TYPES_H + +#define NNTPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* NNTP driver for session */ + +enum { + NNTPDRIVER_SET_MAX_ARTICLES = 1, +}; + +struct nntp_session_state_data { + newsnntp * nntp_session; + char * nntp_userid; + char * nntp_password; + + struct newsnntp_group_info * nntp_group_info; + char * nntp_group_name; + + clist * nntp_subscribed_list; + + uint32_t nntp_max_articles; + + int nntp_mode_reader; +}; + +/* cached NNTP driver for session */ + +enum { + /* the mapping of the parameters should be the same as for nntp */ + NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1, + /* cache specific */ + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct nntp_cached_session_state_data { + mailsession * nntp_ancestor; + char nntp_cache_directory[PATH_MAX]; + char nntp_flags_directory[PATH_MAX]; + struct mail_flags_store * nntp_flags_store; +}; + + +/* nntp storage */ + +/* + nntp_mailstorage is the state data specific to the IMAP4rev1 storage. + + - storage this is the storage to initialize. + + - servername this is the name of the NNTP server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache + + - flags_directory is the location of the flags +*/ + +struct nntp_mailstorage { + char * nntp_servername; + uint16_t nntp_port; + char * nntp_command; + int nntp_connection_type; + + int nntp_auth_type; + char * nntp_login; + char * nntp_password; + + int nntp_cached; + char * nntp_cache_directory; + char * nntp_flags_directory; +}; + +/* this is the type of NNTP authentication */ + +enum { + NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/nntpstorage.c b/kmicromail/libetpan/generic/nntpstorage.c new file mode 100644 index 0000000..5ba333b --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpstorage.c @@ -0,0 +1,267 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "nntpstorage.h" + +#include +#include + +#include "maildriver.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "mailstorage_tools.h" +#include "mail.h" + +/* nntp storage */ + +#define NNTP_DEFAULT_PORT 119 +#define NNTPS_DEFAULT_PORT 563 + +static int nntp_mailstorage_connect(struct mailstorage * storage); +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void nntp_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver nntp_mailstorage_driver = { + .sto_name = "nntp", + .sto_connect = nntp_mailstorage_connect, + .sto_get_folder_session = nntp_mailstorage_get_folder_session, + .sto_uninitialize = nntp_mailstorage_uninitialize, +}; + +int nntp_mailstorage_init(struct mailstorage * storage, + char * nn_servername, uint16_t nn_port, + char * nn_command, + int nn_connection_type, int nn_auth_type, + char * nn_login, char * nn_password, + int nn_cached, char * nn_cache_directory, char * nn_flags_directory) +{ + struct nntp_mailstorage * nntp_storage; + int res; + + nntp_storage = malloc(sizeof(struct nntp_mailstorage)); + if (nntp_storage == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + nntp_storage->nntp_servername = strdup(nn_servername); + if (nntp_storage->nntp_servername == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + nntp_storage->nntp_connection_type = nn_connection_type; + + if (nn_port == 0) { + switch (nn_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_COMMAND: + nn_port = NNTP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + nn_port = NNTPS_DEFAULT_PORT; + break; + + default: + res = MAIL_ERROR_INVAL; + goto free_servername; + } + } + + nntp_storage->nntp_port = nn_port; + + if (nn_command != NULL) { + nntp_storage->nntp_command = strdup(nn_command); + if (nntp_storage->nntp_command == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_servername; + } + } + else + nntp_storage->nntp_command = NULL; + + nntp_storage->nntp_auth_type = nn_auth_type; + + if (nn_login != NULL) { + nntp_storage->nntp_login = strdup(nn_login); + if (nntp_storage->nntp_login == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_command; + } + } + else + nntp_storage->nntp_login = NULL; + + if (nn_password != NULL) { + nntp_storage->nntp_password = strdup(nn_password); + if (nntp_storage->nntp_password == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_login; + } + } + else + nntp_storage->nntp_password = NULL; + + nntp_storage->nntp_cached = nn_cached; + + if (nn_cached && (nn_cache_directory != NULL) && + (nn_flags_directory != NULL)) { + nntp_storage->nntp_cache_directory = strdup(nn_cache_directory); + if (nntp_storage->nntp_cache_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_password; + } + nntp_storage->nntp_flags_directory = strdup(nn_flags_directory); + if (nntp_storage->nntp_flags_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_cache_directory; + } + } + else { + nntp_storage->nntp_cached = FALSE; + nntp_storage->nntp_cache_directory = NULL; + nntp_storage->nntp_flags_directory = NULL; + } + + storage->sto_data = nntp_storage; + storage->sto_driver = &nntp_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(nntp_storage->nntp_cache_directory); + free_password: + free(nntp_storage->nntp_password); + free_login: + free(nntp_storage->nntp_login); + free_command: + free(nn_command); + free_servername: + free(nntp_storage->nntp_servername); + free: + free(nntp_storage); + err: + return res; +} + +static void nntp_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + + nntp_storage = storage->sto_data; + + if (nntp_storage->nntp_flags_directory != NULL) + free(nntp_storage->nntp_flags_directory); + if (nntp_storage->nntp_cache_directory != NULL) + free(nntp_storage->nntp_cache_directory); + if (nntp_storage->nntp_password != NULL) + free(nntp_storage->nntp_password); + if (nntp_storage->nntp_login != NULL) + free(nntp_storage->nntp_login); + if (nntp_storage->nntp_command != NULL) + free(nntp_storage->nntp_command); + free(nntp_storage->nntp_servername); + free(nntp_storage); + + storage->sto_data = NULL; +} + +static int nntp_mailstorage_connect(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + nntp_storage = storage->sto_data; + + if (nntp_storage->nntp_cached) + driver = nntp_cached_session_driver; + else + driver = nntp_session_driver; + + r = mailstorage_generic_connect(driver, + nntp_storage->nntp_servername, + nntp_storage->nntp_port, nntp_storage->nntp_command, + nntp_storage->nntp_connection_type, + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + nntp_storage->nntp_cache_directory, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY, + nntp_storage->nntp_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + r = mailstorage_generic_auth(session, r, + nntp_storage->nntp_connection_type, + nntp_storage->nntp_login, + nntp_storage->nntp_password); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + int r; + + r = mailsession_select_folder(storage->sto_session, pathname); + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/nntpstorage.h b/kmicromail/libetpan/generic/nntpstorage.h new file mode 100644 index 0000000..794c717 --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpstorage.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPSTORAGE_H + +#define NNTPSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + nntp_mailstorage_init is the constructor for a NNTP storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the NNTP server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int nntp_mailstorage_init(struct mailstorage * storage, + char * nntp_servername, uint16_t nntp_port, + char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + char * nntp_login, char * nntp_password, + int nntp_cached, char * nntp_cache_directory, + char * nntp_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver.c b/kmicromail/libetpan/generic/pop3driver.c new file mode 100644 index 0000000..20b0fc2 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver.c @@ -0,0 +1,387 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3driver.h" + +#include +#include + +#include "pop3driver_message.h" +#include "maildriver_tools.h" +#include "pop3driver_tools.h" +#include "mailmessage.h" + +static int pop3driver_initialize(mailsession * session); + +static void pop3driver_uninitialize(mailsession * session); + +static int pop3driver_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_connect_stream(mailsession * session, mailstream * s); + +static int pop3driver_starttls(mailsession * session); + +static int pop3driver_login(mailsession * session, + char * userid, char * password); + +static int pop3driver_logout(mailsession * session); + +static int pop3driver_noop(mailsession * session); + +static int pop3driver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_messages_number(mailsession * session, char * mb, + uint32_t * result); + +static int pop3driver_remove_message(mailsession * session, uint32_t num); + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static mailsession_driver local_pop3_session_driver = { + .sess_name = "pop3", + + .sess_initialize = pop3driver_initialize, + .sess_uninitialize = pop3driver_uninitialize, + + .sess_parameters = pop3driver_parameters, + + .sess_connect_stream = pop3driver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = pop3driver_starttls, + .sess_login = pop3driver_login, + .sess_logout = pop3driver_logout, + .sess_noop = pop3driver_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = NULL, + .sess_status_folder = pop3driver_status_folder, + .sess_messages_number = pop3driver_messages_number, + .sess_recent_number = pop3driver_messages_number, + .sess_unseen_number = pop3driver_messages_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = NULL, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = pop3driver_get_messages_list, + .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, + .sess_remove_message = pop3driver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = pop3driver_get_message, + .sess_get_message_by_uid = NULL, +}; + +mailsession_driver * pop3_session_driver = &local_pop3_session_driver; + +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + +static int pop3driver_initialize(mailsession * session) +{ + struct pop3_session_state_data * data; + mailpop3 * pop3; + + pop3 = mailpop3_new(0, NULL); + if (session == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->pop3_session = pop3; + data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + mailpop3_free(pop3); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3driver_uninitialize(mailsession * session) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + mailpop3_free(data->pop3_session); + free(data); + + session->sess_data = data; +} + +static int pop3driver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailpop3_connect(get_pop3_session(session), s); + + switch (r) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return pop3driver_pop3_error_to_mail_error(r); + } +} + +static int pop3driver_starttls(mailsession * session) +{ + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_stls(pop3); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + low = mailstream_get_low(pop3->pop3_stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAIL_ERROR_STREAM; + + new_low = mailstream_low_ssl_open(fd); + if (new_low == NULL) + return MAIL_ERROR_STREAM; + mailstream_low_free(low); + mailstream_set_low(pop3->pop3_stream, new_low); + + return MAIL_NO_ERROR; +} + +static int pop3driver_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (id) { + case POP3DRIVER_SET_AUTH_TYPE: + { + int * param; + + param = value; + + data->pop3_auth_type = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + +static int pop3driver_login(mailsession * session, + char * userid, char * password) +{ + int r; + carray * msg_tab; + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (data->pop3_auth_type) { + case POP3DRIVER_AUTH_TYPE_TRY_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + if (r != MAILPOP3_NO_ERROR) + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + + case POP3DRIVER_AUTH_TYPE_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + break; + + default: + case POP3DRIVER_AUTH_TYPE_PLAIN: + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + } + + mailpop3_list(get_pop3_session(session), &msg_tab); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_logout(mailsession * session) +{ + int r; + + r = mailpop3_quit(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_noop(mailsession * session) +{ + int r; + + r = mailpop3_noop(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = pop3driver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int pop3driver_messages_number(mailsession * session, char * mb, + uint32_t * result) +{ + carray * msg_tab; + + mailpop3_list(get_pop3_session(session), &msg_tab); + + * result = carray_count(msg_tab) - + get_pop3_session(session)->pop3_deleted_count; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int pop3driver_remove_message(mailsession * session, uint32_t num) +{ + mailpop3 * pop3; + int r; + + pop3 = get_pop3_session(session); + + r = mailpop3_dele(pop3, num); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + default: + return MAIL_ERROR_REMOVE; + } +} + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_message_driver, result); +} + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/pop3driver.h b/kmicromail/libetpan/generic/pop3driver.h new file mode 100644 index 0000000..2df94db --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_H + +#define POP3DRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * pop3_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver_cached.c b/kmicromail/libetpan/generic/pop3driver_cached.c new file mode 100644 index 0000000..6f97303 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_cached.c @@ -0,0 +1,857 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3driver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mail_cache_db.h" + +#include "maildriver.h" +#include "mailmessage.h" +#include "pop3driver.h" +#include "mailpop3.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "pop3driver_cached_message.h" +#include "pop3driver_tools.h" +#include "maildriver_tools.h" + +static int pop3driver_cached_initialize(mailsession * session); + +static void pop3driver_cached_uninitialize(mailsession * session); + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int pop3driver_cached_starttls(mailsession * session); + +static int pop3driver_cached_login(mailsession * session, + char * userid, char * password); + +static int pop3driver_cached_logout(mailsession * session); + +static int pop3driver_cached_check_folder(mailsession * session); + +static int pop3driver_cached_noop(mailsession * session); + +static int pop3driver_cached_expunge_folder(mailsession * session); + +static int pop3driver_cached_status_folder(mailsession * session, + char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result); + +static int pop3driver_cached_recent_number(mailsession * session, + char * mb, + uint32_t * result); + +static int pop3driver_cached_unseen_number(mailsession * session, + char * mb, + uint32_t * result); + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num); + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static mailsession_driver local_pop3_cached_session_driver = { + .sess_name = "pop3-cached", + + .sess_initialize = pop3driver_cached_initialize, + .sess_uninitialize = pop3driver_cached_uninitialize, + + .sess_parameters = pop3driver_cached_parameters, + + .sess_connect_stream = pop3driver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = pop3driver_cached_starttls, + .sess_login = pop3driver_cached_login, + .sess_logout = pop3driver_cached_logout, + .sess_noop = pop3driver_cached_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = pop3driver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = pop3driver_cached_expunge_folder, + .sess_status_folder = pop3driver_cached_status_folder, + .sess_messages_number = pop3driver_cached_messages_number, + .sess_recent_number = pop3driver_cached_recent_number, + .sess_unseen_number = pop3driver_cached_unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = NULL, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = pop3driver_cached_get_messages_list, + .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list, + .sess_remove_message = pop3driver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = pop3driver_cached_get_message, + .sess_get_message_by_uid = NULL, +}; + +mailsession_driver * pop3_cached_session_driver = +&local_pop3_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct pop3_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailsession * session) +{ + return get_ancestor_data(session)->pop3_session; +} + +static int pop3driver_cached_initialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->pop3_flags_store = mail_flags_store_new(); + if (data->pop3_flags_store == NULL) + goto free_data; + + data->pop3_ancestor = mailsession_new(pop3_session_driver); + if (data->pop3_ancestor == NULL) + goto free_store; + + data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE); + if (data->pop3_flags_hash == NULL) + goto free_session; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->pop3_ancestor); + free_store: + mail_flags_store_free(data->pop3_flags_store); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int pop3_flags_store_process(char * flags_directory, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s", + flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void pop3driver_cached_uninitialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = get_cached_data(session); + + pop3_flags_store_process(data->pop3_flags_directory, + data->pop3_flags_store); + + mail_flags_store_free(data->pop3_flags_store); + + chash_free(data->pop3_flags_hash); + mailsession_free(data->pop3_ancestor); + free(data); + + session->sess_data = data; +} + +static int pop3driver_cached_check_folder(mailsession * session) +{ + struct pop3_cached_session_state_data * pop3_data; + + pop3_data = get_cached_data(session); + + pop3_flags_store_process(pop3_data->pop3_flags_directory, + pop3_data->pop3_flags_store); + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->pop3_cache_directory, value, PATH_MAX); + data->pop3_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->pop3_flags_directory, value, PATH_MAX); + data->pop3_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->pop3_ancestor, id, value); + } +} + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + r = mailsession_connect_stream(get_ancestor(session), s); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_starttls(mailsession * session) +{ + return mailsession_starttls(get_ancestor(session)); +} + + +static int pop3driver_cached_login(mailsession * session, + char * userid, char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int pop3driver_cached_logout(mailsession * session) +{ + struct pop3_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int pop3driver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int pop3driver_cached_expunge_folder(mailsession * session) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + mailpop3_list(pop3, &msg_tab); + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailpop3_dele(pop3, pop3_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_status_folder(mailsession * session, + char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + uint32_t recent; + uint32_t unseen; + + recent = 0; + unseen = 0; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + mailpop3_list(pop3, &msg_tab); + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_messages_number(mailsession * session, + char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int pop3driver_cached_recent_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_unseen_number(mailsession * session, + char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_cached_message_driver, result); +} + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailpop3_msg_info * info; + struct mailimf_fields * fields; + int res; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct pop3_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_env, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, ENV_NAME); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = maildriver_generic_get_envelopes_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(cached_data->pop3_cache_directory, + env_list, get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} diff --git a/kmicromail/libetpan/generic/pop3driver_cached.h b/kmicromail/libetpan/generic/pop3driver_cached.h new file mode 100644 index 0000000..953e699 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_CACHED_H + +#define POP3DRIVER_CACHED_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * pop3_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver_cached_message.c b/kmicromail/libetpan/generic/pop3driver_cached_message.c new file mode 100644 index 0000000..7aeb22c --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_cached_message.c @@ -0,0 +1,355 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3driver_cached_message.h" + +#include +#include + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "pop3driver.h" +#include "pop3driver_tools.h" +#include "pop3driver_cached.h" +#include "pop3driver_message.h" +#include "generic_cache.h" + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static void pop3_flush(mailmessage * msg_info); + +static void pop3_check(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void pop3_uninitialize(mailmessage * msg_info); + +static mailmessage_driver local_pop3_cached_message_driver = { + .msg_name = "pop3-cached", + + .msg_initialize = pop3_initialize, + .msg_uninitialize = pop3_uninitialize, + + .msg_flush = pop3_flush, + .msg_check = pop3_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = pop3_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = pop3_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = pop3_get_flags, +}; + +mailmessage_driver * pop3_cached_message_driver = +&local_pop3_cached_message_driver; + + +static inline struct pop3_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->pop3_session; +} + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void pop3_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void pop3_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void pop3_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store, + msg_info); + } +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s-header", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message trough the network */ + + r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct pop3_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->pop3_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/pop3driver_cached_message.h b/kmicromail/libetpan/generic/pop3driver_cached_message.h new file mode 100644 index 0000000..d03f8e5 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_CACHED_MESSAGE_H + +#define POP3DRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver_message.c b/kmicromail/libetpan/generic/pop3driver_message.c new file mode 100644 index 0000000..77bd94c --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_message.c @@ -0,0 +1,159 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3driver_message.h" + +#include "mailmessage_tools.h" +#include "pop3driver_tools.h" +#include "pop3driver.h" +#include "mailpop3.h" + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_pop3_message_driver = { + .msg_name = "pop3", + + .msg_initialize = pop3_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = pop3_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = pop3_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +}; + +mailmessage_driver * pop3_message_driver = &local_pop3_message_driver; + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + + return MAIL_NO_ERROR; +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = pop3driver_header(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result); +} diff --git a/kmicromail/libetpan/generic/pop3driver_message.h b/kmicromail/libetpan/generic/pop3driver_message.h new file mode 100644 index 0000000..6281a39 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_MESSAGE_H + +#define POP3DRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver_tools.c b/kmicromail/libetpan/generic/pop3driver_tools.c new file mode 100644 index 0000000..8978b47 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_tools.c @@ -0,0 +1,344 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3driver_tools.h" + +#include +#include +#include +#include + +#include "maildriver_types.h" +#include "mailpop3.h" +#include "pop3driver.h" +#include "pop3driver_cached.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int pop3driver_pop3_error_to_mail_error(int error) +{ + switch (error) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_UNAUTHORIZED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_ERROR_DENIED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_BAD_USER: + case MAILPOP3_ERROR_BAD_PASSWORD: + return MAIL_ERROR_LOGIN; + + case MAILPOP3_ERROR_CANT_LIST: + return MAIL_ERROR_LIST; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILPOP3_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_APOP_NOT_SUPPORTED: + return MAIL_ERROR_NO_APOP; + + case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED: + return MAIL_ERROR_CAPABILITY; + + case MAILPOP3_ERROR_STLS_NOT_SUPPORTED: + return MAIL_ERROR_NO_TLS; + + default: + return MAIL_ERROR_INVAL; + } +}; + +static inline struct pop3_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailpop3 * session_get_pop3_session(mailsession * session) +{ + return session_get_data(session)->pop3_session; +} + +static inline struct pop3_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailpop3 * +cached_session_get_pop3_session(mailsession * session) +{ + return session_get_pop3_session(cached_session_get_ancestor(session)); +} + + +int pop3driver_retr(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + + r = mailpop3_retr(session_get_pop3_session(session), index, + &msg_content, &msg_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_header(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + + r = mailpop3_header(session_get_pop3_session(session), + index, &headers, &headers_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_size(mailsession * session, uint32_t index, + size_t * result) +{ + mailpop3 * pop3; + carray * msg_tab; + struct mailpop3_msg_info * info; + int r; + + pop3 = session_get_pop3_session(session); + + mailpop3_list(pop3, &msg_tab); + + r = mailpop3_get_msg_info(pop3, index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = info->msg_size; + + return MAIL_NO_ERROR; +} + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailpop3_msg_info * info; + + r = mailpop3_get_msg_info(cached_session_get_pop3_session(session), + num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * msg_tab; + carray * tab; + struct mailmessage_list * env_list; + unsigned int i; + int res; + int r; + + mailpop3_list(pop3, &msg_tab); + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + mailmessage * msg; + + pop3_info = carray_get(msg_tab, i); + + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + (uint32_t) pop3_info->msg_index, pop3_info->msg_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(/*list*/ tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/kmicromail/libetpan/generic/pop3driver_tools.h b/kmicromail/libetpan/generic/pop3driver_tools.h new file mode 100644 index 0000000..ad5f589 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_tools.h @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_TOOLS_H + +#define POP3DRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "pop3driver_types.h" +#include "mailpop3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int pop3driver_pop3_error_to_mail_error(int error); + +int pop3driver_retr(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int pop3driver_header(mailsession * session, uint32_t index, + char ** result, + size_t * result_len); + +int pop3driver_size(mailsession * session, uint32_t index, + size_t * result); + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3driver_types.h b/kmicromail/libetpan/generic/pop3driver_types.h new file mode 100644 index 0000000..73286d8 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3driver_types.h @@ -0,0 +1,153 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_TYPES_H + +#define POP3DRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* POP3 driver for session */ + +enum { + POP3DRIVER_SET_AUTH_TYPE = 1, +}; + +enum { + POP3DRIVER_AUTH_TYPE_PLAIN = 0, + POP3DRIVER_AUTH_TYPE_APOP, + POP3DRIVER_AUTH_TYPE_TRY_APOP, +}; + +struct pop3_session_state_data { + int pop3_auth_type; + mailpop3 * pop3_session; +}; + +/* cached POP3 driver for session */ + +enum { + /* the mapping of the parameters should be the same as for pop3 */ + POP3DRIVER_CACHED_SET_AUTH_TYPE = 1, + /* cache specific */ + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct pop3_cached_session_state_data { + mailsession * pop3_ancestor; + char pop3_cache_directory[PATH_MAX]; + char pop3_flags_directory[PATH_MAX]; + chash * pop3_flags_hash; + carray * pop3_flags_array; + struct mail_flags_store * pop3_flags_store; +}; + +/* pop3 storage */ + +/* + pop3_mailstorage is the state data specific to the POP3 storage. + + - servername this is the name of the POP3 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct pop3_mailstorage { + char * pop3_servername; + uint16_t pop3_port; + char * pop3_command; + int pop3_connection_type; + + int pop3_auth_type; + char * pop3_login; + char * pop3_password; + + int pop3_cached; + char * pop3_cache_directory; + char * pop3_flags_directory; +}; + +/* this is the type of POP3 authentication */ + +enum { + POP3_AUTH_TYPE_PLAIN, /* plain text authentication */ + POP3_AUTH_TYPE_APOP, /* APOP authentication */ + POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails, + try plain text */ + POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/generic/pop3storage.c b/kmicromail/libetpan/generic/pop3storage.c new file mode 100644 index 0000000..8e7a94e --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3storage.c @@ -0,0 +1,284 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "pop3storage.h" + +#include +#include + +#include "mail.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* pop3 storage */ + +#define POP3_DEFAULT_PORT 110 +#define POP3S_DEFAULT_PORT 995 + +static int pop3_mailstorage_connect(struct mailstorage * storage); +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void pop3_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver pop3_mailstorage_driver = { + .sto_name = "pop3", + .sto_connect = pop3_mailstorage_connect, + .sto_get_folder_session = pop3_mailstorage_get_folder_session, + .sto_uninitialize = pop3_mailstorage_uninitialize, +}; + +int pop3_mailstorage_init(struct mailstorage * storage, + char * pop3_servername, uint16_t pop3_port, + char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + char * pop3_login, char * pop3_password, + int pop3_cached, char * pop3_cache_directory, char * pop3_flags_directory) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = malloc(sizeof(struct pop3_mailstorage)); + if (pop3_storage == NULL) + goto err; + + pop3_storage->pop3_servername = strdup(pop3_servername); + if (pop3_storage->pop3_servername == NULL) + goto free; + + pop3_storage->pop3_connection_type = pop3_connection_type; + + if (pop3_port == 0) { + switch (pop3_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + pop3_port = POP3_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + pop3_port = POP3S_DEFAULT_PORT; + break; + } + } + + pop3_storage->pop3_port = pop3_port; + + if (pop3_command != NULL) { + pop3_storage->pop3_command = strdup(pop3_command); + if (pop3_storage->pop3_command == NULL) + goto free_servername; + } + else + pop3_storage->pop3_command = NULL; + + pop3_storage->pop3_auth_type = pop3_auth_type; + + if (pop3_login != NULL) { + pop3_storage->pop3_login = strdup(pop3_login); + if (pop3_storage->pop3_login == NULL) + goto free_command; + } + else + pop3_storage->pop3_login = NULL; + + if (pop3_password != NULL) { + pop3_storage->pop3_password = strdup(pop3_password); + if (pop3_storage->pop3_password == NULL) + goto free_login; + } + else + pop3_storage->pop3_password = NULL; + + pop3_storage->pop3_cached = pop3_cached; + + if (pop3_cached && (pop3_cache_directory != NULL) && + (pop3_flags_directory != NULL)) { + pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory); + if (pop3_storage->pop3_cache_directory == NULL) + goto free_password; + pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory); + if (pop3_storage->pop3_flags_directory == NULL) + goto free_cache_directory; + } + else { + pop3_storage->pop3_cached = FALSE; + pop3_storage->pop3_cache_directory = NULL; + pop3_storage->pop3_flags_directory = NULL; + } + + storage->sto_data = pop3_storage; + storage->sto_driver = &pop3_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(pop3_storage->pop3_cache_directory); + free_password: + if (pop3_storage->pop3_password != NULL) + free(pop3_storage->pop3_password); + free_login: + if (pop3_storage->pop3_login != NULL) + free(pop3_storage->pop3_login); + free_command: + if (pop3_storage->pop3_command != NULL) + free(pop3_storage->pop3_command); + free_servername: + if (pop3_storage->pop3_servername != NULL) + free(pop3_storage->pop3_servername); + free: + free(pop3_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = storage->sto_data; + + if (pop3_storage->pop3_flags_directory != NULL) + free(pop3_storage->pop3_flags_directory); + if (pop3_storage->pop3_cache_directory != NULL) + free(pop3_storage->pop3_cache_directory); + if (pop3_storage->pop3_password != NULL) + free(pop3_storage->pop3_password); + if (pop3_storage->pop3_login != NULL) + free(pop3_storage->pop3_login); + if (pop3_storage->pop3_command != NULL) + free(pop3_storage->pop3_command); + free(pop3_storage->pop3_servername); + free(pop3_storage); + + storage->sto_data = pop3_storage; +} + +static int pop3_mailstorage_connect(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + int auth_type; + + pop3_storage = storage->sto_data; + + if (pop3_storage->pop3_cached) + driver = pop3_cached_session_driver; + else + driver = pop3_session_driver; + + r = mailstorage_generic_connect(driver, + pop3_storage->pop3_servername, + pop3_storage->pop3_port, pop3_storage->pop3_command, + pop3_storage->pop3_connection_type, + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + pop3_storage->pop3_cache_directory, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY, + pop3_storage->pop3_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + auth_type = -1; + switch (pop3_storage->pop3_auth_type) { + case POP3_AUTH_TYPE_PLAIN: + auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + break; + case POP3_AUTH_TYPE_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_APOP; + break; + case POP3_AUTH_TYPE_TRY_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP; + break; + } + + if (auth_type != -1) { + mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type); + } + + r = mailstorage_generic_auth(session, r, + pop3_storage->pop3_auth_type, + pop3_storage->pop3_login, + pop3_storage->pop3_password); + if (r != MAIL_NO_ERROR) { + if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) { + /* try in clear authentication */ + mailsession_free(session); + + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN; + r = mailstorage_connect(storage); + if (r != MAIL_NO_ERROR) { + res = r; + return res; + } + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP; + + return MAIL_NO_ERROR; + } + + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/kmicromail/libetpan/generic/pop3storage.h b/kmicromail/libetpan/generic/pop3storage.h new file mode 100644 index 0000000..c2118b6 --- a/dev/null +++ b/kmicromail/libetpan/generic/pop3storage.h @@ -0,0 +1,95 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3STORAGE_H + +#define POP3STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + pop3_mailstorage_init is the constructor for a POP3 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the POP3 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int pop3_mailstorage_init(struct mailstorage * storage, + char * pop3_servername, uint16_t pop3_port, + char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + char * pop3_login, char * pop3_password, + int pop3_cached, char * pop3_cache_directory, + char * pop3_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/.libs/libmailimap.a b/kmicromail/libetpan/imap/.libs/libmailimap.a new file mode 100644 index 0000000..c98f6a7 --- a/dev/null +++ b/kmicromail/libetpan/imap/.libs/libmailimap.a Binary files differ diff --git a/kmicromail/libetpan/imap/TODO b/kmicromail/libetpan/imap/TODO new file mode 100644 index 0000000..a787a3b --- a/dev/null +++ b/kmicromail/libetpan/imap/TODO @@ -0,0 +1,4 @@ +- literal data send progress +- implement draft-16 (rfc 2822 things) +- more efficient parser + diff --git a/kmicromail/libetpan/imap/mailimap.c b/kmicromail/libetpan/imap/mailimap.c new file mode 100644 index 0000000..c8fbfee --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap.c @@ -0,0 +1,2161 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mail.h" + +#include +#include +#include + +#ifdef DEBUG +#include "mailimap_print.h" +#endif + +/* + RFC 2060 : IMAP4rev1 + draft-crispin-imapv-15 + RFC 2222 : Simple Authentication and Security Layer + +2061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996. + (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL) + +2062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin. + December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL) + +2086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925 + bytes) (Status: PROPOSED STANDARD) + +2087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542 + bytes) (Status: PROPOSED STANDARD) + +2088 IMAP4 non-synchronizing literals. J. Myers. January 1997. + (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD) + +2177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes) + (Status: PROPOSED STANDARD) + +2180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997. + (Format: TXT=24750 bytes) (Status: INFORMATIONAL) + +2192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426 + bytes) (Status: PROPOSED STANDARD) + +2193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format: + TXT=16248 bytes) (Status: PROPOSED STANDARD) + +2195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J. + Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468 + bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD) + +2221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251 + bytes) (Status: PROPOSED STANDARD) + +2342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format: + TXT=19489 bytes) (Status: PROPOSED STANDARD) + +2359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862 + bytes) (Status: PROPOSED STANDARD) + +2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999. + (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD) + +2683 IMAP4 Implementation Recommendations. B. Leiba. September 1999. + (Format: TXT=56300 bytes) (Status: INFORMATIONAL) + +2971 IMAP4 ID extension. T. Showalter. October 2000. (Format: + TXT=14670 bytes) (Status: PROPOSED STANDARD) + +http://www.ietf.org/ids.by.wg/imapext.html +*/ + +static char * read_line(mailimap * session); + +static int send_current_tag(mailimap * session); + +static int parse_response(mailimap * session, + struct mailimap_response ** result); + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result); + + +/* struct mailimap_response_info * */ + +static void resp_text_store(mailimap * session, + struct mailimap_resp_text * + resp_text) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = resp_text->rsp_code; + + if (resp_text_code != NULL) { + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_ALERT: + if (session->imap_response_info) + if (session->imap_response_info->rsp_alert != NULL) + free(session->imap_response_info->rsp_alert); + session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text); + break; + + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + session->imap_response_info->rsp_badcharset = + resp_text_code->rc_data.rc_badcharset; + resp_text_code->rc_data.rc_badcharset = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = + resp_text_code->rc_data.rc_cap_data; + /* detach before free */ + resp_text_code->rc_data.rc_cap_data = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PARSE: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_parse != NULL) + free(session->imap_response_info->rsp_parse); + session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text); + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_perm_flags != NULL) { + clist_foreach(session->imap_selection_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(session->imap_selection_info->sel_perm_flags); + } + session->imap_selection_info->sel_perm_flags = + resp_text_code->rc_data.rc_perm_flags; + /* detach before free */ + resp_text_code->rc_data.rc_perm_flags = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY; + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + if (session->imap_response_info) + session->imap_response_info->rsp_trycreate = TRUE; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidnext = + resp_text_code->rc_data.rc_uidnext; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidvalidity = + resp_text_code->rc_data.rc_uidvalidity; + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + if (session->imap_selection_info) + session->imap_selection_info->sel_first_unseen = + resp_text_code->rc_data.rc_first_unseen; + break; + } + } +} + +static void resp_cond_state_store(mailimap * session, + struct mailimap_resp_cond_state * resp_cond_state) +{ + resp_text_store(session, resp_cond_state->rsp_text); +} + +static void mailbox_data_store(mailimap * session, + struct mailimap_mailbox_data * mb_data) +{ + int r; + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_flags != NULL) + mailimap_flag_list_free(session->imap_selection_info->sel_flags); + session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags; + mb_data->mbd_data.mbd_flags = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_list, + mb_data->mbd_data.mbd_list); + if (r == 0) + mb_data->mbd_data.mbd_list = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_lsub, + mb_data->mbd_data.mbd_lsub); + if (r == 0) + mb_data->mbd_data.mbd_lsub = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_search_result != NULL) { + if (mb_data->mbd_data.mbd_search != NULL) { + clist_concat(session->imap_response_info->rsp_search_result, + mb_data->mbd_data.mbd_search); + clist_free(mb_data->mbd_data.mbd_search); + mb_data->mbd_data.mbd_search = NULL; + } + } + else { + if (mb_data->mbd_data.mbd_search != NULL) { + session->imap_response_info->rsp_search_result = + mb_data->mbd_data.mbd_search; + mb_data->mbd_data.mbd_search = NULL; + } + } + } + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status); + session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status; +#if 0 + if (session->imap_selection_info != NULL) { + clistiter * cur; + + for(cur = clist_begin(mb_data->status->status_info_list) + ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + switch (info->att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + session->imap_selection_info->exists = info->value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + session->imap_selection_info->recent = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + session->imap_selection_info->uidnext = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + session->imap_selection_info->uidvalidity = info->value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + session->imap_selection_info->unseen = info->value; + break; + } + } + } +#endif +#if 0 + mailimap_mailbox_data_status_free(mb_data->status); +#endif + mb_data->mbd_data.mbd_status = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + if (session->imap_selection_info) + session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists; + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + if (session->imap_selection_info) + session->imap_selection_info->sel_recent = + mb_data->mbd_data.mbd_recent; + break; + } +} + +static void +message_data_store(mailimap * session, + struct mailimap_message_data * msg_data) +{ + uint32_t * expunged; + int r; + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + if (session->imap_response_info) { + expunged = mailimap_number_alloc_new(msg_data->mdt_number); + if (expunged != NULL) { + r = clist_append(session->imap_response_info->rsp_expunged, expunged); + if (r == 0) { + /* do nothing */ + } + else { + /* TODO : must handle error case */ + mailimap_number_alloc_free(expunged); + } + if (session->imap_selection_info != NULL) + session->imap_selection_info->sel_exists --; + } + } + break; + + case MAILIMAP_MESSAGE_DATA_FETCH: + r = clist_append(session->imap_response_info->rsp_fetch_list, + msg_data->mdt_msg_att); + if (r == 0) { + msg_data->mdt_msg_att->att_number = msg_data->mdt_number; + msg_data->mdt_msg_att = NULL; + } + else { + /* TODO : must handle error case */ + } + break; + } +} + +static void +cont_req_or_resp_data_store(mailimap * session, + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) { + struct mailimap_response_data * resp_data; + + resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data; + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + message_data_store(session, resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data; + resp_data->rsp_data.rsp_capability_data = NULL; + } + break; + } + } +} + +static void response_tagged_store(mailimap * session, + struct mailimap_response_tagged * tagged) +{ + resp_cond_state_store(session, tagged->rsp_cond_state); +} + +static void resp_cond_bye_store(mailimap * session, + struct mailimap_resp_cond_bye * resp_cond_bye) +{ + resp_text_store(session, resp_cond_bye->rsp_text); +} + +static void response_fatal_store(mailimap * session, + struct mailimap_response_fatal * fatal) +{ + resp_cond_bye_store(session, fatal->rsp_bye); +} + +static void response_done_store(mailimap * session, + struct mailimap_response_done * resp_done) +{ + switch(resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + response_tagged_store(session, resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + response_fatal_store(session, resp_done->rsp_data.rsp_fatal); + break; + } +} + +static void +response_store(mailimap * session, + struct mailimap_response * response) +{ + clistiter * cur; + + if (session->imap_response_info) { + mailimap_response_info_free(session->imap_response_info); + session->imap_response_info = NULL; + } + + session->imap_response_info = mailimap_response_info_new(); + if (session->imap_response_info == NULL) { + /* ignored error */ + return; + } + + if (response->rsp_cont_req_or_resp_data_list != NULL) { + for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = clist_content(cur); + + cont_req_or_resp_data_store(session, cont_req_or_resp_data); + } + } + + response_done_store(session, response->rsp_resp_done); +} + +static void resp_cond_auth_store(mailimap * session, + struct mailimap_resp_cond_auth * cond_auth) +{ + resp_text_store(session, cond_auth->rsp_text); +} + +static void greeting_store(mailimap * session, + struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + resp_cond_auth_store(session, greeting->gr_data.gr_auth); + break; + + case MAILIMAP_GREETING_RESP_COND_BYE: + resp_cond_bye_store(session, greeting->gr_data.gr_bye); + break; + } +} + +int mailimap_connect(mailimap * session, mailstream * s) +{ + struct mailimap_greeting * greeting; + int r; + int auth_type; + struct mailimap_connection_info * connection_info; + + if (session->imap_state != MAILIMAP_STATE_DISCONNECTED) + return MAILIMAP_ERROR_BAD_STATE; + + session->imap_stream = s; + + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + connection_info = mailimap_connection_info_new(); + if (connection_info != NULL) + session->imap_connection_info = connection_info; + + if (read_line(session) == NULL) { + return MAILIMAP_ERROR_STREAM; + } + + r = parse_greeting(session, &greeting); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + auth_type = greeting->gr_data.gr_auth->rsp_type; + + mailimap_greeting_free(greeting); + + switch (auth_type) { + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR_AUTHENTICATED; + default: + session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED; + return MAILIMAP_NO_ERROR_NON_AUTHENTICATED; + } +} + + + + + + + + +/* ********************************************************************** */ + + + +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_continue_req * cont_req; + size_t index; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time, + literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + index = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r == MAILIMAP_NO_ERROR) + mailimap_continue_req_free(cont_req); + + if (r == MAILIMAP_ERROR_PARSE) { + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_response_free(response); + + return MAILIMAP_ERROR_APPEND; + } + + r = mailimap_literal_data_send(session->imap_stream, literal, literal_size, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_APPEND; + } +} + +/* +gboolean mailimap_authenticate(mailimap * session, + gchar * auth_type) +{ +} + +gboolean mailimap_authenticate_resp_send(mailimap * session, + gchar * base64) +{ +} +*/ + +int mailimap_noop(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_noop_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_NOOP; + } +} + +int mailimap_logout(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + int res; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_logout_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + if (read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + if (session->imap_connection_info) { + mailimap_connection_info_free(session->imap_connection_info); + session->imap_connection_info = NULL; + } + res = MAILIMAP_NO_ERROR; + goto close; + + default: + res = MAILIMAP_ERROR_LOGOUT; + goto close; + } + + close: + mailstream_close(session->imap_stream); + session->imap_stream = NULL; + session->imap_state = MAILIMAP_STATE_DISCONNECTED; + return res; +} + +/* send the results back to the caller */ +/* duplicate the result */ + +static struct mailimap_capability * +mailimap_capability_dup(struct mailimap_capability * orig_cap) +{ + struct mailimap_capability * cap; + char * auth_type; + char * name; + + name = NULL; + auth_type = NULL; + switch (orig_cap->cap_type) { + case MAILIMAP_CAPABILITY_NAME: + name = strdup(orig_cap->cap_data.cap_name); + if (name == NULL) + goto err; + break; + case MAILIMAP_CAPABILITY_AUTH_TYPE: + auth_type = strdup(orig_cap->cap_data.cap_auth_type); + if (auth_type == NULL) + goto err; + break; + } + + cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name); + if (cap == NULL) + goto free; + + return cap; + + free: + if (name != NULL) + free(name); + if (auth_type != NULL) + free(auth_type); + err: + return NULL; +} + +static struct mailimap_capability_data * +mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data) +{ + struct mailimap_capability_data * cap_data; + struct mailimap_capability * cap_dup; + clist * list; + clistiter * cur; + int r; + + list = clist_new(); + if (list == NULL) + goto err; + + for(cur = clist_begin(orig_cap_data->cap_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + cap_dup = mailimap_capability_dup(cap); + if (cap_dup == NULL) + goto list; + + r = clist_append(list, cap_dup); + if (r < 0) { + mailimap_capability_free(cap_dup); + goto list; + } + } + + cap_data = mailimap_capability_data_new(list); + if (cap_data == NULL) + goto list; + + return cap_data; + +list: + clist_foreach(list, (clist_func) mailimap_capability_free, NULL); + clist_free(list); +err: + return NULL; +} + +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_capability_data * cap_data; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_capability_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + cap_data = + mailimap_capability_data_dup(session->imap_connection_info->imap_capability); + if (cap_data == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = cap_data; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CAPABILITY; + } +} + +int mailimap_check(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_check_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CHECK; + } +} + +int mailimap_close(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_close_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + /* leave selected state */ + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CLOSE; + } +} + +int mailimap_expunge(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_expunge_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_COPY; + } +} + +int mailimap_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_COPY; + } +} + +int mailimap_create(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_create_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CREATE; + } +} + + +int mailimap_delete(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_delete_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_DELETE; + } +} + +int mailimap_examine(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_examine_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_EXAMINE; + } +} + +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_FETCH; + } +} + +void mailimap_fetch_list_free(clist * fetch_list) +{ + clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL); + clist_free(fetch_list); +} + +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_FETCH; + } +} + +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_list; + session->imap_response_info->rsp_mailbox_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LIST; + } +} + +int mailimap_login(mailimap * session, + const char * userid, const char * password) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_login_send(session->imap_stream, userid, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LOGIN; + } +} + +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_lsub_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_lsub; + session->imap_response_info->rsp_mailbox_lsub = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LSUB; + } +} + +void mailimap_list_result_free(clist * list) +{ + clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(list); +} + +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_rename_send(session->imap_stream, mb, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (!mailimap_crlf_send(session->imap_stream)) + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_RENAME; + } +} + +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SEARCH; + } +} + +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_SEARCH; + } +} + +void mailimap_search_result_free(clist * search_result) +{ + clist_foreach(search_result, (clist_func) free, NULL); + clist_free(search_result); +} + +int +mailimap_select(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_select_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_SELECT; + } +} + +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_send(session->imap_stream, mb, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_status; + session->imap_response_info->rsp_status = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STATUS; + } +} + + +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +} + +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +} + +int mailimap_subscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SUBSCRIBE; + } +} + +int mailimap_unsubscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UNSUBSCRIBE; + } +} + + +int mailimap_starttls(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_starttls_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STARTTLS; + } +} + + + +static char * read_line(mailimap * session) +{ + return mailstream_read_line(session->imap_stream, session->imap_stream_buffer); +} + +static int send_current_tag(mailimap * session) +{ + char tag_str[15]; + int r; + + session->imap_tag ++; + snprintf(tag_str, 15, "%i", session->imap_tag); + + r = mailimap_tag_send(session->imap_stream, tag_str); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int parse_response(mailimap * session, + struct mailimap_response ** result) +{ + size_t index; + struct mailimap_response * response; + char tag_str[15]; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_response_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &response, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_response_print(response); +#endif + + response_store(session, response); + + if (mmap_string_assign(session->imap_response_buffer, + response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text) + == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL) + return MAILIMAP_ERROR_FATAL; + + snprintf(tag_str, 15, "%i", session->imap_tag); + if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0) + return MAILIMAP_ERROR_PROTOCOL; + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type == + MAILIMAP_RESP_COND_STATE_BAD) + return MAILIMAP_ERROR_PROTOCOL; + + * result = response; + + return MAILIMAP_NO_ERROR; +} + + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result) +{ + size_t index; + struct mailimap_greeting * greeting; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_greeting_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &greeting, session->imap_progr_rate, + session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_greeting_print(greeting); +#endif + + greeting_store(session, greeting); + + if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) { + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION; + } + + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + * result = greeting; + + return MAILIMAP_NO_ERROR; +} + + +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun) +{ + mailimap * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->imap_response = NULL; + + f->imap_stream = NULL; + + f->imap_progr_rate = imap_progr_rate; + f->imap_progr_fun = imap_progr_fun; + + f->imap_stream_buffer = mmap_string_new(""); + if (f->imap_stream_buffer == NULL) + goto free_f; + + f->imap_response_buffer = mmap_string_new(""); + if (f->imap_response_buffer == NULL) + goto free_stream_buffer; + + f->imap_state = MAILIMAP_STATE_DISCONNECTED; + f->imap_tag = 0; + + f->imap_selection_info = NULL; + f->imap_response_info = NULL; + f->imap_connection_info = NULL; + + return f; + + free_stream_buffer: + mmap_string_free(f->imap_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +void mailimap_free(mailimap * session) +{ + if (session->imap_stream) + mailimap_logout(session); + + mmap_string_free(session->imap_response_buffer); + mmap_string_free(session->imap_stream_buffer); + + if (session->imap_response_info) + mailimap_response_info_free(session->imap_response_info); + if (session->imap_selection_info) + mailimap_selection_info_free(session->imap_selection_info); + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + + free(session); +} diff --git a/kmicromail/libetpan/imap/mailimap.h b/kmicromail/libetpan/imap/mailimap.h new file mode 100644 index 0000000..8dfa3d4 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap.h @@ -0,0 +1,598 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +void mailimap_free(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_helper.c b/kmicromail/libetpan/imap/mailimap_helper.c new file mode 100644 index 0000000..afc9098 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_helper.c @@ -0,0 +1,205 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_helper.h" + +#include +#include "mailimap.h" + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + int res; + + fetch_att = mailimap_fetch_att_new_rfc822(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + * result = item->att_data.att_static->att_data.att_rfc822.att_content; + item->att_data.att_static->att_data.att_rfc822.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + int res; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + + fetch_att = mailimap_fetch_att_new_rfc822_header(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822_HEADER) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + * result = item->att_data.att_static->att_data.att_rfc822_header.att_content; + item->att_data.att_static->att_data.att_rfc822_header.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + + fetch_att = mailimap_fetch_att_new_envelope(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_interval(first, last); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = fetch_list; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_append_simple(mailimap * session, char * mailbox, + char * content, uint32_t size) +{ + return mailimap_append(session, mailbox, NULL, NULL, content, size); +} + +int mailimap_login_simple(mailimap * session, + char * userid, char * password) +{ + if (session->imap_state == MAILIMAP_STATE_NON_AUTHENTICATED) + return mailimap_login(session, userid, password); + else + return MAILIMAP_NO_ERROR; +} + diff --git a/kmicromail/libetpan/imap/mailimap_helper.h b/kmicromail/libetpan/imap/mailimap_helper.h new file mode 100644 index 0000000..d73cf5f --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_helper.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +int mailimap_append_simple(mailimap * session, char * mailbox, + char * content, uint32_t size); + +int mailimap_login_simple(mailimap * session, + char * userid, char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_keywords.c b/kmicromail/libetpan/imap/mailimap_keywords.c new file mode 100644 index 0000000..b277aed --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_keywords.c @@ -0,0 +1,353 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_keywords.h" +#include "mailimap_types.h" +#include +#include + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +struct mailimap_token_value { + int value; + const char * str; +}; + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token) +{ + int len; + int cur_token; + int r; + + cur_token = * index; + len = strlen(token); + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + if (strncasecmp(buffer->str + cur_token, token, len) == 0) { + cur_token += len; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +static int is_space_or_tab(char ch) +{ + return (ch == ' ') || (ch == '\t'); +} + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token) +{ + int cur_token; + + cur_token = * index; + + if (buffer->str[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ +#ifdef UNSTRICT_SYNTAX + + /* can accept unstrict syntax */ + size_t cur_token; + + cur_token = * index; + + while (is_space_or_tab(* (buffer->str + cur_token))) + cur_token ++; + + if (cur_token == * index) + return MAILIMAP_ERROR_PARSE; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +#else + return mailimap_char_parse(fd, buffer, index, ' '); +#endif +} + + + +#define mailimap_get_token_str(index, tab) \ + mailimap_get_token_str_size(index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + +#define mailimap_get_token_value(fd, buffer, index, tab) \ + mailimap_get_token_value_size(fd, buffer, index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + + +static const char * mailimap_get_token_str_size(int index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + + for(i = 0 ; i < size ; i++) + if (index == tab[i].value) + return tab[i].str; + + return NULL; +} + + + +static int mailimap_get_token_value_size(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + for(i = 0 ; i < size ; i++) { + r = mailimap_token_case_insensitive_parse(fd, buffer, index, tab[i].str); + if (r == MAILIMAP_NO_ERROR) + return tab[i].value; + } + + return -1; +} + + +static struct mailimap_token_value status_att_tab[] = { + {MAILIMAP_STATUS_ATT_MESSAGES, "MESSAGES"}, + {MAILIMAP_STATUS_ATT_RECENT, "RECENT"}, + {MAILIMAP_STATUS_ATT_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_STATUS_ATT_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_STATUS_ATT_UNSEEN, "UNSEEN"} +}; + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + return mailimap_get_token_value(fd, buffer, index, + status_att_tab); +} + + +const char * mailimap_status_att_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, status_att_tab); +} + +static struct mailimap_token_value month_tab[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"} +}; + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, month_tab); +} + + +const char * mailimap_month_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, month_tab); +} + + + + + +static struct mailimap_token_value mailimap_flag_tab[] = { + {MAILIMAP_FLAG_ANSWERED, "\\Answered"}, + {MAILIMAP_FLAG_FLAGGED, "\\Flagged"}, + {MAILIMAP_FLAG_DELETED, "\\Deleted"}, + {MAILIMAP_FLAG_SEEN, "\\Seen"}, + {MAILIMAP_FLAG_DRAFT, "\\Draft"} +}; + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, + mailimap_flag_tab); +} + + +const char * mailimap_flag_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, mailimap_flag_tab); +} + + + + +static struct mailimap_token_value encoding_tab[] = { + {MAILIMAP_BODY_FLD_ENC_7BIT, "7BIT"}, + {MAILIMAP_BODY_FLD_ENC_8BIT, "8BIT"}, + {MAILIMAP_BODY_FLD_ENC_BINARY, "BINARY"}, + {MAILIMAP_BODY_FLD_ENC_BASE64, "BASE64"}, + {MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, "QUOTED-PRINTABLE"} +}; + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, encoding_tab); +} + +static struct mailimap_token_value mbx_list_sflag_tab[] = { + {MAILIMAP_MBX_LIST_SFLAG_MARKED, "\\Marked"}, + {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "\\Noselect"}, + {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "\\Unmarked"} +}; + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, mbx_list_sflag_tab); +} + +static struct mailimap_token_value media_basic_tab[] = { + {MAILIMAP_MEDIA_BASIC_APPLICATION, "APPLICATION"}, + {MAILIMAP_MEDIA_BASIC_AUDIO, "AUDIO"}, + {MAILIMAP_MEDIA_BASIC_IMAGE, "IMAGE"}, + {MAILIMAP_MEDIA_BASIC_MESSAGE, "MESSAGE"}, + {MAILIMAP_MEDIA_BASIC_VIDEO, "VIDEO"} +}; + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, media_basic_tab); +} + +static struct mailimap_token_value resp_cond_state_tab[] = { + {MAILIMAP_RESP_COND_STATE_OK, "OK"}, + {MAILIMAP_RESP_COND_STATE_NO, "NO"}, + {MAILIMAP_RESP_COND_STATE_BAD, "BAD"} +}; + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_cond_state_tab); +} + +static struct mailimap_token_value resp_text_code_1_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_ALERT, "ALERT"}, + {MAILIMAP_RESP_TEXT_CODE_PARSE, "PARSE"}, + {MAILIMAP_RESP_TEXT_CODE_READ_ONLY, "READ-ONLY"}, + {MAILIMAP_RESP_TEXT_CODE_READ_WRITE, "READ-WRITE"}, + {MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, "TRYCREATE"} +}; + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_1_tab); +} + +static struct mailimap_token_value resp_text_code_2_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_RESP_TEXT_CODE_UNSEEN, "UNSEEN"}, +}; + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_2_tab); +} + +static struct mailimap_token_value section_msgtext_tab[] = { + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, "HEADER.FIELDS.NOT"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, "HEADER.FIELDS"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER, "HEADER"}, + {MAILIMAP_SECTION_MSGTEXT_TEXT, "TEXT"} +}; + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, section_msgtext_tab); +} diff --git a/kmicromail/libetpan/imap/mailimap_keywords.h b/kmicromail/libetpan/imap/mailimap_keywords.h new file mode 100644 index 0000000..a8443aa --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_keywords.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_COMMON_H + +#define MAILIMAP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + + +/* tools */ + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token); + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +/* tokens */ + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token); + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_status_att_get_token_str(size_t index); + + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_month_get_token_str(size_t index); + + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +const char * mailimap_flag_get_token_str(size_t index); + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_parser.c b/kmicromail/libetpan/imap/mailimap_parser.c new file mode 100644 index 0000000..1c2ecde --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_parser.c @@ -0,0 +1,9506 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include +#include +#include + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mmapstring.h" +#include "mail.h" + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +/* + Document: internet-drafts/draft-crispin-imapv-15.txt + RFC 2060 (IMAP but rather used draft) + RFC 2234 for all token that are not defined such as ALPHA +*/ + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result); + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result); + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * index, + gint * result); +*/ +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + int * result); + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +/* +struct mailimap_date_text { + gint day; + gint month; + gint year; +}; + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, + guint32 * index, struct mailimap_date_text ** result); +static void mailimap_date_text_free(struct mailimap_date_text * date_text); +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** t, + size_t progr_rate, + progress_function * progr_fun); + +#ifndef UNSTRICT_SYNTAX +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); +#endif + + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result); + + +static int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_message_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + + +static int +mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + +static int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result); + + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result); + + + + + +static int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +static int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * phour, int * pmin, int * psec); + +static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +/* ******************** TOOLS **************************** */ + + +static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token) +{ + size_t cur_token; + int r; + + cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + + mailimap_space_parse(fd, buffer, &cur_token); + if (token == ' ') { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + r = mailimap_char_parse(fd, buffer, &cur_token, token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '('); +} + +static int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ')'); +} + +static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '{'); +} + +static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '}'); +} + +static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '+'); +} + +static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '-'); +} + +static int mailimap_star_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '*'); +} + +static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '.'); +} + +static int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ':'); +} + +static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '<'); +} + +static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '>'); +} + +static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '['); +} + +static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ']'); +} + +static int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_char_parse(fd, buffer, index, '\"'); +} + +static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + size_t cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + if (mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n")) { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + +#ifdef UNSTRICT_SYNTAX + else if (mailimap_unstrict_char_parse(fd, buffer, &cur_token, '\n')) { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + else + return MAILIMAP_ERROR_PARSE; +} + +typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer, + size_t * index, void * result, + size_t progr_rate, + progress_function * progr_fun); +typedef int mailimap_struct_destructor(void * result); + + +static int +mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * index; + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + while (1) { + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + } + + * result = struct_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * index; + struct_list = NULL; + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimap_unstrict_char_parse(fd, buffer, &cur_token, symbol); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + + * result = struct_list; + * index = final_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_struct_list_parse(fd, buffer, index, result, + ' ', parser, destructor, + progr_rate, progr_fun); +} + + + +static int +mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &begin); +#endif + + end = begin; + + while (is_custom_char(buffer->str[end])) + end ++; + + if (end != begin) { + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * index = end; + * result = gstr; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + + +static int +mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + uint32_t number; + uint32_t * number_alloc; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + number_alloc = mailimap_number_alloc_new(number); + if (number_alloc == NULL) + return MAILIMAP_ERROR_MEMORY; + + * index = cur_token; + * result = number_alloc; + + return MAILIMAP_NO_ERROR; +} + + +static int is_ctl(char ch) +{ + unsigned char uch = (unsigned char) ch; + + return (uch <= 0x1F); +} + +static int is_char(char ch) +{ +#ifdef UNSTRICT_SYNTAX + return (ch != 0); +#else + unsigned char uch = ch; + + return (uch >= 0x01) && (uch <= 0x7f); +#endif +} + +static int is_alpha(char ch) +{ + return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z'))); +} + +static int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_digit(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +/* ******************** parser **************************** */ + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" +*/ + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * addr_name; + char * addr_adl; + char * addr_mailbox; + char * addr_host; + struct mailimap_address * addr; + int r; + int res; + + cur_token = * index; + + addr_name = NULL; + addr_adl = NULL; + addr_mailbox = NULL; + addr_host = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_addr_name_parse(fd, buffer, &cur_token, &addr_name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_addr_adl_parse(fd, buffer, &cur_token, &addr_adl, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_addr_mailbox_parse(fd, buffer, &cur_token, &addr_mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_addr_host_parse(fd, buffer, &cur_token, &addr_host, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_host_free; + } + + addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host); + + if (addr == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto addr_host_free; + } + + * result = addr; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + addr_host_free: + mailimap_addr_host_free(addr_host); + addr_mailbox_free: + mailimap_addr_mailbox_free(addr_mailbox); + addr_adl_free: + mailimap_addr_adl_free(addr_adl); + addr_name_free: + mailimap_addr_name_free(addr_name); + err: + return res; +} + +/* + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL +*/ + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name +*/ + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + */ + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + NOT IMPLEMENTED + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +/* + astring = 1*ASTRING-CHAR / string +*/ + +static int is_astring_char(char ch); + +static int +mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_astring_char); +} + +static int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * astring; + int r; + + cur_token = * index; + + r = mailimap_atom_astring_parse(fd, buffer, &cur_token, &astring, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_string_parse(fd, buffer, &cur_token, &astring, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + + default: + return r; + } + + * result = astring; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom_char(char ch); +static int is_resp_specials(char ch); + +static int is_astring_char(char ch) +{ + if (is_atom_char(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + return FALSE; +} + +/* + atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_atom_char); +} + +/* + ATOM-CHAR = +*/ + +static int is_atom_specials(char ch); + +static int is_atom_char(char ch) +{ + if (is_atom_specials(ch)) + return FALSE; + + return is_char(ch); +} + +/* + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + +no "}" because there is no need (Mark Crispin) +*/ + +static int is_quoted_specials(char ch); +static int is_list_wildcards(char ch); + +static int is_atom_specials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '{': + case ' ': + return TRUE; + }; + if (is_ctl(ch)) + return TRUE; + if (is_list_wildcards(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + + return is_quoted_specials(ch); +} + +/* + NOT IMPLEMENTED + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +/* + auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_atom_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + base64 = *(4base64-char) [base64-terminal] +*/ + +static int is_base64_4char(char * str); +static int is_base64_terminal(char * str); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + end = begin; + + while (is_base64_4char(buffer->str + end)) + end += 4; + if (is_base64_terminal(buffer->str + end)) + end += 4; + else + return MAILIMAP_ERROR_PARSE; + + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * result = gstr; + * index = end; + + return MAILIMAP_NO_ERROR; +} + +/* + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive +*/ + +static int is_base64_char(char ch) +{ + return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/'); +} + +static int is_base64_4char(char * str) +{ + size_t i; + + for (i = 0 ; i < 4 ; i++) + if (!is_base64_char(str[i])) + return FALSE; + return TRUE; +} + +/* + base64-terminal = (2base64-char "==") / (3base64-char "=") +*/ + +static int is_base64_terminal(char * str) +{ + if (str[0] == 0) + return FALSE; + if (str[1] == 0) + return FALSE; + if (str[2] == 0) + return FALSE; + if (str[3] == 0) + return FALSE; + + if (is_base64_char(str[0]) || is_base64_char(str[1]) + || str[2] == '=' || str[3] == '=') + return TRUE; + if (is_base64_char(str[0]) || is_base64_char(str[1]) + || is_base64_char(str[2]) || str[3] == '=') + return TRUE; + return FALSE; +} + + +/* + body = "(" (body-type-1part / body-type-mpart) ")" +*/ + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_mpart * body_type_mpart; + struct mailimap_body * body; + size_t cur_token; + int type; + int r; + int res; + + cur_token = * index; + + body_type_1part = NULL; + body_type_mpart = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_1PART; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token, + &body_type_mpart, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_MPART; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + body = mailimap_body_new(type, body_type_1part, body_type_mpart); + if (body == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_1part) + mailimap_body_type_1part_free(body_type_1part); + if (body_type_mpart) + mailimap_body_type_mpart_free(body_type_mpart); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +/* + "(" body-extension *(SP body-extension) ")" +*/ + +static int +mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &list, + (mailimap_struct_parser * ) + mailimap_body_extension_parse, + (mailimap_struct_destructor * ) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + char * nstring; + clist * body_extension_list; + struct mailimap_body_extension * body_extension; + int type; + int r; + int res; + + cur_token = * index; + + nstring = NULL; + number = 0; + body_extension_list = NULL; + type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NSTRING; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NUMBER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_ext_list_parse(fd, buffer, &cur_token, + &body_extension_list, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + body_extension = mailimap_body_extension_new(type, nstring, number, + body_extension_list); + + if (body_extension == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body_extension; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (nstring != NULL) + mailimap_nstring_free(nstring); + if (body_extension_list) { + clist_foreach(body_extension_list, + (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_extension_list); + } + err: + return res; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +/* + *(SP body-extension) +*/ + +static int +mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + body_ext_list, + (mailimap_struct_parser *) + mailimap_body_extension_parse, + (mailimap_struct_destructor *) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** fld_lang, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * fld_lang = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token, + body_ext_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** fld_dsp, + struct mailimap_body_fld_lang ** fld_lang, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * fld_dsp = NULL; + * fld_lang = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token, + fld_lang, body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + char * fld_md5; + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + clist * body_ext_list; + int r; + int res; + + struct mailimap_body_ext_1part * ext_1part; + + cur_token = * index; + + fld_md5 = NULL; + fld_dsp = NULL; + fld_lang = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, + &fld_dsp, + &fld_lang, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang, + body_ext_list); + + if (ext_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_1part; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + mailimap_body_fld_md5_free(fld_md5); + err: + return res; +} + + +/* + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + struct mailimap_body_fld_param * fld_param; + clist * body_ext_list; + + struct mailimap_body_ext_mpart * ext_mpart; + int r; + int res; + + cur_token = * index; + + fld_param = NULL; + fld_dsp = NULL; + fld_lang = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, + &fld_dsp, + &fld_lang, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang, + body_ext_list); + if (ext_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_mpart; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + if (fld_param != NULL) + mailimap_body_fld_param_free(fld_param); + err: + return res; +} + +/* + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets +*/ + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + size_t cur_token; + struct mailimap_body_fld_param * body_fld_param; + char * body_fld_id; + char * body_fld_desc; + struct mailimap_body_fld_enc * body_fld_enc; + size_t body_fld_octets; + int r; + int res; + + body_fld_param = NULL; + body_fld_id = NULL; + body_fld_desc = NULL; + body_fld_enc = NULL; + body_fld_octets = 0; + + cur_token = * index; + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token, + &body_fld_octets); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + body_fields = mailimap_body_fields_new(body_fld_param, + body_fld_id, + body_fld_desc, + body_fld_enc, + body_fld_octets); + if (body_fields == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_enc_free; + } + + * result = body_fields; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + fld_enc_free: + mailimap_body_fld_enc_free(body_fld_enc); + fld_desc_free: + mailimap_body_fld_desc_free(body_fld_desc); + fld_id_free: + mailimap_body_fld_id_free(body_fld_id); + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + err: + return res; +} + +/* + body-fld-desc = nstring +*/ + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-dsp = "(" string SP body-fld-param ")" / nil +*/ + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + struct mailimap_body_fld_param * body_fld_param; + struct mailimap_body_fld_dsp * body_fld_dsp; + int res; + int r; + + cur_token = * index; + name = NULL; + body_fld_param = NULL; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, + &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param); + if (body_fld_dsp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_param_free; + } + + * index = cur_token; + * result = body_fld_dsp; + + return MAILIMAP_NO_ERROR; + + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + string_free: + mailimap_string_free(name); + err: + return res; +} + +/* + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string +*/ + +static inline int +mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + int r; + int res; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); + + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + err: + return res; +} + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * value; + struct mailimap_body_fld_enc * body_fld_enc; + int r; + int res; + + cur_token = * index; + + r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token, + &type, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + value = NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + type = MAILIMAP_BODY_FLD_ENC_OTHER; + + r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + else { + res = r; + goto err; + } + + body_fld_enc = mailimap_body_fld_enc_new(type, value); + if (body_fld_enc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto value_free; + } + + * result = body_fld_enc; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + value_free: + if (value) + mailimap_string_free(value); + err: + return res; +} + +/* + body-fld-id = nstring +*/ + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +/* +"(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + char * elt; + + r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + mailimap_string_free(elt); + res = r; + goto list_free; + } + } + else { + res = r; + goto list_free; + } + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto list_free; + } + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + list_free: + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * value; + clist * list; + struct mailimap_body_fld_lang * fld_lang; + int type; + int r; + int res; + + size_t cur_token; + + cur_token = * index; + + value = NULL; + list = NULL; + type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_SINGLE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + fld_lang = mailimap_body_fld_lang_new(type, value, list); + if (fld_lang == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = fld_lang; + + return MAILIMAP_NO_ERROR; + + free: + if (value) + mailimap_nstring_free(value); + if (list) { + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + body-fld-lines = number +*/ + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result) +{ + return mailimap_number_parse(fd, buffer, index, result); +} + +/* + body-fld-md5 = nstring +*/ + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-octets = number +*/ + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result) +{ + return mailimap_number_parse(fd, buffer, index, result); +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +/* + string SP string +*/ + +static int +mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_single_body_fld_param ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_single_body_fld_param * param; + char * name; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + name = NULL; + value = NULL; + + r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + param = mailimap_single_body_fld_param_new(name, value); + if (param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = param; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + mailimap_string_free(name); + free_name: + mailimap_string_free(value); + err: + return res; +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * param_list; + struct mailimap_body_fld_param * fld_param; + int r; + int res; + + param_list = NULL; + cur_token = * index; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, ¶m_list, + (mailimap_struct_parser *) + mailimap_single_body_fld_param_parse, + (mailimap_struct_destructor *) + mailimap_single_body_fld_param_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + fld_param = mailimap_body_fld_param_new(param_list); + if (fld_param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = fld_param; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(param_list, + (clist_func) mailimap_single_body_fld_param_free, + NULL); + clist_free(param_list); + err: + return res; +} + +/* + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] +*/ + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_body_type_msg * body_type_msg; + struct mailimap_body_type_text * body_type_text; + struct mailimap_body_ext_1part * body_ext_1part; + int type; + size_t final_token; + int r; + int res; + + cur_token = * index; + + body_type_basic = NULL; + body_type_msg = NULL; + body_type_text = NULL; + body_ext_1part = NULL; + + type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_msg_parse(fd, buffer, &cur_token, + &body_type_msg, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_MSG; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_text_parse(fd, buffer, &cur_token, + &body_type_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_basic_parse(fd, buffer, &cur_token, + &body_type_basic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_BASIC; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + body_ext_1part = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + body_type_1part = mailimap_body_type_1part_new(type, body_type_basic, + body_type_msg, body_type_text, + body_ext_1part); + if (body_type_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = final_token; + * result = body_type_1part; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_basic) + mailimap_body_type_basic_free(body_type_basic); + if (body_type_msg) + mailimap_body_type_msg_free(body_type_msg); + if (body_type_text) + mailimap_body_type_text_free(body_type_text); + if (body_ext_1part) + mailimap_body_ext_1part_free(body_ext_1part); + err: + return res; +} + +/* + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" +*/ + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_media_basic * media_basic; + struct mailimap_body_fields * body_fields; + int r; + int res; + + cur_token = * index; + + media_basic = NULL; + body_fields = NULL; + + r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields); + if (body_type_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * index = cur_token; + * result = body_type_basic; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_basic: + mailimap_media_basic_free(media_basic); + err: + return res; +} + +/* + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] +*/ + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_mpart * body_type_mpart; + clist * body_list; + size_t cur_token; + size_t final_token; + char * media_subtype; + struct mailimap_body_ext_mpart * body_ext_mpart; + int r; + int res; + + cur_token = * index; + + body_list = NULL; + media_subtype = NULL; + body_ext_mpart = NULL; + + r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, + &body_list, + (mailimap_struct_parser *) + mailimap_body_parse, + (mailimap_struct_destructor *) + mailimap_body_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + + final_token = cur_token; + + body_ext_mpart = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + + body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype, + body_ext_mpart); + if (body_type_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_ext_mpart; + } + + * result = body_type_mpart; + * index = final_token; + + return MAILIMAP_NO_ERROR; + + free_body_ext_mpart: + if (body_ext_mpart) + mailimap_body_ext_mpart_free(body_ext_mpart); + mailimap_media_subtype_free(media_subtype); + free_body_list: + clist_foreach(body_list, (clist_func) mailimap_body_free, NULL); + clist_free(body_list); + err: + return res; +} + +/* + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines +*/ + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + struct mailimap_envelope * envelope; + struct mailimap_body * body; + uint32_t body_fld_lines; + struct mailimap_body_type_msg * body_type_msg; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + body_fields = NULL; + envelope = NULL; + body = NULL; + body_fld_lines = 0; + + r = mailimap_media_message_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, + &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + body_type_msg = mailimap_body_type_msg_new(body_fields, envelope, + body, body_fld_lines); + if (body_type_msg == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto body; + } + + * result = body_type_msg; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + body: + mailimap_body_free(body); + envelope: + mailimap_envelope_free(envelope); + body_fields: + mailimap_body_fields_free(body_fields); + err: + return res; +} + +/* + body-type-text = media-text SP body-fields SP body-fld-lines +*/ + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * media_text; + struct mailimap_body_fields * body_fields; + uint32_t body_fld_lines; + struct mailimap_body_type_text * body_type_text; + size_t cur_token; + int r; + int res; + + media_text = NULL; + body_fields = NULL; + body_fld_lines = 0; + + cur_token = * index; + + r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + body_type_text = mailimap_body_type_text_new(media_text, body_fields, + body_fld_lines); + if (body_type_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * result = body_type_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_text: + mailimap_media_text_free(media_text); + err: + return res; +} + + +/* + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track +*/ + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * auth_type; + char * atom; + struct mailimap_capability * cap; + int r; + int res; + + cur_token = * index; + + auth_type = NULL; + atom = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH="); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_CAPABILITY_AUTH_TYPE; + + r = mailimap_auth_type_parse(fd, buffer, &cur_token, &auth_type, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_CAPABILITY_NAME; + break; + + default: + res = r; + goto err; + } + + cap = mailimap_capability_new(type, auth_type, atom); + if (cap == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cap; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (auth_type) + mailimap_auth_type_free(auth_type); + if (atom) + mailimap_atom_free(atom); + err: + return res; +} + +/* + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. +*/ + +/* + SP capability *(SP capability) +*/ + +static int mailimap_capability_list_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_capability_parse, + (mailimap_struct_destructor *) + mailimap_capability_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * cap_list; +#if 0 + clist * cap_list_2; +#endif + struct mailimap_capability_data * cap_data; + int r; + int res; + + cur_token = * index; + + cap_list = NULL; +#if 0 + cap_list_2 = NULL; +#endif + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_capability_list_parse(fd, buffer, &cur_token, + &cap_list, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + +#if 0 + if (!mailimap_space_parse(fd, buffer, &cur_token)) { + res = r; + goto free_list; + } + + if (!mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "IMAP4rev1")) + goto free_list; + + r = mailimap_capability_list_parse(fd, buffer, &cur_token, + &cap_list_2, + progr_rate, progr_fun); + + cap_list = g_list_concat(cap_list, cap_list_2); +#endif + + cap_data = mailimap_capability_data_new(cap_list); + if (cap_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = cap_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + if (cap_list) { + clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL); + clist_free(cap_list); + } + err: + return res; +} + +/* + UNIMPLEMENTED BECAUSE UNUSED (only in literal) + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +static gboolean is_char8(gchar ch) +{ + return (ch != 0x00); +} +*/ + + +/* +UNIMPLEMENTED + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +UNIMPLEMENTED + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +/* +UNIMPLEMENTED + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +UNIMPLEMENTED + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +UNIMPLEMENTED + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text * resp_text; + size_t cur_token; + struct mailimap_continue_req * cont_req; + char * base64; + int type; + int r; + int res; + + cur_token = * index; + + r = mailimap_plus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + resp_text = NULL; + base64 = NULL; + + type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_base64_parse(fd, buffer, &cur_token, &base64, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_CONTINUE_REQ_BASE64; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &resp_text, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_CONTINUE_REQ_TEXT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + cont_req = mailimap_continue_req_new(type, resp_text, base64); + if (cont_req == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cont_req; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (base64 != NULL) + mailimap_base64_free(base64); + if (resp_text != NULL) + mailimap_resp_text_free(resp_text); + err: + return res; +} + +/* + UNIMPLEMENTED + copy = "COPY" SP set SP mailbox +*/ + +/* + UNIMPLEMENTED + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + UNIMPLEMENTED + date = date-text / DQUOTE date-text DQUOTE +*/ + +/* + UNIMPLEMENTED + date-day = 1*2DIGIT + ; Day of month +*/ + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * index, + gint * result) +{ + guint32 cur_token; + gint digit; + gint number; + + cur_token = * index; + + if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + return FALSE; + + number = digit; + + if (mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + number = number * 10 + digit; + + * result = number; + * index = cur_token; + + return TRUE; +} +*/ + +/* + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + int * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t day; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = day; + + return MAILIMAP_NO_ERROR; + +#else + size_t cur_token; + int r; + + cur_token = * index; + + if (mailimap_space_parse(fd, buffer, &cur_token)) { + int digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } + else { + int digit1; + int digit2; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit1 * 10 + digit2; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } +#endif +} + + +/* + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + int month; + + cur_token = * index; + + month = mailimap_month_get_token_value(fd, buffer, &cur_token); + if (month == -1) + return MAILIMAP_ERROR_PARSE; + + * result = month; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + date-text = date-day "-" date-month "-" date-year +*/ + +/* +static struct mailimap_date_text * +mailimap_date_text_new(gint day, gint month, gint year) +{ + struct mailimap_date_text * date_text; + + date_text = g_new(struct mailimap_date_text, 1); + if (date_text == NULL) + return NULL; + + date_text->day = day; + date_text->month = month; + date_text->year = year; + + return date_text; +} + +static void mailimap_date_text_free(struct mailimap_date_text * date_text) +{ + g_free(date_text); +} + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, + guint32 * index, struct mailimap_date_text ** result) +{ + struct mailimap_date_text * date_text; + gint day; + gint month; + gint year; + guint32 cur_token; + + cur_token = * index; + + if (!mailimap_date_day_parse(fd, buffer, &cur_token, &day)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, &cur_token)) + return FALSE; + + if (!mailimap_date_month_parse(fd, buffer, &cur_token, &month)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, &cur_token)) + return FALSE; + + if (!mailimap_date_year_parse(fd, buffer, &cur_token, &year)) + return FALSE; + + date_text = mailimap_date_text_new(day, month, year); + if (date_text == NULL) + return FALSE; + + * result = date_text; + * index = cur_token; + + return TRUE; +} +*/ + +/* + date-year = 4DIGIT +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ +#ifdef UNSTRICT_SYNTAX + uint32_t year; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = year; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#else + int i; + size_t cur_token; + int year; + int digit; + int r; + + cur_token = * index; + year = 0; + + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + year = year * 10 + digit; + } + + * result = year; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int day; + int month; + int year; + int hour; + int min; + int sec; + struct mailimap_date_time * date_time; + size_t cur_token; + int zone; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_parse(fd, buffer, &cur_token, &month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_parse(fd, buffer, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_time_parse(fd, buffer, &cur_token, &hour, &min, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_zone_parse(fd, buffer, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = date_time; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + digit-nz = %x31-39 + ; 1-9 +*/ + +#ifndef UNSTRICT_SYNTAX +static int is_digit_nz(char ch) +{ + return (ch >= '1') && (ch <= '9'); +} + +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_digit_nz(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} +#endif + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" +*/ + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * date; + char * subject; + struct mailimap_env_from * from; + struct mailimap_env_sender * sender; + struct mailimap_env_reply_to * reply_to; + struct mailimap_env_to * to; + struct mailimap_env_cc * cc; + struct mailimap_env_bcc * bcc; + char * in_reply_to; + char * message_id; + struct mailimap_envelope * envelope; + int r; + int res; + + date = NULL; + subject = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + in_reply_to = NULL; + message_id = NULL; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_env_date_parse(fd, buffer, &cur_token, &date, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_env_subject_parse(fd, buffer, &cur_token, &subject, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_env_from_parse(fd, buffer, &cur_token, &from, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_env_sender_parse(fd, buffer, &cur_token, &sender, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_env_reply_to_parse(fd, buffer, &cur_token, &reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_env_to_parse(fd, buffer, &cur_token, &to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_env_cc_parse(fd, buffer, &cur_token, &cc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_env_bcc_parse(fd, buffer, &cur_token, &bcc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_env_in_reply_to_parse(fd, buffer, &cur_token, &in_reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_env_message_id_parse(fd, buffer, &cur_token, &message_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto message_id; + } + + envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to, + cc, bcc, in_reply_to, message_id); + if (envelope == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto message_id; + } + + * result = envelope; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + message_id: + mailimap_env_message_id_free(message_id); + in_reply_to: + mailimap_env_in_reply_to_free(in_reply_to); + bcc: + mailimap_env_bcc_free(bcc); + cc: + mailimap_env_cc_free(cc); + to: + mailimap_env_to_free(to); + reply_to: + mailimap_env_reply_to_free(reply_to); + sender: + mailimap_env_sender_free(sender); + from: + mailimap_env_from_free(from); + subject: + mailimap_env_subject_free(date); + date: + mailimap_env_date_free(date); + err: + return res; +} + +/* + "(" 1*address ")" +*/ + +static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * address_list; + int r; + int res; + + cur_token = * index; + + address_list = NULL; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + address_list = NULL; + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &address_list, + (mailimap_struct_parser *) + mailimap_address_parse, + (mailimap_struct_destructor *) + mailimap_address_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto address_list; + } + + break; + + default: + res = r; + goto err; + } + + * result = address_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + address_list: + if (address_list) { + clist_foreach(address_list, (clist_func) mailimap_address_free, NULL); + clist_free(address_list); + } + err: + return res; +} + +/* + env-bcc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_bcc * env_bcc; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_bcc = mailimap_env_bcc_new(list); + if (env_bcc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_bcc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-cc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_cc * env_cc; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_cc = mailimap_env_cc_new(list); + if (env_cc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_cc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-date = nstring +*/ + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-from = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_from * env_from; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_from = mailimap_env_from_new(list); + if (env_from == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_from; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-in-reply-to = nstring +*/ + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-message-id = nstring +*/ + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-reply-to = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_reply_to * env_reply_to; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_reply_to = mailimap_env_reply_to_new(list); + if (env_reply_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_reply_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-sender = "(" 1*address ")" / nil +*/ + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_sender * env_sender; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_sender = mailimap_env_sender_new(list); + if (env_sender == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_sender; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + env-subject = nstring +*/ + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + env-to = "(" 1*address ")" / nil +*/ + +static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_to * env_to; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_to = mailimap_env_to_new(list); + if (env_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + UNIMPLEMENTED + examine = "EXAMINE" SP mailbox +*/ + +/* + UNIMPLEMENTED + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +/* + UNIMPLEMENTED + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +/* + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_flag * flag; + size_t cur_token; + char * flag_keyword; + char * flag_extension; + int type; + int r; + int res; + + cur_token = * index; + + flag_keyword = NULL; + flag_extension = NULL; + + type = mailimap_flag_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + r = mailimap_flag_keyword_parse(fd, buffer, &cur_token, &flag_keyword, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_KEYWORD; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, &cur_token, + &flag_extension, + progr_rate, progr_fun); + type = MAILIMAP_FLAG_EXTENSION; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + flag = mailimap_flag_new(type, flag_keyword, flag_extension); + if (flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_keyword != NULL) + mailimap_flag_keyword_free(flag_keyword); + if (flag_extension != NULL) + mailimap_flag_extension_free(flag_extension); + err: + return res; +} + +/* + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + int r; + + cur_token = * index; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = atom; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag * flag; + struct mailimap_flag_fetch * flag_fetch; + int type; + int r; + int res; + + cur_token = * index; + + flag = NULL; + + type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Recent"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_RECENT; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_OTHER; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_fetch = mailimap_flag_fetch_new(type, flag); + if (flag_fetch == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = flag_fetch; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + flag-keyword = atom +*/ + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_atom_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + struct mailimap_flag_list * flag_list; + int r; + int res; + + list = NULL; + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_flag_parse, + (mailimap_struct_destructor *) + mailimap_flag_free, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + flag_list = mailimap_flag_list_new(list); + if (flag_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + flag-perm = flag / "\*" +*/ + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_perm * flag_perm; + struct mailimap_flag * flag; + int type; + int r; + int res; + + flag = NULL; + cur_token = * index; + type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_FLAG; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "\\*"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_ALL; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_perm = mailimap_flag_perm_new(type, flag); + if (flag_perm == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_perm; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_auth * resp_cond_auth; + struct mailimap_resp_cond_bye * resp_cond_bye; + struct mailimap_greeting * greeting; + int type; + int r; + int res; + + cur_token = * index; + resp_cond_bye = NULL; + resp_cond_auth = NULL; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_auth_parse(fd, buffer, &cur_token, &resp_cond_auth, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_AUTH; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, + &resp_cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_BYE; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye); + if (greeting == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = greeting; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (resp_cond_auth) + mailimap_resp_cond_auth_free(resp_cond_auth); + if (resp_cond_bye) + mailimap_resp_cond_bye_free(resp_cond_bye); + err: + return res; +} + +/* + header-fld-name = astring +*/ + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_header_list * header_list; + clist * list; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_header_fld_name_parse, + (mailimap_struct_destructor *) + mailimap_header_fld_name_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + header_list = mailimap_header_list_new(list); + if (header_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = header_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL); + clist_free(list); + err: + return res; +} + +/* +UNIMPLEMENTED + list = "LIST" SP mailbox SP list-mailbox + +UNIMPLEMENTED + list-mailbox = 1*list-char / string + +UNIMPLEMENTED + list-char = ATOM-CHAR / list-wildcards / resp-specials +*/ + +/* + list-wildcards = "%" / "*" +*/ + +static int is_list_wildcards(char ch) +{ + switch (ch) { + case '%': + case '*': + return TRUE; + } + return FALSE; +} + + +/* + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + MMAPString * literal; + char * literal_p; + uint32_t left; + int r; + int res; + size_t number_token; + + cur_token = * index; + + r = mailimap_oaccolade_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + number_token = cur_token; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_caccolade_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + literal = mmap_string_sized_new(number); + /* + literal = g_new(char, number + 1); + */ + if (literal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + left = buffer->len - cur_token; + + if (left >= number) { + /* + if (number > 0) + strncpy(literal, buffer->str + cur_token, number); + literal[number] = 0; + */ + if (number > 0) + if (mmap_string_append_len(literal, buffer->str + cur_token, + number) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + if ((progr_fun != NULL) && (progr_rate != 0)) + progr_fun(number, number); + + cur_token = cur_token + number; + } + else { + uint32_t needed; + uint32_t current_prog = 0; + uint32_t last_prog = 0; + + needed = number - left; + memcpy(literal->str, buffer->str + cur_token, left); + literal->len += left; + literal_p = literal->str + left; + current_prog = left; + + while (needed > 0) { + ssize_t read_bytes; + + read_bytes = mailstream_read(fd, literal_p, needed); + if (read_bytes == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + literal->len += read_bytes; + needed -= read_bytes; + literal_p += read_bytes; + + current_prog += read_bytes; + if ((progr_fun != NULL) && (progr_rate != 0)) + if (current_prog - last_prog > progr_rate) { + progr_fun(current_prog, number); + last_prog = current_prog; + } + } + + literal->str[number] = 0; + +#if 0 + literal->str[number] = 0; + if (mmap_string_append_len(buffer, literal->str + left, + literal->len - left) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } +#endif + + if (mmap_string_truncate(buffer, number_token) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + if (mmap_string_append(buffer, "0}\r\n") == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + cur_token = number_token + 4; + } + if ((progr_fun != NULL) && (progr_rate != 0)) + progr_fun(number, number); + + if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + + if (mmap_string_ref(literal) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + * result = literal->str; + if (result_len != NULL) + * result_len = literal->len; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_literal: + mmap_string_free(literal); + err: + return res; +} + +/* + UNIMPLEMENTED + login = "LOGIN" SP userid SP password + + UNIMPLEMENTED + lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +static int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + int r; + + cur_token = * index; + + r = mailimap_astring_parse(fd, buffer, &cur_token, &name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = name; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +/* + "FLAGS" SP flag-list +*/ + +static int +mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_list * flag_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_flag_list_parse(fd, buffer, &cur_token, &flag_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = flag_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "LIST" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "LSUB" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "SEARCH" *(SP nz-number) +*/ + + +static int +mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + size_t final_token; + clist * number_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + final_token = cur_token; + number_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &number_list, + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + } + + * result = number_list; + * index = final_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +/* + status-att SP number +*/ + +static int +mailimap_status_info_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_status_info ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int status_att; + uint32_t value; + struct mailimap_status_info * info; + int r; + + cur_token = * index; + value = 0; + + r = mailimap_status_att_parse(fd, buffer, &cur_token, &status_att); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) + return r; + + info = mailimap_status_info_new(status_att, value); + if (info == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = info; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +static int +mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct + mailimap_mailbox_data_status ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mb; + clist * status_info_list; + struct mailimap_mailbox_data_status * data_status; + int r; + int res; + + cur_token = * index; + mb = NULL; + status_info_list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &status_info_list, + (mailimap_struct_parser *) + mailimap_status_info_parse, + (mailimap_struct_destructor *) + mailimap_status_info_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto mailbox; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto status_info_list; + } + + data_status = mailimap_mailbox_data_status_new(mb, status_info_list); + if (data_status == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto status_info_list; + } + + * result = data_status; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + status_info_list: + if (status_info_list != NULL) { + clist_foreach(status_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(status_info_list); + } + mailbox: + mailimap_mailbox_free(mb); + err: + return res; +} + +/* + number SP "EXISTS" +*/ + +static int +mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "RECENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_flag_list * data_flags; + struct mailimap_mailbox_list * data_list; + struct mailimap_mailbox_list * data_lsub; + clist * data_search; + struct mailimap_mailbox_data_status * data_status; + uint32_t data_exists; + uint32_t data_recent; + + struct mailimap_mailbox_data * mailbox_data; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + data_flags = NULL; + data_list = NULL; + data_lsub = NULL; + data_search = NULL; + data_status = NULL; + data_exists = 0; + data_recent = 0; + + type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_mailbox_data_flags_parse(fd, buffer, &cur_token, + &data_flags, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_FLAGS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_list_parse(fd, buffer, &cur_token, + &data_list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LIST; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_lsub_parse(fd, buffer, &cur_token, + &data_lsub, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LSUB; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_search_parse(fd, buffer, &cur_token, + &data_search, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_SEARCH; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_status_parse(fd, buffer, &cur_token, + &data_status, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_STATUS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_exists_parse(fd, buffer, &cur_token, + &data_exists); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_EXISTS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_recent_parse(fd, buffer, &cur_token, + &data_recent); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_RECENT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list, + data_lsub, data_search, + data_status, + data_exists, data_recent); + + if (mailbox_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mailbox_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (data_flags != NULL) + mailimap_flag_list_free(data_flags); + if (data_list != NULL) + mailimap_mailbox_list_free(data_list); + if (data_lsub != NULL) + mailimap_mailbox_list_free(data_lsub); + if (data_search != NULL) + mailimap_mailbox_data_search_free(data_search); + if (data_status != NULL) + mailimap_mailbox_data_status_free(data_status); + err: + return res; +} + +/* + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox +*/ + +/* + DQUOTE QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = ch; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mailbox_list * mb_list; + struct mailimap_mbx_list_flags * mb_flag_list; + char ch; + char * mb; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mb_flag_list = NULL; + ch = 0; + mb = NULL; + + r = mailimap_mbx_list_flags_parse(fd, buffer, &cur_token, + &mb_flag_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + r = mailimap_nil_parse(fd, buffer, &cur_token); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb); + if (mb_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_mailbox; + } + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_mailbox: + mailimap_mailbox_free(mb); + free_list_flags: + if (mb_flag_list != NULL) + mailimap_mbx_list_flags_free(mb_flag_list); + err: + return res; +} + +/* + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) +*/ + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mbx_list_flags * mbx_list_flag; + size_t cur_token; + clist * oflags; + clist * oflags_2; + int sflag; + int type; + int r; + int res; + size_t final_token; + int try_sflag; + + cur_token = * index; + final_token = cur_token; + + oflags = clist_new(); + if (oflags == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR; + oflags_2 = NULL; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &oflags_2, + (mailimap_struct_parser *) + mailimap_mbx_list_oflag_no_sflag_parse, + (mailimap_struct_destructor *) + mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + try_sflag = 1; + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + try_sflag = 0; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + try_sflag = 1; + } + + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + if (try_sflag) { + r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag); + switch (r) { + case MAILIMAP_ERROR_PARSE: + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + break; + + case MAILIMAP_NO_ERROR: + type = MAILIMAP_MBX_LIST_FLAGS_SFLAG; + + final_token = cur_token; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &oflags_2, + (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse, + (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + } + } + + break; + + default: + res = r; + goto free; + } + } + + if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) { + res = MAILIMAP_ERROR_PARSE; + goto free; + } + + cur_token = final_token; + mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag); + if (mbx_list_flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mbx_list_flag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL); + clist_free(oflags); +err: + return res; +} + +/* + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response +*/ + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + size_t cur_token; + struct mailimap_mbx_list_oflag * oflag; + char * flag_ext; + int r; + int res; + int sflag_type; + + cur_token = * index; + flag_ext = NULL; + type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Noinferiors"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, &cur_token, + &flag_ext, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + oflag = mailimap_mbx_list_oflag_new(type, flag_ext); + if (oflag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = oflag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_ext != NULL) + mailimap_flag_extension_free(flag_ext); + err: + return res; +} + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int sflag_type; + int r; + + cur_token = * index; + + r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag_type); + if (r == MAILIMAP_NO_ERROR) + return MAILIMAP_ERROR_PARSE; + + return mailimap_mbx_list_oflag_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + + +/* + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response +*/ + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + int type; + size_t cur_token; + + cur_token = * index; + + type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +/* + DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE +*/ + +static int +mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + size_t cur_token; + int type; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return FALSE; + + * index = cur_token; + * result = type; + + return MAILIMAP_NO_ERROR; +} + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * basic_type; + char * subtype; + struct mailimap_media_basic * media_basic; + int r; + int res; + + cur_token = * index; + + basic_type = NULL; + subtype = NULL; + + r = mailimap_media_basic_standard_parse(fd, buffer, &cur_token, + &type); + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_string_parse(fd, buffer, &cur_token, &basic_type, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MEDIA_BASIC_OTHER; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + media_basic = mailimap_media_basic_new(type, basic_type, subtype); + if (media_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_subtype; + } + + * result = media_basic; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_subtype: + mailimap_media_subtype_free(subtype); + free_basic_type: + if (basic_type != NULL) + mailimap_string_free(basic_type); + err: + return res; +} + + +/* + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "MESSAGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + media-subtype = string + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * media_subtype; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = media_subtype; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) +*/ + + +static int +mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_message_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + int type; + struct mailimap_msg_att * msg_att; + struct mailimap_message_data * msg_data; + int r; + int res; + + cur_token = * index; + msg_att = NULL; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "EXPUNGE"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MESSAGE_DATA_EXPUNGE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "FETCH"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_msg_att_parse(fd, buffer, &cur_token, &msg_att, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_MESSAGE_DATA_FETCH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_data = mailimap_message_data_new(number, type, msg_att); + if (msg_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_msg_att; + } + + * result = msg_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_msg_att: + if (msg_att != NULL) + mailimap_msg_att_free(msg_att); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +/* + msg-att-dynamic / msg-att-static +*/ + +static int +mailimap_msg_att_item_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_item ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_msg_att_dynamic * msg_att_dynamic; + struct mailimap_msg_att_static * msg_att_static; + size_t cur_token; + struct mailimap_msg_att_item * item; + int r; + int res; + + cur_token = * index; + + msg_att_dynamic = NULL; + msg_att_static = NULL; + + type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_dynamic_parse(fd, buffer, &cur_token, + &msg_att_dynamic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_static_parse(fd, buffer, &cur_token, + &msg_att_static, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_STATIC; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static); + if (item == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = item; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (msg_att_dynamic != NULL) + mailimap_msg_att_dynamic_free(msg_att_dynamic); + if (msg_att_static != NULL) + mailimap_msg_att_static_free(msg_att_static); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +static int +mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + struct mailimap_msg_att * msg_att; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_msg_att_item_parse, + (mailimap_struct_destructor *) + mailimap_msg_att_item_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att = mailimap_msg_att_new(list); + if (msg_att == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = msg_att; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(list); + err: + return res; +} + +/* + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message +*/ + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + struct mailimap_msg_att_dynamic * msg_att_dyn; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &list, + (mailimap_struct_parser *) + mailimap_flag_fetch_parse, + (mailimap_struct_destructor *) + mailimap_flag_fetch_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att_dyn = mailimap_msg_att_dynamic_new(list); + if (msg_att_dyn == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_dyn; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +/* + "ENVELOPE" SP envelope +*/ + + +static int +mailimap_msg_att_envelope_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_envelope * env; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ENVELOPE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_envelope_parse(fd, buffer, &cur_token, &env, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = env; + + return MAILIMAP_NO_ERROR; +} + + +/* + "INTERNALDATE" SP date-time +*/ + + +static int +mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_date_time * date_time; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "INTERNALDATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return FALSE; + + r = mailimap_date_time_parse(fd, buffer, &cur_token, &date_time, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = date_time; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_message; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_message, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_message; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".HEADER" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_header; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_header, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_header; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".TEXT" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_text; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_text, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_text; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822.SIZE" SP number +*/ + +static int +mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822.SIZE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" SP body +*/ + + +static int +mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" "STRUCTURE" SP body +*/ + + +static int +mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "STRUCTURE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" section ["<" number ">"] SP nstring +*/ + +static int +mailimap_msg_att_body_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_body_section ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + struct mailimap_section * section; + char * body_part; + struct mailimap_msg_att_body_section * msg_att_body_section; + int r; + int res; + size_t length; + + cur_token = * index; + + section = NULL; + number = 0; + body_part = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_parse(fd, buffer, &cur_token, §ion, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_lower_parse(fd, buffer, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + r = mailimap_greater_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + break; + + case MAILIMAP_ERROR_PARSE: + break; + + default: + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &body_part, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + msg_att_body_section = + mailimap_msg_att_body_section_new(section, number, body_part, length); + if (msg_att_body_section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_string; + } + + * result = msg_att_body_section; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_string: + mailimap_nstring_free(body_part); + free_section: + if (section != NULL) + mailimap_section_free(section); + err: + return res; +} + +/* + "UID" SP uniqueid +*/ + +static int +mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t uid; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uid); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = uid; + + return MAILIMAP_NO_ERROR; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +static int +mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_envelope * env; + struct mailimap_date_time * internal_date; + char * rfc822; + char * rfc822_header; + char * rfc822_text; + uint32_t rfc822_size; + struct mailimap_body * bodystructure; + struct mailimap_body * body; + struct mailimap_msg_att_body_section * body_section; + uint32_t uid; + struct mailimap_msg_att_static * msg_att_static; + int type; + int r; + int res; + size_t length; + + cur_token = * index; + + env = NULL; + internal_date = NULL; + rfc822 = NULL; + rfc822_header = NULL; + rfc822_text = NULL; + rfc822_size = 0; + length = 0; + bodystructure = NULL; + body = NULL; + body_section = NULL; + uid = 0; + + type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_envelope_parse(fd, buffer, &cur_token, &env, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ENVELOPE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_internaldate_parse(fd, buffer, &cur_token, + &internal_date, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_INTERNALDATE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_parse(fd, buffer, &cur_token, + &rfc822, &length, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_header_parse(fd, buffer, &cur_token, + &rfc822_header, &length, + progr_rate, progr_fun); + type = MAILIMAP_MSG_ATT_RFC822_HEADER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_text_parse(fd, buffer, &cur_token, + &rfc822_text, &length, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_size_parse(fd, buffer, &cur_token, + &rfc822_size); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_SIZE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_parse(fd, buffer, &cur_token, + &body, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_bodystructure_parse(fd, buffer, &cur_token, + &bodystructure, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODYSTRUCTURE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_section_parse(fd, buffer, &cur_token, + &body_section, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY_SECTION; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_uid_parse(fd, buffer, &cur_token, + &uid); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_UID; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_att_static = mailimap_msg_att_static_new(type, env, internal_date, + rfc822, rfc822_header, + rfc822_text, length, + rfc822_size, bodystructure, + body, body_section, uid); + if (msg_att_static == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_static; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (env) + mailimap_msg_att_envelope_free(env); + if (internal_date) + mailimap_msg_att_internaldate_free(internal_date); + if (rfc822) + mailimap_msg_att_rfc822_free(rfc822); + if (rfc822_header) + mailimap_msg_att_rfc822_header_free(rfc822_header); + if (rfc822_text) + mailimap_msg_att_rfc822_text_free(rfc822_text); + if (bodystructure) + mailimap_msg_att_bodystructure_free(bodystructure); + if (body) + mailimap_msg_att_body_free(body); + if (body_section) + mailimap_msg_att_body_section_free(body_section); + err: + return res; +} + + +/* + nil = "NIL" +*/ + +static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_token_case_insensitive_parse(fd, buffer, index, "NIL"); +} + +/* + nstring = string / nil +*/ + + +static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_string_parse(fd, buffer, index, result, result_len, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + return MAILIMAP_NO_ERROR; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_nil_parse(fd, buffer, index); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = NULL; + if (result_len != NULL) + * result_len = 0; + return MAILIMAP_NO_ERROR; + + default: + return r; + } +} + +/* + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +static int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * index; + parsed = FALSE; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + number = 0; + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += digit; + parsed = TRUE; + } + else + return r; + } + + if (!parsed) + return MAILIMAP_ERROR_PARSE; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +static int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (number == 0) + return MAILIMAP_ERROR_PARSE; + +#else + size_t cur_token; + int digit; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_digit_nz_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + number = digit; + + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += (guint32) digit; + } + else + return r; + } +#endif + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + password = astring +*/ + +/* + quoted = DQUOTE *QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char ch; + size_t cur_token; + MMAPString * gstr_quoted; + int r; + int res; + + cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + gstr_quoted = mmap_string_new(""); + if (gstr_quoted == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + if (mmap_string_append_c(gstr_quoted, ch) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + else { + res = r; + goto free; + } + } + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + if (mmap_string_ref(gstr_quoted) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = gstr_quoted->str; + + return MAILIMAP_NO_ERROR; + + free: + mmap_string_free(gstr_quoted); + err: + return res; +} + +/* + QUOTED-CHAR = / + "\" quoted-specials +*/ + +static int is_quoted_specials(char ch); + +static int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result) +{ + size_t cur_token; + int r; + + cur_token = * index; + + if (!is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else { + char quoted_special; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quoted_specials_parse(fd, buffer, &cur_token, + "ed_special); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = quoted_special; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } +} + +/* + quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +/* + UNIMPLEMENTED + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +/* + response = *(continue-req / response-data) response-done +*/ + +/* + continue-req / response-data +*/ + +/* static */ int +mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_cont_req_or_resp_data ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + struct mailimap_continue_req * cont_req; + struct mailimap_response_data * resp_data; + int type; + int r; + int res; + + cur_token = * index; + + cont_req = NULL; + resp_data = NULL; + type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_continue_req_parse(fd, buffer, &cur_token, &cont_req, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_CONT_REQ; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_data_parse(fd, buffer, &cur_token, &resp_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_RESP_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + /* + multi-lines response + read another response line because after that token, + there must have something (continue-req, response-data or response-done) + */ + + if (!mailstream_read_line_append(fd, buffer)) { + res = MAILIMAP_ERROR_STREAM; + goto free; + } + + cont_req_or_resp_data = + mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data); + if (cont_req_or_resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cont_req_or_resp_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cont_req != NULL) + mailimap_continue_req_free(cont_req); + if (resp_data != NULL) + mailimap_response_data_free(resp_data); + err: + return res; +} + +/* + response = *(continue-req / response-data) response-done +*/ + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * cont_req_or_resp_data_list; + struct mailimap_response * resp; + struct mailimap_response_done * resp_done; + int r; + int res; + + cur_token = * index; + cont_req_or_resp_data_list = NULL; + resp_done = NULL; + + r = mailimap_struct_multiple_parse(fd, buffer, + &cur_token, &cont_req_or_resp_data_list, + (mailimap_struct_parser *) + mailimap_cont_req_or_resp_data_parse, + (mailimap_struct_destructor *) + mailimap_cont_req_or_resp_data_free, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + r = mailimap_response_done_parse(fd, buffer, &cur_token, &resp_done, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done); + if (resp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_resp_done; + } + + * result = resp; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_resp_done: + mailimap_response_done_free(resp_done); + free_list: + if (cont_req_or_resp_data_list != NULL) { + clist_foreach(cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(cont_req_or_resp_data_list); + } + return res; +} + +/* + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF +*/ + +static int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_response_data * resp_data; + size_t cur_token; + int type; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_mailbox_data * mb_data; + struct mailimap_message_data * msg_data; + struct mailimap_capability_data * cap_data; + int r; + int res; + + cond_state = NULL; + cond_bye = NULL; + mb_data = NULL; + msg_data = NULL; + cap_data = NULL; + + cur_token = * index; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_STATE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_BYE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_parse(fd, buffer, &cur_token, &mb_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_message_data_parse(fd, buffer, &cur_token, &msg_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + resp_data = mailimap_response_data_new(type, cond_state, + cond_bye, mb_data, + msg_data, cap_data); + if (resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = resp_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cond_state) + mailimap_resp_cond_state_free(cond_state); + if (cond_bye) + mailimap_resp_cond_bye_free(cond_bye); + if (mb_data) + mailimap_mailbox_data_free(mb_data); + if (msg_data) + mailimap_message_data_free(msg_data); + if (cap_data) + mailimap_capability_data_free(cap_data); + err: + return res; +} + +/* + response-done = response-tagged / response-fatal +*/ + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_response_done * resp_done; + size_t cur_token; + struct mailimap_response_tagged * tagged; + struct mailimap_response_fatal * fatal; + int r; + int res; + + cur_token = * index; + + tagged = NULL; + fatal = NULL; + + type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */ + + r = mailimap_response_tagged_parse(fd, buffer, &cur_token, &tagged, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_TAGGED; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_fatal_parse(fd, buffer, &cur_token, &fatal, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_FATAL; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + resp_done = mailimap_response_done_new(type, tagged, fatal); + if (resp_done == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = resp_done; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (tagged == NULL) + mailimap_response_tagged_free(tagged); + if (fatal == NULL) + mailimap_response_fatal_free(fatal); + err: + return res; +} + +/* + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately +*/ + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_response_fatal * fatal; + size_t cur_token; + int res; + int r; + + cur_token = * index; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + fatal = mailimap_response_fatal_new(cond_bye); + if (fatal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = fatal; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_cond_bye_free(cond_bye); + err: + return res; +} + +/* + response-tagged = tag SP resp-cond-state CRLF +*/ + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_response_tagged * resp_tagged; + int r; + int res; + + cur_token = * index; + cond_state = NULL; + + r = mailimap_tag_parse(fd, buffer, &cur_token, &tag, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + resp_tagged = mailimap_response_tagged_new(tag, cond_state); + if (resp_tagged == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_cond_state; + } + + * result = resp_tagged; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_cond_state: + mailimap_resp_cond_state_free(cond_state); + free_tag: + mailimap_tag_free(tag); + err: + return res; +} + +/* + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition +*/ + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_auth * cond_auth; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * index; + text = NULL; + + type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_OK; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "PREAUTH"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_PREAUTH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_auth = mailimap_resp_cond_auth_new(type, text); + if (cond_auth == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_auth; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-bye = "BYE" SP resp-text +*/ + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_resp_text * text; + int r; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "BYE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_bye = mailimap_resp_cond_bye_new(text); + if (cond_bye == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = cond_bye; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition +*/ + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_state * cond_state; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * index; + text = NULL; + + type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_state = mailimap_resp_cond_state_new(type, text); + if (cond_state == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_state; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + + +/* + resp-specials = "]" +*/ + +static int is_resp_specials(char ch) +{ + switch (ch) { + case ']': + return TRUE; + }; + return FALSE; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +/* "[" resp-text-code "]" */ + +static int +mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text_code * text_code; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimap_obracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_code_parse(fd, buffer, &cur_token, &text_code, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + * result = text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_code_free(text_code); + err: + return res; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * text_code; + struct mailimap_resp_text * resp_text; + char * text; + int r; + int res; + + cur_token = * index; + text = NULL; + text_code = NULL; + + r = mailimap_resp_text_resp_text_code_parse(fd, buffer, &cur_token, + &text_code, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + r = mailimap_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free_resp_text_code; + } + + resp_text = mailimap_resp_text_new(text_code, text); + if (resp_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_text; + } + + * result = resp_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_resp_text_code: + if (text_code != NULL) + mailimap_resp_text_code_free(text_code); + free_text: + mailimap_text_free(text); + return res; +} + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +/* + ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE +*/ + +static int +mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + int id; + size_t cur_token; + + cur_token = * index; + + id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token); + + if (id == -1) + return MAILIMAP_ERROR_PARSE; + + * result = id; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +/* + SP "(" astring *(SP astring) ")" +*/ + +static int +mailimap_resp_text_code_badcharset_1_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + int res; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &charset, + (mailimap_struct_parser *) + mailimap_astring_parse, + (mailimap_struct_destructor *) + mailimap_astring_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto charset; + } + + * index = cur_token; + * result = charset; + + return MAILIMAP_NO_ERROR; + + charset: + clist_foreach(charset, (clist_func) mailimap_string_free, NULL); + clist_free(charset); + err: + return res; +} + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +static int +mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BADCHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + + charset = NULL; + + r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, &cur_token, + &charset, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * result = charset; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" +*/ + +static int +mailimap_resp_text_code_permanentflags_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * flaglist; + int r; + int res; + + cur_token = * index; + + flaglist = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "PERMANENTFLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &flaglist, + (mailimap_struct_parser *) + mailimap_flag_perm_parse, + (mailimap_struct_destructor *) + mailimap_flag_perm_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + * index = cur_token; + * result = flaglist; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL); + clist_free(flaglist); + err: + return res; +} + + +/* + "UIDNEXT" SP nz-number / + "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number +*/ + +static int +mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + uint32_t number; + struct mailimap_resp_text_code * resp_text_code; + int r; + + cur_token = * index; + + resp_text_code = NULL; + + type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + switch (type) { + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + number, 0, 0, NULL , NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, number, 0, NULL , NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, 0, number, NULL , NULL); + break; + } + + if (resp_text_code == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*] +*/ + +static int is_text_char(char ch); + +/* + any TEXT-CHAR except "]" +*/ + +static int is_text_char_1(char ch) +{ + if (ch == ']') + return FALSE; + return is_text_char(ch); +} + +/* + 1* +*/ + +static int +mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * value; + int r; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_resp_text_code_other_2_parse(fd, buffer, &cur_token, + &value, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = value; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*] +*/ + +static int +mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + char * value; + struct mailimap_resp_text_code * resp_text_code; + int r; + int res; + + cur_token = * index; + atom = NULL; + value = NULL; + + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_code_other_1_parse(fd, buffer, &cur_token, + &value, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER, + NULL, NULL, NULL, + 0, 0, 0, atom, value); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + if (value != NULL) + free(value); + mailimap_atom_free(atom); + err: + return res; +} + + + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * resp_text_code; + clist * badcharset; + clist * permanentflags; + struct mailimap_capability_data * cap_data; + int type; + int r; + int res; + + cur_token = * index; + + resp_text_code = NULL; + badcharset = NULL; + cap_data = NULL; + permanentflags = NULL; + + r = mailimap_resp_text_code_1_parse(fd, buffer, &cur_token, &type); + if (r == MAILIMAP_NO_ERROR) { + /* do nothing */ + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_resp_text_code_badcharset_parse(fd, buffer, &cur_token, + &badcharset, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET; + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_capability_data_parse(fd, buffer, &cur_token, + &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, &cur_token, + &permanentflags, + progr_rate, + progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_number_parse(fd, buffer, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_other_parse(fd, buffer, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (resp_text_code == NULL) { + resp_text_code = mailimap_resp_text_code_new(type, + badcharset, cap_data, + permanentflags, + 0, 0, 0, NULL, NULL); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + if (permanentflags) { + clist_foreach(permanentflags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(permanentflags); + } + if (cap_data) + mailimap_capability_data_free(cap_data); + if (badcharset) { + clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL); + clist_free(badcharset); + } +err: + return res; +} + +/* + UNIMPLEMENTED + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +/* + UNIMPLEMENTED + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + +/* + section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_spec * section_spec; + size_t cur_token; + struct mailimap_section * section; + int r; + int res; + + cur_token = * index; + + section_spec = NULL; + + r = mailimap_obracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_spec_parse(fd, buffer, &cur_token, §ion_spec, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (section_spec == NULL) + section = NULL; + else { + section = mailimap_section_new(section_spec); + if (section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = section; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_section_spec_free(section_spec); + err: + return res; +} + +/* + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + struct mailimap_header_list * header_list; + struct mailimap_section_msgtext * msgtext; + int r; + int res; + + cur_token = * index; + + header_list = NULL; + + type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) { + r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) { + r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + msgtext = mailimap_section_msgtext_new(type, header_list); + if (msgtext == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_header_list; + } + + * result = msgtext; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_header_list: + if (header_list) + mailimap_header_list_free(header_list); + err: + return res; +} + +/* + section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_part * section_part; + size_t cur_token; + clist * section_id; + int r; + int res; + + cur_token = * index; + section_id = NULL; + + r = mailimap_struct_list_parse(fd, buffer, &cur_token, §ion_id, '.', + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(section_id); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_section_id; + } + + * result = section_part; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_section_id: + clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_id); + err: + return res; +} + +/* + section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_section_msgtext * section_msgtext; + struct mailimap_section_part * section_part; + struct mailimap_section_text * section_text; + struct mailimap_section_spec * section_spec; + size_t cur_token; + int r; + int res; + size_t final_token; + + cur_token = * index; + + section_msgtext = NULL; + section_part = NULL; + section_text = NULL; + + r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, + §ion_msgtext, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT; + break; + + case MAILIMAP_ERROR_PARSE: + + r = mailimap_section_part_parse(fd, buffer, &cur_token, + §ion_part, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + + type = MAILIMAP_SECTION_SPEC_SECTION_PART; + + r = mailimap_dot_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_section_text_parse(fd, buffer, &cur_token, §ion_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + final_token = cur_token; + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + cur_token = final_token; + break; + + default: + res = r; + goto err; + } + + section_spec = mailimap_section_spec_new(type, section_msgtext, + section_part, section_text); + if (section_spec == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_spec; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + if (section_part) + mailimap_section_part_free(section_part); + if (section_text) + mailimap_section_text_free(section_text); + err: + return res; +} + +/* + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_msgtext * section_msgtext; + size_t cur_token; + struct mailimap_section_text * section_text; + int type; + int r; + int res; + + cur_token = * index; + + section_msgtext = NULL; + + type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, §ion_msgtext, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT; + + if (r == MAILIMAP_ERROR_PARSE) { + r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME"); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_MIME; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_text = mailimap_section_text_new(type, section_msgtext); + if (section_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + err: + return res; +} + +/* + UNIMPLEMENTED + select = "SELECT" SP mailbox +*/ + +/* + UNIMPLEMENTED + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* + UNIMPLEMENTED + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +/* + UNIMPLEMENTED + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +/* + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + +static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + int type; + size_t cur_token; + + cur_token = * index; + + type = mailimap_status_att_get_token_value(fd, buffer, &cur_token); + + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + store = "STORE" SP set SP store-att-flags +*/ + +/* + UNIMPLEMENTED + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +/* + string = quoted / literal +*/ + +static int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * string; + int r; + size_t len; + + cur_token = * index; + + r = mailimap_quoted_parse(fd, buffer, &cur_token, &string, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + len = strlen(string); + else if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_literal_parse(fd, buffer, &cur_token, &string, &len, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = string; + if (result_len != NULL) + * result_len = len; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + subscribe = "SUBSCRIBE" SP mailbox +*/ + +/* + tag = 1* +*/ + +/* + any ASTRING-CHAR except "+" +*/ + +static int is_tag_char(char ch) +{ + if (ch == '+') + return FALSE; + return is_astring_char(ch); +} + +/* + tag = 1* +*/ + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + int r; + + cur_token = * index; + + r = mailimap_custom_string_parse(fd, buffer, &cur_token, &tag, + is_tag_char); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = tag; + + return MAILIMAP_NO_ERROR; +} + +/* + text = 1*TEXT-CHAR +*/ + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_text_char); +} + + +/* + TEXT-CHAR = +*/ + +static int is_text_char(char ch) +{ + if ((ch == '\r') || (ch == '\n')) + return FALSE; + + return is_char(ch); +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* + 2DIGIT +*/ + +static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ +#ifndef UNSTRICT_SYNTAX + int digit; + int two_digit; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = two_digit * 10 + digit; + + * result = two_digit; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#else + uint32_t number; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = number; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * phour, int * pmin, int * psec) +{ + size_t cur_token; + int hour; + int min; + int sec; + int r; + + cur_token = * index; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &hour); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &min); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers +*/ + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + return mailimap_nz_number_parse(fd, buffer, index, result); +} + +/* + UNIMPLEMENTED + unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +/* + UNIMPLEMENTED + userid = astring +*/ + +/* + UNIMPLEMENTED + x-command = "X" atom +*/ + +/* + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + uint32_t zone; +#ifndef UNSTRICT_SYNTAX + int i; + int digit; +#endif + int sign; + int r; + + cur_token = * index; + + sign = 1; + r = mailimap_plus_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = 1; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = -1; + } + + if (r != MAILIMAP_NO_ERROR) + return r; + +#ifdef UNSTRICT_SYNTAX + r = mailimap_number_parse(fd, buffer, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; +#else + zone = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + zone = zone * 10 + digit; + } +#endif + + zone *= sign; + + * result = zone; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} diff --git a/kmicromail/libetpan/imap/mailimap_parser.h b/kmicromail/libetpan/imap/mailimap_parser.h new file mode 100644 index 0000000..b1de75b --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_parser.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_PARSER_H + +#define MAILIMAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_print.c b/kmicromail/libetpan/imap/mailimap_print.c new file mode 100644 index 0000000..8a04348 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_print.c @@ -0,0 +1,1615 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ +#ifdef DEBUG +#include "mailimap_print.h" + +#include + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields); +static void mailimap_envelope_print(struct mailimap_envelope * env); +static void mailimap_body_print(struct mailimap_body * body); +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * + fld_enc); + +static int indent_size = 0; + +static void indent() +{ + indent_size ++; +} + +static void unindent() +{ + indent_size --; +} + +static void print_indent() +{ + int i; + + for (i = 0 ; i < indent_size ; i++) + printf(" "); +} + + +static void mailimap_body_fld_lang_print(struct mailimap_body_fld_lang * + fld_lang) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-lang { "); + + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + printf("%s ", fld_lang->lg_data.lg_single); + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(fld_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * lang; + + lang = clist_content(cur); + + printf("%s ", lang); + } + break; + } + + print_indent(); + printf("}\n"); +} + +static void +mailimap_single_body_fld_param_print(struct mailimap_single_body_fld_param * + single) +{ + printf("(%s = %s)", single->pa_name, single->pa_value); +} + +static void mailimap_body_fld_param_print(struct mailimap_body_fld_param * + fld_param) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-param { "); + + for(cur = clist_begin(fld_param->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * single; + + single = clist_content(cur); + + mailimap_single_body_fld_param_print(single); + printf(" "); + } + printf("\n"); +} + +static void mailimap_body_fld_dsp_print(struct mailimap_body_fld_dsp * fld_dsp) +{ + print_indent(); + printf("body-fld-dsp {\n"); + indent(); + + print_indent(); + printf("name { %s }\n", fld_dsp->dsp_type); + + mailimap_body_fld_param_print(fld_dsp->dsp_attributes); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_extension_list_print(clist * ext_list); + +static void mailimap_body_extension_print(struct mailimap_body_extension * ext) +{ + print_indent(); + printf("body-extention {\n"); + indent(); + + switch (ext->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + print_indent(); + printf("%s\n", ext->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + print_indent(); + printf("%i\n", ext->ext_data.ext_number); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_extension_list_print(ext->ext_data.ext_body_extension_list); + break; + } + + unindent(); + print_indent(); + printf("}\n"); + +} + +static void mailimap_body_extension_list_print(clist * ext_list) +{ + clistiter * cur; + + print_indent(); + printf("body-extention-list {\n"); + indent(); + + for (cur = clist_begin(ext_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body_extension * ext; + + ext = clist_content(cur); + + mailimap_body_extension_print(ext); + } + + unindent(); + print_indent(); + printf("}"); +} + +static void mailimap_body_ext_1part_print(struct mailimap_body_ext_1part * + body_ext_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + print_indent(); + printf("md5 { %s }\n", body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) { + mailimap_body_fld_dsp_print(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) { + mailimap_body_fld_lang_print(body_ext_1part->bd_language); + + if (body_ext_1part->bd_extension_list) + mailimap_body_extension_list_print(body_ext_1part->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_text_print(struct mailimap_body_type_text * + body_type_text) +{ + print_indent(); + printf("body-type-text {\n"); + indent(); + + print_indent(); + printf("media-text { %s }\n", body_type_text->bd_media_text); + mailimap_body_fields_print(body_type_text->bd_fields); + print_indent(); + printf("lines { %i }\n", body_type_text->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_msg_print(struct mailimap_body_type_msg * + body_type_msg) +{ + print_indent(); + printf("body-type-msg {\n"); + indent(); + + mailimap_body_fields_print(body_type_msg->bd_fields); + mailimap_envelope_print(body_type_msg->bd_envelope); + mailimap_body_print(body_type_msg->bd_body); + + print_indent(); + printf("lines { %i }\n", body_type_msg->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * fld_enc) +{ + print_indent(); + printf("body-fld-enc { "); + + switch (fld_enc->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + print_indent(); + printf("7bit"); + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + printf("8bit"); + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + printf("binary"); + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + printf("base64"); + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + printf("quoted-printable"); + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + printf("%s", fld_enc->enc_value); + break; + } + + printf("}\n"); +} + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields) +{ + print_indent(); + printf("body-fields {\n"); + indent(); + + mailimap_body_fld_param_print(body_fields->bd_parameter); + + print_indent(); + printf("body-fld-id { %s }\n", body_fields->bd_id); + printf("body-fld-desc { %s }\n", body_fields->bd_description); + mailimap_body_fld_enc_print(body_fields->bd_encoding); + printf("body-fld-octets { %i }\n", body_fields->bd_size); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_media_basic_print(struct mailimap_media_basic * + media_basic) +{ + print_indent(); + printf("media-basic {"); + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + printf("application"); + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + printf("audio"); + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + printf("image"); + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + printf("message"); + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + printf("video"); + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + printf("%s", media_basic->med_basic_type); + break; + } + printf(" / %s }\n", media_basic->med_subtype); +} + +static void mailimap_body_type_basic_print(struct mailimap_body_type_basic * + body_type_basic) +{ + print_indent(); + printf("body-type-basic {\n"); + indent(); + + mailimap_media_basic_print(body_type_basic->bd_media_basic); + mailimap_body_fields_print(body_type_basic->bd_fields); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_1part_print(struct mailimap_body_type_1part * + body_type_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + switch (body_type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_print(body_type_1part->bd_data.bd_type_basic); + break; + + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_print(body_type_1part->bd_data.bd_type_msg); + break; + + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_print(body_type_1part->bd_data.bd_type_text); + break; + } + + if (body_type_1part->bd_ext_1part != NULL) + mailimap_body_ext_1part_print(body_type_1part->bd_ext_1part); + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_ext_mpart(struct mailimap_body_ext_mpart * ext_mpart) +{ + print_indent(); + printf("body-ext-mpart {\n"); + indent(); + + mailimap_body_fld_param_print(ext_mpart->bd_parameter); + if (ext_mpart->bd_disposition) { + mailimap_body_fld_dsp_print(ext_mpart->bd_disposition); + if (ext_mpart->bd_language) { + mailimap_body_fld_lang_print(ext_mpart->bd_language); + + if (ext_mpart->bd_extension_list) + mailimap_body_extension_list_print(ext_mpart->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_type_mpart_print(struct mailimap_body_type_mpart * + mpart) +{ + clistiter * cur; + + print_indent(); + printf("body-type-mpart {\n"); + indent(); + + for(cur = clist_begin(mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * body; + + body = clist_content(cur); + + mailimap_body_print(body); + } + + printf("media-subtype { %s }\n", mpart->bd_media_subtype); + + if (mpart->bd_ext_mpart) + mailimap_body_ext_mpart(mpart->bd_ext_mpart); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_print(struct mailimap_body * body) +{ + print_indent(); + printf("body {\n"); + indent(); + + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_print(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_print(body->bd_data.bd_body_mpart); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_date_time_print(struct mailimap_date_time * date_time) +{ + print_indent(); + printf("date-time { %i/%i/%i - %i:%i:%i %i }\n", + date_time->dt_day, date_time->dt_month, date_time->dt_year, + date_time->dt_hour, date_time->dt_min, date_time->dt_month, + date_time->dt_zone); +} + +static void mailimap_address_print(struct mailimap_address * address) +{ + print_indent(); + printf("address { name: %s, addr: %s, mailbox: %s, host: %s) }\n", + address->ad_personal_name, address->ad_source_route, + address->ad_mailbox_name, address->ad_host_name); +} + +static void mailimap_envelope_address_list_print(clist * address) +{ + clistiter * cur; + + print_indent(); + printf("envelope-address-list {\n"); + indent(); + + for(cur = clist_begin(address) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * addr; + + addr = clist_content(cur); + + mailimap_address_print(addr); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_envelope_print(struct mailimap_envelope * env) +{ + print_indent(); + printf("envelope {\n"); + indent(); + + print_indent(); + printf("date { %s }\n", env->env_date); + + print_indent(); + printf("subject { %s }\n", env->env_subject); + + print_indent(); + printf("from {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_from->frm_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("sender {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_sender->snd_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("reply-to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_reply_to->rt_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_to->to_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("cc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_cc->cc_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("bcc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_bcc->bcc_list); + unindent(); + print_indent(); + printf("}\n"); + + printf("in-reply-to { %s }\n", env->env_in_reply_to); + printf("message-id { %s }\n", env->env_message_id); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_header_list_print(struct mailimap_header_list * + header_list) +{ + clistiter * cur; + + print_indent(); + printf("header-list { "); + for(cur = clist_begin(header_list->hdr_list) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); +} + +static void mailimap_section_msgtext_print(struct mailimap_section_msgtext * + section_msgtext) +{ + print_indent(); + printf("section-msgtext {\n"); + indent(); + + switch(section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + print_indent(); + printf("header\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + print_indent(); + printf("header fields {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + print_indent(); + printf("header fields not {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + print_indent(); + printf("text\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_part_print(struct mailimap_section_part * + section_part) +{ + clistiter * cur; + + print_indent(); + printf("section-part { "); + + for(cur = clist_begin(section_part->sec_id) ; + cur != NULL ; cur = clist_next(cur)) { + printf("%i", * ((uint32_t *) clist_content(cur))); + if (clist_next(cur) != NULL) + printf("."); + } + printf(" }\n"); +} + +static void mailimap_section_text_print(struct mailimap_section_text * + section_text) +{ + print_indent(); + printf("section-text {\n"); + indent(); + + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_MIME: + print_indent(); + printf("MIME"); + break; + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_text->sec_msgtext); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_spec_print(struct mailimap_section_spec * + section_spec) +{ + print_indent(); + printf("section-spec {"); + indent(); + + switch(section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_spec->sec_data.sec_msgtext); + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + mailimap_section_part_print(section_spec->sec_data.sec_part); + if (section_spec->sec_text != NULL) + mailimap_section_text_print(section_spec->sec_text); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_print(struct mailimap_section * section) +{ + print_indent(); + printf("section {\n"); + indent(); + + if (section != NULL) + if (section->sec_spec != NULL) + mailimap_section_spec_print(section->sec_spec); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_body_section_print(struct + mailimap_msg_att_body_section * + msg_att_body_section) +{ + print_indent(); + printf("msg-att-body-section {\n"); + indent(); + + mailimap_section_print(msg_att_body_section->sec_section); + printf("origin-octet: %i\n", msg_att_body_section->sec_origin_octet); + printf("body-part: %s\n", msg_att_body_section->sec_body_part); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_msg_att_static_print(struct mailimap_msg_att_static * + msg_att_static) +{ + print_indent(); + printf("msg-att-static {\n"); + indent(); + + switch (msg_att_static->att_type) { + + case MAILIMAP_MSG_ATT_ENVELOPE: + print_indent(); + printf("envelope {\n"); + indent(); + print_indent(); + mailimap_envelope_print(msg_att_static->att_data.att_env); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_INTERNALDATE: + print_indent(); + printf("internaldate {\n"); + indent(); + print_indent(); + mailimap_date_time_print(msg_att_static->att_data.att_internal_date); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822: + print_indent(); + printf("rfc822 {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_HEADER: + print_indent(); + printf("rfc822-header {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_header.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_TEXT: + print_indent(); + printf("rfc822-text {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_text.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + print_indent(); + printf("rfc822-size { %i }\n", msg_att_static->att_data.att_rfc822_size); + break; + + case MAILIMAP_MSG_ATT_BODY: + print_indent(); + printf("body {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_body); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + print_indent(); + printf("bodystructure {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_bodystructure); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + print_indent(); + printf("body-section {\n"); + indent(); + print_indent(); + mailimap_msg_att_body_section_print(msg_att_static->att_data.att_body_section); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_UID: + printf("uid { %i }\n", msg_att_static->att_data.att_uid); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag); + +static void mailimap_flag_fetch_print(struct mailimap_flag_fetch * flag) +{ + print_indent(); + printf("flag fetch {\n"); + indent(); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_FETCH_RECENT: + printf("recent\n"); + break; + case MAILIMAP_FLAG_FETCH_OTHER: + print_indent(); + printf("flag {\n"); + indent(); + mailimap_flag_print(flag->fl_flag); + unindent(); + print_indent(); + printf("}\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_dynamic_print(struct mailimap_msg_att_dynamic * + dynamic) +{ + clistiter * cur; + + print_indent(); + printf("msg-att-dynamic {\n"); + indent(); + + for(cur = clist_begin(dynamic->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag; + + flag = (struct mailimap_flag_fetch *) clist_content(cur); + mailimap_flag_fetch_print(flag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_item_print(struct mailimap_msg_att_item * item) +{ + print_indent(); + printf("msg-att-item {\n"); + indent(); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_print(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_print(item->att_data.att_static); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_print(struct mailimap_msg_att * msg_att) +{ + clistiter * cur; + + print_indent(); + printf("msg-att {\n"); + indent(); + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(cur); + + mailimap_msg_att_item_print(item); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_message_data_print(struct mailimap_message_data * + msg_data) +{ + print_indent(); + printf("message-data {\n"); + indent(); + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + print_indent(); + printf("expunged { %i }\n", msg_data->mdt_number); + break; + case MAILIMAP_MESSAGE_DATA_FETCH: + print_indent(); + printf("message-number { %i }\n", msg_data->mdt_number); + mailimap_msg_att_print(msg_data->mdt_msg_att); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_status_att_print(int status_att) +{ + print_indent(); + printf("status-att { "); + + switch(status_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + printf("messages"); + break; + case MAILIMAP_STATUS_ATT_RECENT: + printf("recent"); + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + printf("uidnext"); + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + printf("status att uidvalidity"); + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + printf("status att unseen"); + break; + } + + printf(" \n"); +} + +static void +mailimap_status_info_print(struct mailimap_status_info * info) +{ + print_indent(); + printf("status-info {\n"); + indent(); + + mailimap_status_att_print(info->st_att); + + print_indent(); + printf("value { %i }\n", info->st_value); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_mailbox_data_status_print(struct mailimap_mailbox_data_status * + mb_data_status) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data-status {\n"); + indent(); + + print_indent(); + printf("mailbox { %s }\n", mb_data_status->st_mailbox); + + for(cur = clist_begin(mb_data_status->st_info_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + + mailimap_status_info_print(info); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mbx_list_oflag_print(struct mailimap_mbx_list_oflag * + oflag) +{ + print_indent(); + printf("mbx-list-oflag { "); + + switch (oflag->of_type) { + case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: + printf("noinferiors"); + break; + case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: + printf("%s", oflag->of_flag_ext); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_sflag_print(int sflag) +{ + print_indent(); + printf("mbx-list-sflag { "); + + switch (sflag) { + case MAILIMAP_MBX_LIST_SFLAG_MARKED: + printf("marked"); + break; + case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: + printf("noselected"); + break; + case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: + printf("unmarked"); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_flags_print(struct mailimap_mbx_list_flags * + mbx_list_flags) +{ + clistiter * cur; + + print_indent(); + printf("mbx-list-flags {"); + indent(); + + if (mbx_list_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) + mailimap_mbx_list_sflag_print(mbx_list_flags->mbf_sflag); + + for(cur = clist_begin(mbx_list_flags->mbf_oflags) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_mbx_list_oflag * oflag; + + oflag = clist_content(cur); + + mailimap_mbx_list_oflag_print(oflag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mailbox_list_print(struct mailimap_mailbox_list * mb_list) +{ + print_indent(); + printf("mailbox-list {\n"); + indent(); + + mailimap_mbx_list_flags_print(mb_list->mb_flag); + printf("dir-separator { %c }\n", mb_list->mb_delimiter); + printf("mailbox { %s }\n", mb_list->mb_name); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_list_print(struct mailimap_flag_list * flag_list) +{ + clistiter * cur; + + print_indent(); + printf("flag-list {\n"); + indent(); + + for(cur = clist_begin(flag_list->fl_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag * flag; + + flag = clist_content(cur); + + print_indent(); + mailimap_flag_print(flag); + printf("\n"); + } + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_mailbox_data_print(struct mailimap_mailbox_data * mb_data) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data {\n"); + indent(); + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + print_indent(); + printf("flags {\n"); + indent(); + mailimap_flag_list_print(mb_data->mbd_data.mbd_flags); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + print_indent(); + printf("list {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + print_indent(); + printf("lsub {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_lsub); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + print_indent(); + printf("search { "); + for(cur = clist_begin(mb_data->mbd_data.mbd_search) ; + cur != NULL ; cur = clist_next(cur)) { + uint32_t * id; + + id = clist_content(cur); + printf("%i ", * id); + } + printf(" }\n"); + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + print_indent(); + printf("status {\n"); + indent(); + mailimap_mailbox_data_status_print(mb_data->mbd_data.mbd_status); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + print_indent(); + printf("exists { %i }\n", mb_data->mbd_data.mbd_exists); + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + print_indent(); + printf("recent { %i }\n", mb_data->mbd_data.mbd_recent); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code); + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text); + +static void mailimap_resp_cond_bye_print(struct mailimap_resp_cond_bye * + resp_cond_bye) +{ + print_indent(); + printf("resp-cond-bye {\n"); + indent(); + mailimap_resp_text_print(resp_cond_bye->rsp_text); + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_state_print(struct mailimap_resp_cond_state * + resp_cond_state) +{ + print_indent(); + printf("resp-cond-state {\n"); + indent(); + + switch(resp_cond_state->rsp_type) { + case MAILIMAP_RESP_COND_STATE_OK: + print_indent(); + printf("OK\n"); + break; + case MAILIMAP_RESP_COND_STATE_NO: + print_indent(); + printf("NO\n"); + break; + case MAILIMAP_RESP_COND_STATE_BAD: + print_indent(); + printf("BAD\n"); + break; + } + + mailimap_resp_text_print(resp_cond_state->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data); + +static void mailimap_response_data_print(struct mailimap_response_data * + resp_data) +{ + print_indent(); + printf("response-data {\n"); + indent(); + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + mailimap_resp_cond_state_print(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + mailimap_resp_cond_bye_print(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailimap_mailbox_data_print(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + mailimap_message_data_print(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + mailimap_capability_data_print(resp_data->rsp_data.rsp_capability_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag) +{ + printf("flag { "); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + printf("answered"); + break; + + case MAILIMAP_FLAG_FLAGGED: + printf("flagged"); + break; + + case MAILIMAP_FLAG_DELETED: + printf("deleted"); + break; + + case MAILIMAP_FLAG_SEEN: + printf("seen"); + break; + + case MAILIMAP_FLAG_DRAFT: + printf("flag draft"); + break; + + case MAILIMAP_FLAG_KEYWORD: + printf("keyword { %s }", flag->fl_data.fl_keyword); + break; + + case MAILIMAP_FLAG_EXTENSION: + printf("extention { %s }", flag->fl_data.fl_extension); + break; + } + + printf(" }"); +} + +static void mailimap_flag_perm_print(struct mailimap_flag_perm * flag_perm) +{ + print_indent(); + printf("flag-perm { "); + + switch (flag_perm->fl_type) { + case MAILIMAP_FLAG_PERM_FLAG: + mailimap_flag_print(flag_perm->fl_flag); + break; + + case MAILIMAP_FLAG_PERM_ALL: + printf("all"); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_print(struct mailimap_capability * cap) +{ + print_indent(); + printf("capability { "); + + switch (cap->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + printf("auth { %s }", cap->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + printf("atom { %s }", cap->cap_data.cap_name); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data) +{ + clistiter * cur; + + print_indent(); + printf("capability-data {\n"); + indent(); + + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + mailimap_capability_print(cap); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code) +{ + clistiter * cur; + + print_indent(); + printf("resp-text-code {\n"); + indent(); + + switch (text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + print_indent(); + printf("badcharset { "); + for(cur = clist_begin(text_code->rc_data.rc_badcharset) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + print_indent(); + printf("capability {\n"); + indent(); + mailimap_capability_data_print(text_code->rc_data.rc_cap_data); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + print_indent(); + printf("permanent-flags {\n"); + indent(); + cur = clist_begin(text_code->rc_data.rc_perm_flags); + while (cur != NULL) { + mailimap_flag_perm_print(clist_content(cur)); + cur = clist_next(cur); + } + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + print_indent(); + printf("readonly\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + print_indent(); + printf("readwrite\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + print_indent(); + printf("trycreate\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + print_indent(); + printf("uidnext { %i }\n", text_code->rc_data.rc_uidnext); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + print_indent(); + printf("uidvalidity { %i }\n", text_code->rc_data.rc_uidvalidity); + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + print_indent(); + printf("unseen { %i }\n", text_code->rc_data.rc_first_unseen); + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + print_indent(); + printf("other { %s = %s }\n", + text_code->rc_data.rc_atom.atom_name, + text_code->rc_data.rc_atom.atom_value); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text) +{ + print_indent(); + printf("resp-text {\n"); + indent(); + + if (resp_text->rsp_code) + mailimap_resp_text_code_print(resp_text->rsp_code); + print_indent(); + printf("text { %s }\n", resp_text->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_continue_req_print(struct mailimap_continue_req * + cont_req) +{ + print_indent(); + printf("continue-req {\n"); + indent(); + + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + print_indent(); + printf("resp-text {\n"); + indent(); + mailimap_resp_text_print(cont_req->cr_data.cr_text); + unindent(); + print_indent(); + printf("}\n"); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + printf("base64 { %s }\n", cont_req->cr_data.cr_base64); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_cont_req_or_resp_data_print(struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + print_indent(); + printf("cont-req-or-resp-data {\n"); + indent(); + + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + mailimap_continue_req_print(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + mailimap_response_data_print(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_tagged_print(struct mailimap_response_tagged * + tagged) +{ + print_indent(); + printf("response-tagged {\n"); + indent(); + + print_indent(); + printf("tag { %s }\n", tagged->rsp_tag); + mailimap_resp_cond_state_print(tagged->rsp_cond_state); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_fatal_print(struct mailimap_response_fatal * + fatal) +{ + print_indent(); + printf("response-fatal {\n"); + indent(); + + mailimap_resp_cond_bye_print(fatal->rsp_bye); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_done_print(struct mailimap_response_done * + resp_done) +{ + print_indent(); + printf("response-done {\n"); + indent(); + + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_print(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_print(resp_done->rsp_data.rsp_fatal); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_response_print(struct mailimap_response * resp) +{ + clistiter * cur; + + print_indent(); + printf("response {\n"); + indent(); + + for(cur = clist_begin(resp->rsp_cont_req_or_resp_data_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * resp; + + resp = clist_content(cur); + + mailimap_cont_req_or_resp_data_print(resp); + } + + mailimap_response_done_print(resp->rsp_resp_done); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_auth_print(struct mailimap_resp_cond_auth * + cond_auth) +{ + print_indent(); + printf("resp-cond-auth {\n"); + indent(); + + switch (cond_auth->rsp_type) { + case MAILIMAP_RESP_COND_AUTH_OK: + print_indent(); + printf("OK\n"); + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + print_indent(); + printf("PREAUTH\n"); + } + mailimap_resp_text_print(cond_auth->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_greeting_print(struct mailimap_greeting * greeting) +{ + print_indent(); + printf("greeting {\n"); + indent(); + + switch(greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_print(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_print(greeting->gr_data.gr_bye); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} +#endif diff --git a/kmicromail/libetpan/imap/mailimap_print.h b/kmicromail/libetpan/imap/mailimap_print.h new file mode 100644 index 0000000..24016fa --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_print.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_PRINT_H + +#define MAILIMAP_PRINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +void mailimap_response_print(struct mailimap_response * resp); + +void mailimap_greeting_print(struct mailimap_greeting * greeting); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_sender.c b/kmicromail/libetpan/imap/mailimap_sender.c new file mode 100644 index 0000000..ac4bfe8 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_sender.c @@ -0,0 +1,2743 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_sender.h" +#include "clist.h" +#include "mail.h" +#include + +#include +#include + +/* + TODO : + implement progression for literal +*/ + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static int mailimap_atom_send(mailstream * fd, const char * atom); + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type); + +static int mailimap_base64_send(mailstream * fd, const char * base64); + + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date); + +static int mailimap_date_day_send(mailstream * fd, int day); + +static int mailimap_date_month_send(mailstream * fd, int month); + + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text); +*/ + + +static int mailimap_date_year_send(mailstream *fd, int year); + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time); + +static int mailimap_digit_send(mailstream * fd, int digit); + + + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type); + + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att); + + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag); + + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension); + + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword); + + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list); + + + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header); + + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list); + +static int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern); + + +static int mailimap_mailbox_send(mailstream * fd, const char * mb); + +static int mailimap_number_send(mailstream * fd, uint32_t number); + +static int mailimap_password_send(mailstream * fd, const char * pass); + +static int mailimap_quoted_char_send(mailstream * fd, char ch); + +static int mailimap_quoted_send(mailstream * fd, const char * quoted); + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key); + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section); + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext); + + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section); + + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec); + + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text); + + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num); + + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item); + + +static int mailimap_set_send(mailstream * fd, + struct mailimap_set * set); + + + +static int mailimap_status_att_send(mailstream * fd, int * status_att); + + + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags); + + +static int mailimap_userid_send(mailstream * fd, const char * user); + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +static int mailimap_sized_token_send(mailstream * fd, const char * atom, + size_t len) +{ + if (mailstream_write(fd, atom, len) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_token_send(mailstream * fd, const char * atom) +{ + if (mailstream_write(fd, atom, strlen(atom)) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_char_send(mailstream * fd, char ch) +{ + if (mailstream_write(fd, &ch, 1) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +typedef int mailimap_struct_sender(mailstream * fd, void * data); + +static int +mailimap_struct_list_send(mailstream * fd, clist * list, + char symbol, + mailimap_struct_sender * sender) +{ + clistiter * cur; + void * elt; + int r; + + cur = clist_begin(list); + + if (cur == NULL) + return MAILIMAP_NO_ERROR; + + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + + while (cur != NULL) { + r = mailimap_char_send(fd, symbol); + if (r != MAILIMAP_NO_ERROR) + return r; + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + } + + return MAILIMAP_NO_ERROR; +} + + +static int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender) +{ + return mailimap_struct_list_send(fd, list, ' ', sender); +} + +int mailimap_space_send(mailstream * fd) +{ + return mailimap_char_send(fd, ' '); +} + +int mailimap_crlf_send(mailstream * fd) +{ + int r; + + r = mailimap_char_send(fd, '\r'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '\n'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_oparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, '('); +} + +static int mailimap_cparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, ')'); +} + +static int mailimap_dquote_send(mailstream * fd) +{ + return mailimap_char_send(fd, '"'); +} + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +/* +=> append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size) +{ + int r; + + r = mailimap_token_send(fd, "APPEND"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + if (flag_list != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_list_send(fd, flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + } + if (date_time != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_time_send(fd, date_time); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_count_send(fd, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + astring = 1*ASTRING-CHAR / string + +=> ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom(const char * str) +{ + if (* str == '\0') + return 0; + + while (* str != '\0') { + unsigned char uch = (unsigned char) * str; + + if (!isalnum(uch)) + return 0; + + str ++; + } + + return 1; +} + +static int mailimap_astring_send(mailstream * fd, const char * astring) +{ + /* + workaround for buggy Courier-IMAP that does not accept + quoted-strings for fields name but prefer atoms. + */ + if (is_atom(astring)) + return mailimap_atom_send(fd, astring); + else + return mailimap_quoted_send(fd, astring); +} + +/* +=> atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_send(mailstream * fd, const char * atom) +{ + return mailimap_token_send(fd, atom); +} + +/* +=> ATOM-CHAR = +*/ + +/* +=> atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials +*/ + +/* +=> authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type) +{ + int r; + + r = mailimap_token_send(fd, "AUTHENTICATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_auth_type_send(fd, auth_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64) +{ + int r; + + r = mailimap_base64_send(fd, base64); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type) +{ + return mailimap_atom_send(fd, auth_type); +} + + +/* +=> base64 = *(4base64-char) [base64-terminal] +*/ + +static int mailimap_base64_send(mailstream * fd, const char * base64) +{ + return mailimap_token_send(fd, base64); +} + +/* +=> base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +=> command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +=> command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +int mailimap_capability_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_logout_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "LOGOUT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_noop_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "NOOP"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +=> command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +=> command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +int mailimap_check_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CHECK"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_close_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CLOSE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_expunge_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "EXPUNGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +/* +=> copy = "COPY" SP set SP mailbox +*/ + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "COPY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_copy_send(fd, set, mb); +} + +/* +=> create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_create_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "CREATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date = date-text / DQUOTE date-text DQUOTE +*/ + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date) +{ + int r; + + r = mailimap_date_day_send(fd, date->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date->dt_year); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-day = 1*2DIGIT + ; Day of month +*/ + +static int mailimap_date_day_send(mailstream * fd, int day) +{ + return mailimap_number_send(fd, day); +} + +/* +=> date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_send(mailstream * fd, int day) +{ + int r; + + if (day < 10) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, day); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_number_send(fd, day); +} + +/* +=> date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_send(mailstream * fd, int month) +{ + const char * name; + int r; + + name = mailimap_month_get_token_str(month); + + if (name == NULL) + return MAILIMAP_ERROR_INVAL; + + r = mailimap_token_send(fd, name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-text = date-day "-" date-month "-" date-year +*/ + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text) +{ + if (!mailimap_date_day_send(fd, date_text->day)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_month_send(fd, date_text->month)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_year_send(fd, date_text->year)) + return FALSE; + + return TRUE; +} +*/ + +/* +=> date-year = 4DIGIT +*/ + +static int mailimap_fixed_digit_send(mailstream * fd, + int num, int count) +{ + int r; + + r = mailimap_fixed_digit_send(fd, num / 10, count); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_digit_send(fd, num % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_year_send(mailstream *fd, int year) +{ + int r; + + r = mailimap_fixed_digit_send(fd, year, 4); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time) +{ + int r; + + r = mailimap_date_day_fixed_send(fd, date_time->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_delete_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "DELETE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + +digit + +digit-nz = %x31-39 + ; 1-9 +*/ + +static int mailimap_digit_send(mailstream * fd, int digit) +{ + return mailimap_char_send(fd, digit + '0'); +} + + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil +*/ + +/* +=> examine = "EXAMINE" SP mailbox +*/ + +int mailimap_examine_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "EXAMINE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list); + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_ALL: + return mailimap_token_send(fd, "ALL"); + case MAILIMAP_FETCH_TYPE_FULL: + return mailimap_token_send(fd, "FULL"); + case MAILIMAP_FETCH_TYPE_FAST: + return mailimap_token_send(fd, "FAST"); + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att); + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + return mailimap_fetch_att_list_send(fd, + fetch_type->ft_data.ft_fetch_att_list); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +int mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "FETCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_type_send(fd, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_fetch_send(fd, set, fetch_type); +} + +/* currently porting */ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, fetch_att_list, + (mailimap_struct_sender *) + mailimap_fetch_att_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + switch(fetch_att->att_type) { + case MAILIMAP_FETCH_ATT_ENVELOPE: + return mailimap_token_send(fd, "ENVELOPE"); + + case MAILIMAP_FETCH_ATT_FLAGS: + return mailimap_token_send(fd, "FLAGS"); + + case MAILIMAP_FETCH_ATT_INTERNALDATE: + return mailimap_token_send(fd, "INTERNALDATE"); + + case MAILIMAP_FETCH_ATT_RFC822: + return mailimap_token_send(fd, "RFC822"); + + case MAILIMAP_FETCH_ATT_RFC822_HEADER: + return mailimap_token_send(fd, "RFC822.HEADER"); + + case MAILIMAP_FETCH_ATT_RFC822_SIZE: + return mailimap_token_send(fd, "RFC822.SIZE"); + + case MAILIMAP_FETCH_ATT_RFC822_TEXT: + return mailimap_token_send(fd, "RFC822.TEXT"); + + case MAILIMAP_FETCH_ATT_BODY: + return mailimap_token_send(fd, "BODY"); + + case MAILIMAP_FETCH_ATT_BODYSTRUCTURE: + return mailimap_token_send(fd, "BODYSTRUCTURE"); + + case MAILIMAP_FETCH_ATT_UID: + return mailimap_token_send(fd, "UID"); + + case MAILIMAP_FETCH_ATT_BODY_SECTION: + + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION: + r = mailimap_token_send(fd, "BODY.PEEK"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +/* +enum { + FLAG_ANSWERED, + FLAG_FLAGGED, + FLAG_DELETED, + FLAG_SEEN, + FLAG_DRAFT, + FLAG_KEYWORD, + FLAG_EXTENSION +}; + +struct mailimap_flag { + gint type; + gchar * flag_keyword; + gchar * flag_extension; +}; +*/ + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag) +{ + switch(flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + return mailimap_token_send(fd, "\\Answered"); + case MAILIMAP_FLAG_FLAGGED: + return mailimap_token_send(fd, "\\Flagged"); + case MAILIMAP_FLAG_DELETED: + return mailimap_token_send(fd, "\\Deleted"); + case MAILIMAP_FLAG_SEEN: + return mailimap_token_send(fd, "\\Seen"); + case MAILIMAP_FLAG_DRAFT: + return mailimap_token_send(fd, "\\Draft"); + case MAILIMAP_FLAG_KEYWORD: + return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword); + case MAILIMAP_FLAG_EXTENSION: + return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + + +/* +=> flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension) +{ + int r; + + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_send(fd, flag_extension); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +/* +=> flag-keyword = atom +*/ + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword) +{ + return mailimap_token_send(fd, flag_keyword); +} + +/* +=> flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (flag_list->fl_list != NULL) { + r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list, + (mailimap_struct_sender *) mailimap_flag_send); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +/* +=> header-fld-name = astring +*/ + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header) +{ + return mailimap_astring_send(fd, header); +} + +/* +=> header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list, + (mailimap_struct_sender *) mailimap_header_fld_name_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list = "LIST" SP mailbox SP list-mailbox +*/ + +int mailimap_list_send(mailstream * fd, + const char * mb, + const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LIST"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list-mailbox = 1*list-char / string +*/ + +static int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern) +{ + return mailimap_quoted_send(fd, pattern); +} + +/* + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" +*/ + +/* +=> literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun) +{ + uint32_t len; + int r; + + len = strlen(literal); + + r = mailimap_literal_count_send(fd, len); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + "{" number "}" CRLF +*/ + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count) +{ + int r; + + r = mailimap_char_send(fd, '{'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, count); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '}'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + *CHAR8 +*/ + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_sized_token_send(fd, literal, len); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + + +/* +=> login = "LOGIN" SP userid SP password +*/ + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password) +{ + int r; + + r = mailimap_token_send(fd, "LOGIN"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_userid_send(fd, userid); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_password_send(fd, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +static int mailimap_mailbox_send(mailstream * fd, const char * mb) +{ + return mailimap_astring_send(fd, mb); +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil +*/ + +/* +=> number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +static int mailimap_number_send(mailstream * fd, uint32_t number) +{ + int r; + + if (number / 10 != 0) { + r = mailimap_number_send(fd, number / 10); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_digit_send(fd, number % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> password = astring +*/ + +static int mailimap_password_send(mailstream * fd, const char * pass) +{ + return mailimap_astring_send(fd, pass); +} + +/* +=> quoted = DQUOTE *QUOTED-CHAR DQUOTE + +=> QUOTED-CHAR = / + "\" quoted-specials + +=> quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int mailimap_quoted_char_send(mailstream * fd, char ch) +{ + int r; + + if (is_quoted_specials(ch)) { + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_char_send(fd, ch); +} + +static int mailimap_quoted_send(mailstream * fd, const char * quoted) +{ + const char * pos; + int r; + + pos = quoted; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + while (* pos != 0) { + r = mailimap_quoted_char_send(fd, * pos); + if (r != MAILIMAP_NO_ERROR) + return r; + pos ++; + } + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_token_send(fd, "RENAME"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +/* +=> search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (charset != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_key_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_search_send(fd, charset, key); +} + + +/* +=> search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key) +{ + int r; + + switch (key->sk_type) { + + case MAILIMAP_SEARCH_KEY_ALL: + return mailimap_token_send(fd, "ALL"); + + case MAILIMAP_SEARCH_KEY_ANSWERED: + return mailimap_token_send(fd, "ANSWERED"); + + case MAILIMAP_SEARCH_KEY_BCC: + r = mailimap_token_send(fd, "BCC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_bcc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BEFORE: + r = mailimap_token_send(fd, "BEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_before); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BODY: + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_body); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_CC: + r = mailimap_token_send(fd, "CC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_cc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_DELETED: + return mailimap_token_send(fd, "DELETED"); + + case MAILIMAP_SEARCH_KEY_FLAGGED: + return mailimap_token_send(fd, "FLAGGED"); + + case MAILIMAP_SEARCH_KEY_FROM: + r = mailimap_token_send(fd, "FROM"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_from); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_KEYWORD: + r = mailimap_token_send(fd, "KEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NEW: + return mailimap_token_send(fd, "NEW"); + + case MAILIMAP_SEARCH_KEY_OLD: + return mailimap_token_send(fd, "OLD"); + + case MAILIMAP_SEARCH_KEY_ON: + r = mailimap_token_send(fd, "ON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_on); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_RECENT: + return mailimap_token_send(fd, "RECENT"); + + case MAILIMAP_SEARCH_KEY_SEEN: + return mailimap_token_send(fd, "SEEN"); + + case MAILIMAP_SEARCH_KEY_SINCE: + r = mailimap_token_send(fd, "SINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_since); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SUBJECT: + r = mailimap_token_send(fd, "SUBJECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_subject); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TEXT: + r = mailimap_token_send(fd, "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TO: + r = mailimap_token_send(fd, "TO"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNANSWERED: + return mailimap_token_send(fd, "UNANSWERED"); + + case MAILIMAP_SEARCH_KEY_UNDELETED: + return mailimap_token_send(fd, "UNDELETED"); + + case MAILIMAP_SEARCH_KEY_UNFLAGGED: + return mailimap_token_send(fd, "UNFLAGGED"); + + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + r = mailimap_token_send(fd, "UNKEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNSEEN: + return mailimap_token_send(fd, "UNSEEN"); + + case MAILIMAP_SEARCH_KEY_DRAFT: + return mailimap_token_send(fd, "DRAFT"); + + case MAILIMAP_SEARCH_KEY_HEADER: + r = mailimap_token_send(fd, "HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_fld_name_send(fd, + key->sk_data.sk_header.sk_header_name); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, + key->sk_data.sk_header.sk_header_value); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_LARGER: + r = mailimap_token_send(fd, "LARGER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_larger); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NOT: + r = mailimap_token_send(fd, "NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_not); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_OR: + r = mailimap_token_send(fd, "OR"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or2); + if (r != MAILIMAP_NO_ERROR) + return r; + return TRUE; + + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + r = mailimap_token_send(fd, "SENTBEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentbefore); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTON: + r = mailimap_token_send(fd, "SENTON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_senton); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTSINCE: + r = mailimap_token_send(fd, "SENTSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentsince); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SMALLER: + r = mailimap_token_send(fd, "SMALLER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_smaller); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UID: + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, key->sk_data.sk_set); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNDRAFT: + return mailimap_token_send(fd, "UNDRAFT"); + + case MAILIMAP_SEARCH_KEY_SET: + return mailimap_set_send(fd, key->sk_data.sk_set); + + case MAILIMAP_SEARCH_KEY_MULTIPLE: + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, + (mailimap_struct_sender *) + mailimap_search_key_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section) +{ + int r; + + r = mailimap_char_send(fd, '['); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section != NULL) { + if (section->sec_spec != NULL) { + r = mailimap_section_spec_send(fd, section->sec_spec); + if (r != MAILIMAP_NO_ERROR) + return r; + } + } + + r = mailimap_char_send(fd, ']'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext) +{ + int r; + + switch (section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + return mailimap_token_send(fd, "HEADER"); + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + r = mailimap_token_send(fd, "HEADER.FIELDS"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + r = mailimap_token_send(fd, "HEADER.FIELDS.NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + return mailimap_token_send(fd, "TEXT"); + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber) +{ + return mailimap_number_send(fd, * pnumber); +} + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section) +{ + int r; + + r = mailimap_struct_list_send(fd, section->sec_id, '.', + (mailimap_struct_sender *) mailimap_pnumber_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec) +{ + int r; + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, + section_spec->sec_data.sec_msgtext); + + case MAILIMAP_SECTION_SPEC_SECTION_PART: + r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section_spec->sec_text != NULL) { + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_text_send(fd, + section_spec->sec_text); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text) +{ + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, section_text->sec_msgtext); + + case MAILIMAP_SECTION_TEXT_MIME: + return mailimap_token_send(fd, "MIME"); + + default: + /* should not happen */ + return MAILIMAP_NO_ERROR; + } +} + +/* +=> select = "SELECT" SP mailbox +*/ + +int +mailimap_select_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SELECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* if sequence_num == 0 then "*" */ + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num) +{ + if (sequence_num == 0) + return mailimap_char_send(fd, '*'); + else + return mailimap_number_send(fd, sequence_num); +} + +/* +=> set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item) +{ + int r; + + if (item->set_first == item->set_last) + return mailimap_sequence_num_send(fd, item->set_first); + else { + r = mailimap_sequence_num_send(fd, item->set_first); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_sequence_num_send(fd, item->set_last); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + } +} + +static int mailimap_set_send(mailstream * fd, + struct mailimap_set * set) +{ + return mailimap_struct_list_send(fd, set->set_list, ',', + (mailimap_struct_sender *) mailimap_set_item_send); +} + +/* +=> status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +static int +mailimap_status_att_list_send(mailstream * fd, + struct mailimap_status_att_list * status_att_list) +{ + return mailimap_struct_spaced_list_send(fd, status_att_list->att_list, + (mailimap_struct_sender *) mailimap_status_att_send); +} + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list) +{ + int r; + + r = mailimap_token_send(fd, "STATUS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_att_list_send(fd, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + + +static int mailimap_status_att_send(mailstream * fd, int * status_att) +{ + const char * token; + + token = mailimap_status_att_get_token_str(* status_att); + if (token == NULL) { + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } + + return mailimap_token_send(fd, token); +} + +/* +=> store = "STORE" SP set SP store-att-flags +*/ + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "STORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_att_flags_send(fd, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_store_send(fd, set, store_att_flags); +} + +/* +=> store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags) +{ + int r; + + switch (store_flags->fl_sign) { + case 1: + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + case -1: + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_token_send(fd, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (store_flags->fl_silent) { + r = mailimap_token_send(fd, ".SILENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_flag_list_send(fd, store_flags->fl_flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + string = quoted / literal +*/ + +/* +=> subscribe = "SUBSCRIBE" SP mailbox +*/ + +int mailimap_subscribe_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> tag = 1* +*/ + +int mailimap_tag_send(mailstream * fd, const char * tag) +{ + return mailimap_token_send(fd, tag); +} + +/* + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* +=> uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + +functions uid_copy, uid_fetch ... +*/ + + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +/* +=> unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UNSUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_starttls_send(mailstream * fd) +{ + return mailimap_token_send(fd, "STARTTLS"); +} + +/* +=> userid = astring +*/ + +static int mailimap_userid_send(mailstream * fd, const char * user) +{ + return mailimap_astring_send(fd, user); +} + +/* + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ diff --git a/kmicromail/libetpan/imap/mailimap_sender.h b/kmicromail/libetpan/imap/mailimap_sender.h new file mode 100644 index 0000000..3fc30ea --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_sender.h @@ -0,0 +1,164 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_SENDER_H + +#define MAILIMAP_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size); + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type); + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64); + +int mailimap_noop_send(mailstream * fd); + +int mailimap_logout_send(mailstream * fd); + +int mailimap_capability_send(mailstream * fd); + +int mailimap_check_send(mailstream * fd); + +int mailimap_close_send(mailstream * fd); + +int mailimap_expunge_send(mailstream * fd); + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_create_send(mailstream * fd, + const char * mb); + + +int mailimap_delete_send(mailstream * fd, const char * mb); + +int mailimap_examine_send(mailstream * fd, const char * mb); + +int +mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int mailimap_list_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password); + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name); + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_select_send(mailstream * fd, const char * mb); + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list); + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_subscribe_send(mailstream * fd, const char * mb); + + +int mailimap_tag_send(mailstream * fd, const char * tag); + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb); + +int mailimap_crlf_send(mailstream * fd); + +int mailimap_space_send(mailstream * fd); + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count); + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_starttls_send(mailstream * fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_socket.c b/kmicromail/libetpan/imap/mailimap_socket.c new file mode 100644 index 0000000..6f846f2 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_socket.c @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_socket.h" + +#include "mailimap.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_IMAP_PORT 143 +#define SERVICE_NAME_IMAP "imap2" +#define SERVICE_TYPE_TCP "tcp" + +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAP_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_MEMORY; + } + + return mailimap_connect(f, stream); +} diff --git a/kmicromail/libetpan/imap/mailimap_socket.h b/kmicromail/libetpan/imap/mailimap_socket.h new file mode 100644 index 0000000..aadc67e --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_socket.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_ssl.c b/kmicromail/libetpan/imap/mailimap_ssl.c new file mode 100644 index 0000000..ace5678 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_ssl.c @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_ssl.h" + +#include "mailimap.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_IMAPS_PORT 993 +#define SERVICE_NAME_IMAPS "imaps" +#define SERVICE_TYPE_TCP "tcp" + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAPS_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_CONNECTION_REFUSED; + } + + return mailimap_connect(f, stream); +} diff --git a/kmicromail/libetpan/imap/mailimap_ssl.h b/kmicromail/libetpan/imap/mailimap_ssl.h new file mode 100644 index 0000000..76906a0 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_ssl.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_types.c b/kmicromail/libetpan/imap/mailimap_types.c new file mode 100644 index 0000000..c5dde7c --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types.c @@ -0,0 +1,2961 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_types.h" +#include "mmapstring.h" +#include "mail.h" + +#include + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* from parser */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number) +{ + uint32_t * pnumber; + + pnumber = malloc(sizeof(* pnumber)); + if (pnumber == NULL) + return NULL; + + * pnumber = number; + + return pnumber; +} + +void mailimap_number_alloc_free(uint32_t * pnumber) +{ + free(pnumber); +} + + +/* ************************************************************************* */ + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name) +{ + struct mailimap_address * addr; + + addr = malloc(sizeof(* addr)); + if (addr == NULL) + return NULL; + + addr->ad_personal_name = ad_personal_name; + addr->ad_source_route = ad_source_route; + addr->ad_mailbox_name = ad_mailbox_name; + addr->ad_host_name = ad_host_name; + + return addr; +} + +void mailimap_address_free(struct mailimap_address * addr) +{ + mailimap_addr_host_free(addr->ad_host_name); + mailimap_addr_mailbox_free(addr->ad_mailbox_name); + mailimap_addr_adl_free(addr->ad_source_route); + mailimap_addr_name_free(addr->ad_personal_name); + free(addr); +} + +void mailimap_addr_host_free(char * addr_host) +{ + mailimap_nstring_free(addr_host); +} + +void mailimap_addr_mailbox_free(char * addr_mailbox) +{ + mailimap_nstring_free(addr_mailbox); +} + +void mailimap_addr_adl_free(char * addr_adl) +{ + mailimap_nstring_free(addr_adl); +} + +void mailimap_addr_name_free(char * addr_name) +{ + mailimap_nstring_free(addr_name); +} + + + + + +/* +struct mailimap_astring * +mailimap_astring_new(gint type, + gchar * atom_astring, + gchar * string) +{ + struct mailimap_astring * astring; + + astring = g_new(struct mailimap_astring, 1); + if (astring == NULL) + return FALSE; + + astring->type = type; + astring->atom_astring = atom_astring; + astring->string = string; + + return astring; +} + +void mailimap_astring_free(struct mailimap_astring * astring) +{ + if (astring->atom_astring) + mailimap_atom_astring_free(astring->atom_astring); + if (astring->string) + mailimap_string_free(astring->string); + free(astring); +} +*/ + +void mailimap_astring_free(char * astring) +{ + if (mmap_string_unref(astring) != 0) + free(astring); +} + +static void mailimap_custom_string_free(char * str) +{ + free(str); +} + + +void mailimap_atom_free(char * atom) +{ + free(atom); +} + + + + +void mailimap_auth_type_free(char * auth_type) +{ + mailimap_atom_free(auth_type); +} + + + + + +void mailimap_base64_free(char * base64) +{ + free(base64); +} + + + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart) +{ + struct mailimap_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + + body->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_1PART: + body->bd_data.bd_body_1part = bd_body_1part; + break; + case MAILIMAP_BODY_MPART: + body->bd_data.bd_body_mpart = bd_body_mpart; + break; + } + + return body; +} + +void mailimap_body_free(struct mailimap_body * body) +{ + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_free(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_free(body->bd_data.bd_body_mpart); + break; + } + free(body); +} + + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list) +{ + struct mailimap_body_extension * body_extension; + + body_extension = malloc(sizeof(* body_extension)); + if (body_extension == NULL) + return NULL; + + body_extension->ext_type = ext_type; + switch (ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + body_extension->ext_data.ext_nstring = ext_nstring; + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + body_extension->ext_data.ext_number = ext_number; + break; + case MAILIMAP_BODY_EXTENSION_LIST: + body_extension->ext_data.ext_body_extension_list = ext_body_extension_list; + break; + } + + return body_extension; +} + +static void +mailimap_body_ext_list_free(clist * body_ext_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be) +{ + switch (be->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + mailimap_nstring_free(be->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_ext_list_free(be->ext_data.ext_body_extension_list); + break; + } + + free(be); +} + + +static void +mailimap_body_ext_list_free(clist * body_ext_list) +{ + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); +} + + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_1part * body_ext_1part; + + body_ext_1part = malloc(sizeof(* body_ext_1part)); + if (body_ext_1part == NULL) + return NULL; + + body_ext_1part->bd_md5 = bd_md5; + body_ext_1part->bd_disposition = bd_disposition; + body_ext_1part->bd_language = bd_language; + body_ext_1part->bd_extension_list = bd_extension_list; + + return body_ext_1part; +} + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part) +{ + mailimap_body_fld_md5_free(body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) + mailimap_body_fld_lang_free(body_ext_1part->bd_language); + if (body_ext_1part->bd_extension_list) + mailimap_body_ext_list_free(body_ext_1part->bd_extension_list); + + free(body_ext_1part); +} + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_mpart * body_ext_mpart; + + body_ext_mpart = malloc(sizeof(* body_ext_mpart)); + if (body_ext_mpart == NULL) + return NULL; + + body_ext_mpart->bd_parameter = bd_parameter; + body_ext_mpart->bd_disposition = bd_disposition; + body_ext_mpart->bd_language = bd_language; + body_ext_mpart->bd_extension_list = bd_extension_list; + + return body_ext_mpart; +} + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart) +{ + if (body_ext_mpart->bd_parameter != NULL) + mailimap_body_fld_param_free(body_ext_mpart->bd_parameter); + if (body_ext_mpart->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_mpart->bd_disposition); + if (body_ext_mpart->bd_language) + mailimap_body_fld_lang_free(body_ext_mpart->bd_language); + if (body_ext_mpart->bd_extension_list) + mailimap_body_ext_list_free(body_ext_mpart->bd_extension_list); + free(body_ext_mpart); +} + + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size) +{ + struct mailimap_body_fields * body_fields; + + body_fields = malloc(sizeof(* body_fields)); + if (body_fields == NULL) + return NULL; + body_fields->bd_parameter = bd_parameter; + body_fields->bd_id = bd_id; + body_fields->bd_description = bd_description; + body_fields->bd_encoding = bd_encoding; + body_fields->bd_size = bd_size; + + return body_fields; +} + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields) +{ + if (body_fields->bd_parameter != NULL) + mailimap_body_fld_param_free(body_fields->bd_parameter); + mailimap_body_fld_id_free(body_fields->bd_id); + mailimap_body_fld_desc_free(body_fields->bd_description); + mailimap_body_fld_enc_free(body_fields->bd_encoding); + free(body_fields); +} + + + + + + +void mailimap_body_fld_desc_free(char * body_fld_desc) +{ + mailimap_nstring_free(body_fld_desc); +} + + + + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes) +{ + struct mailimap_body_fld_dsp * body_fld_dsp; + + body_fld_dsp = malloc(sizeof(* body_fld_dsp)); + if (body_fld_dsp == NULL) + return NULL; + + body_fld_dsp->dsp_type = dsp_type; + body_fld_dsp->dsp_attributes = dsp_attributes; + + return body_fld_dsp; +} + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd) +{ + if (bfd->dsp_type != NULL) + mailimap_string_free(bfd->dsp_type); + if (bfd->dsp_attributes != NULL) + mailimap_body_fld_param_free(bfd->dsp_attributes); + free(bfd); +} + + + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value) +{ + struct mailimap_body_fld_enc * body_fld_enc; + + body_fld_enc = malloc(sizeof(* body_fld_enc)); + if (body_fld_enc == NULL) + return NULL; + + body_fld_enc->enc_type = enc_type; + body_fld_enc->enc_value = enc_value; + + return body_fld_enc; +} + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe) +{ + if (bfe->enc_value) + mailimap_string_free(bfe->enc_value); + free(bfe); +} + + + +void mailimap_body_fld_id_free(char * body_fld_id) +{ + mailimap_nstring_free(body_fld_id); +} + + + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list) +{ + struct mailimap_body_fld_lang * fld_lang; + + fld_lang = malloc(sizeof(* fld_lang)); + if (fld_lang == NULL) + return NULL; + + fld_lang->lg_type = lg_type; + switch (lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + fld_lang->lg_data.lg_single = lg_single; + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + fld_lang->lg_data.lg_list = lg_list; + break; + } + + return fld_lang; +} + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang) +{ + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + mailimap_nstring_free(fld_lang->lg_data.lg_single); + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + clist_foreach(fld_lang->lg_data.lg_list, + (clist_func) mailimap_string_free, NULL); + clist_free(fld_lang->lg_data.lg_list); + break; + } + free(fld_lang); +} + + + +void mailimap_body_fld_md5_free(char * body_fld_md5) +{ + mailimap_nstring_free(body_fld_md5); +} + + + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value) +{ + struct mailimap_single_body_fld_param * param; + + param = malloc(sizeof(* param)); + if (param == NULL) + return NULL; + param->pa_name = pa_name; + param->pa_value = pa_value; + + return param; +} + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p) +{ + mailimap_string_free(p->pa_name); + mailimap_string_free(p->pa_value); + free(p); +} + + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list) +{ + struct mailimap_body_fld_param * fld_param; + + fld_param = malloc(sizeof(* fld_param)); + if (fld_param == NULL) + return NULL; + fld_param->pa_list = pa_list; + + return fld_param; +} + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param) +{ + clist_foreach(fld_param->pa_list, + (clist_func) mailimap_single_body_fld_param_free, NULL); + clist_free(fld_param->pa_list); + free(fld_param); +} + + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part) +{ + struct mailimap_body_type_1part * body_type_1part; + + body_type_1part = malloc(sizeof(* body_type_1part)); + if (body_type_1part == NULL) + return NULL; + + body_type_1part->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + body_type_1part->bd_data.bd_type_basic = bd_type_basic; + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + body_type_1part->bd_data.bd_type_msg = bd_type_msg; + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + body_type_1part->bd_data.bd_type_text = bd_type_text; + break; + } + body_type_1part->bd_ext_1part = bd_ext_1part; + + return body_type_1part; +} + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p) +{ + switch (bt1p->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_free(bt1p->bd_data.bd_type_basic); + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_free(bt1p->bd_data.bd_type_msg); + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_free(bt1p->bd_data.bd_type_text); + break; + } + if (bt1p->bd_ext_1part) + mailimap_body_ext_1part_free(bt1p->bd_ext_1part); + + free(bt1p); +} + + + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields) +{ + struct mailimap_body_type_basic * body_type_basic; + + body_type_basic = malloc(sizeof(* body_type_basic)); + if (body_type_basic == NULL) + return NULL; + + body_type_basic->bd_media_basic = bd_media_basic; + body_type_basic->bd_fields = bd_fields; + + return body_type_basic; +} + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic) +{ + mailimap_media_basic_free(body_type_basic->bd_media_basic); + mailimap_body_fields_free(body_type_basic->bd_fields); + free(body_type_basic); +} + + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart) +{ + struct mailimap_body_type_mpart * body_type_mpart; + + body_type_mpart = malloc(sizeof(* body_type_mpart)); + if (body_type_mpart == NULL) + return NULL; + + body_type_mpart->bd_list = bd_list; + body_type_mpart->bd_media_subtype = bd_media_subtype; + body_type_mpart->bd_ext_mpart = bd_ext_mpart; + + return body_type_mpart; +} + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart) +{ + clist_foreach(body_type_mpart->bd_list, + (clist_func) mailimap_body_free, NULL); + clist_free(body_type_mpart->bd_list); + mailimap_media_subtype_free(body_type_mpart->bd_media_subtype); + if (body_type_mpart->bd_ext_mpart) + mailimap_body_ext_mpart_free(body_type_mpart->bd_ext_mpart); + + free(body_type_mpart); +} + + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines) +{ + struct mailimap_body_type_msg * body_type_msg; + + body_type_msg = malloc(sizeof(* body_type_msg)); + if (body_type_msg == NULL) + return NULL; + + body_type_msg->bd_fields = bd_fields; + body_type_msg->bd_envelope = bd_envelope; + body_type_msg->bd_body = bd_body; + body_type_msg->bd_lines = bd_lines; + + return body_type_msg; +} + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg) +{ + mailimap_body_fields_free(body_type_msg->bd_fields); + mailimap_envelope_free(body_type_msg->bd_envelope); + mailimap_body_free(body_type_msg->bd_body); + free(body_type_msg); +} + + + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines) +{ + struct mailimap_body_type_text * body_type_text; + + body_type_text = malloc(sizeof(* body_type_text)); + if (body_type_text == NULL) + return NULL; + + body_type_text->bd_media_text = bd_media_text; + body_type_text->bd_fields = bd_fields; + body_type_text->bd_lines = bd_lines; + + return body_type_text; +} + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text) +{ + mailimap_media_text_free(body_type_text->bd_media_text); + mailimap_body_fields_free(body_type_text->bd_fields); + free(body_type_text); +} + + + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name) +{ + struct mailimap_capability * cap; + + cap = malloc(sizeof(* cap)); + if (cap == NULL) + return NULL; + cap->cap_type = cap_type; + switch (cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + cap->cap_data.cap_auth_type = cap_auth_type; + break; + case MAILIMAP_CAPABILITY_NAME: + cap->cap_data.cap_name = cap_name; + break; + } + + return cap; +} + +void mailimap_capability_free(struct mailimap_capability * c) +{ + switch (c->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + free(c->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + free(c->cap_data.cap_name); + break; + } + free(c); +} + + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list) +{ + struct mailimap_capability_data * cap_data; + + cap_data = malloc(sizeof(* cap_data)); + if (cap_data == NULL) + return NULL; + + cap_data->cap_list = cap_list; + + return cap_data; +} + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data) +{ + if (cap_data->cap_list) { + clist_foreach(cap_data->cap_list, + (clist_func) mailimap_capability_free, NULL); + clist_free(cap_data->cap_list); + } + free(cap_data); +} + + + + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64) +{ + struct mailimap_continue_req * cont_req; + + cont_req = malloc(sizeof(* cont_req)); + if (cont_req == NULL) + return NULL; + cont_req->cr_type = cr_type; + switch (cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + cont_req->cr_data.cr_text = cr_text; + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + cont_req->cr_data.cr_base64 = cr_base64; + break; + } + + return cont_req; +} + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req) +{ + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + mailimap_resp_text_free(cont_req->cr_data.cr_text); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + mailimap_base64_free(cont_req->cr_data.cr_base64); + break; + } + free(cont_req); +} + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone) +{ + struct mailimap_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_day = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +void mailimap_date_time_free(struct mailimap_date_time * date_time) +{ + free(date_time); +} + + + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id) +{ + struct mailimap_envelope * env; + + env = malloc(sizeof(* env)); + if (env == NULL) + return NULL; + + env->env_date = env_date; + env->env_subject = env_subject; + env->env_from = env_from; + env->env_sender = env_sender; + env->env_reply_to = env_reply_to; + env->env_to = env_to; + env->env_cc = env_cc; + env->env_bcc = env_bcc; + env->env_in_reply_to = env_in_reply_to; + env->env_message_id = env_message_id; + + return env; +} + + +void mailimap_envelope_free(struct mailimap_envelope * env) +{ + if (env->env_date) + mailimap_env_date_free(env->env_date); + if (env->env_subject) + mailimap_env_subject_free(env->env_subject); + if (env->env_from) + mailimap_env_from_free(env->env_from); + if (env->env_sender) + mailimap_env_sender_free(env->env_sender); + if (env->env_reply_to) + mailimap_env_reply_to_free(env->env_reply_to); + if (env->env_to) + mailimap_env_to_free(env->env_to); + if (env->env_cc) + mailimap_env_cc_free(env->env_cc); + if (env->env_bcc) + mailimap_env_bcc_free(env->env_bcc); + if (env->env_in_reply_to) + mailimap_env_in_reply_to_free(env->env_in_reply_to); + if (env->env_message_id) + mailimap_env_message_id_free(env->env_message_id); + + free(env); +} + + +static void mailimap_address_list_free(clist * addr_list) +{ + if (addr_list != NULL) { + clist_foreach(addr_list, (clist_func) mailimap_address_free, NULL); + clist_free(addr_list); + } +} + + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list) +{ + struct mailimap_env_bcc * env_bcc; + + env_bcc = malloc(sizeof(* env_bcc)); + if (env_bcc == NULL) + return NULL; + env_bcc->bcc_list = bcc_list; + + return env_bcc; +} + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc) +{ + mailimap_address_list_free(env_bcc->bcc_list); + free(env_bcc); +} + + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list) +{ + struct mailimap_env_cc * env_cc; + + env_cc = malloc(sizeof(* env_cc)); + if (env_cc == NULL) + return NULL; + env_cc->cc_list = cc_list; + + return env_cc; +} + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc) +{ + mailimap_address_list_free(env_cc->cc_list); + free(env_cc); +} + + +void mailimap_env_date_free(char * date) +{ + mailimap_nstring_free(date); +} + + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list) +{ + struct mailimap_env_from * env_from; + + env_from = malloc(sizeof(* env_from)); + if (env_from == NULL) + return NULL; + env_from->frm_list = frm_list; + + return env_from; +} + +void mailimap_env_from_free(struct mailimap_env_from * env_from) +{ + mailimap_address_list_free(env_from->frm_list); + free(env_from); +} + + +void mailimap_env_in_reply_to_free(char * in_reply_to) +{ + mailimap_nstring_free(in_reply_to); +} + +void mailimap_env_message_id_free(char * message_id) +{ + mailimap_nstring_free(message_id); +} + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list) +{ + struct mailimap_env_reply_to * env_reply_to; + + env_reply_to = malloc(sizeof(* env_reply_to)); + if (env_reply_to == NULL) + return NULL; + env_reply_to->rt_list = rt_list; + + return env_reply_to; +} + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to) +{ + mailimap_address_list_free(env_reply_to->rt_list); + free(env_reply_to); +} + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list) +{ + struct mailimap_env_sender * env_sender; + + env_sender = malloc(sizeof(* env_sender)); + if (env_sender == NULL) + return NULL; + env_sender->snd_list = snd_list; + + return env_sender; +} + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender) +{ + mailimap_address_list_free(env_sender->snd_list); + free(env_sender); +} + +void mailimap_env_subject_free(char * subject) +{ + mailimap_nstring_free(subject); +} + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list) +{ + struct mailimap_env_to * env_to; + + env_to = malloc(sizeof(* env_to)); + if (env_to == NULL) + return NULL; + env_to->to_list = to_list; + + return env_to; +} + +void mailimap_env_to_free(struct mailimap_env_to * env_to) +{ + mailimap_address_list_free(env_to->to_list); + free(env_to); +} + + + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension) +{ + struct mailimap_flag * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + return NULL; + f->fl_type = fl_type; + switch (fl_type) { + case MAILIMAP_FLAG_KEYWORD: + f->fl_data.fl_keyword = fl_keyword; + break; + case MAILIMAP_FLAG_EXTENSION: + f->fl_data.fl_extension = fl_extension; + break; + } + + return f; +} + +void mailimap_flag_free(struct mailimap_flag * f) +{ + switch (f->fl_type) { + case MAILIMAP_FLAG_KEYWORD: + mailimap_flag_keyword_free(f->fl_data.fl_keyword); + break; + case MAILIMAP_FLAG_EXTENSION: + mailimap_flag_extension_free(f->fl_data.fl_extension); + break; + } + free(f); +} + + + +void mailimap_flag_extension_free(char * flag_extension) +{ + mailimap_atom_free(flag_extension); +} + + + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = malloc(sizeof(* flag_fetch)); + if (flag_fetch == NULL) + return NULL; + + flag_fetch->fl_type = fl_type; + flag_fetch->fl_flag = fl_flag; + + return flag_fetch; +} + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch) +{ + if (flag_fetch->fl_flag) + mailimap_flag_free(flag_fetch->fl_flag); + free(flag_fetch); +} + + + +void mailimap_flag_keyword_free(char * flag_keyword) +{ + mailimap_atom_free(flag_keyword); +} + + + + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list) +{ + struct mailimap_flag_list * flag_list; + + flag_list = malloc(sizeof(* flag_list)); + if (flag_list == NULL) + return NULL; + flag_list->fl_list = fl_list; + + return flag_list; +} + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list) +{ + clist_foreach(flag_list->fl_list, (clist_func) mailimap_flag_free, NULL); + clist_free(flag_list->fl_list); + free(flag_list); +} + + + + + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_perm * flag_perm; + + flag_perm = malloc(sizeof(* flag_perm)); + if (flag_perm == NULL) + return NULL; + + flag_perm->fl_type = fl_type; + flag_perm->fl_flag = fl_flag; + + return flag_perm; +} + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm) +{ + if (flag_perm->fl_flag != NULL) + mailimap_flag_free(flag_perm->fl_flag); + free(flag_perm); +} + + + + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye) +{ + struct mailimap_greeting * greeting; + + greeting = malloc(sizeof(* greeting)); + if (greeting == NULL) + return NULL; + greeting->gr_type = gr_type; + switch (gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + greeting->gr_data.gr_auth = gr_auth; + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + greeting->gr_data.gr_bye = gr_bye; + break; + } + + return greeting; +} + +void mailimap_greeting_free(struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_free(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_free(greeting->gr_data.gr_bye); + break; + } + free(greeting); +} + + + +void +mailimap_header_fld_name_free(char * header_fld_name) +{ + mailimap_astring_free(header_fld_name); +} + + + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list) +{ + struct mailimap_header_list * header_list; + + header_list = malloc(sizeof(* header_list)); + if (header_list == NULL) + return NULL; + + header_list->hdr_list = hdr_list; + + return header_list; +} + +void +mailimap_header_list_free(struct mailimap_header_list * header_list) +{ + clist_foreach(header_list->hdr_list, + (clist_func) mailimap_header_fld_name_free, + NULL); + clist_free(header_list->hdr_list); + free(header_list); +} + + + +void mailimap_literal_free(char * literal) +{ + /* free(literal); */ + mmap_string_unref(literal); +} + +void mailimap_mailbox_free(char * mb) +{ + mailimap_astring_free(mb); +} + + + + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value) +{ + struct mailimap_status_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + info->st_att = st_att; + info->st_value = st_value; + + return info; +} + +void mailimap_status_info_free(struct mailimap_status_info * info) +{ + free(info); +} + + + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list) +{ + struct mailimap_mailbox_data_status * mb_data_status; + + mb_data_status = malloc(sizeof(* mb_data_status)); + if (mb_data_status == NULL) + return NULL; + mb_data_status->st_mailbox = st_mailbox; + mb_data_status->st_info_list = st_info_list; + + return mb_data_status; +} + +void +mailimap_mailbox_data_search_free(clist * data_search) +{ + clist_foreach(data_search, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(data_search); +} + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info) +{ + mailimap_mailbox_free(info->st_mailbox); + clist_foreach(info->st_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(info->st_info_list); + free(info); +} + + +static void +mailimap_mailbox_data_flags_free(struct mailimap_flag_list * flag_list) +{ + mailimap_flag_list_free(flag_list); +} + +static void +mailimap_mailbox_data_list_free(struct mailimap_mailbox_list * mb_list) +{ + mailimap_mailbox_list_free(mb_list); +} + +static void +mailimap_mailbox_data_lsub_free(struct mailimap_mailbox_list * mb_lsub) +{ + mailimap_mailbox_list_free(mb_lsub); +} + + + + + + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent) +{ + struct mailimap_mailbox_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + return NULL; + + data->mbd_type = mbd_type; + switch (mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + data->mbd_data.mbd_flags = mbd_flags; + break; + case MAILIMAP_MAILBOX_DATA_LIST: + data->mbd_data.mbd_list = mbd_list; + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + data->mbd_data.mbd_lsub = mbd_lsub; + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + data->mbd_data.mbd_search = mbd_search; + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + data->mbd_data.mbd_status = mbd_status; + break; + case MAILIMAP_MAILBOX_DATA_EXISTS: + data->mbd_data.mbd_exists = mbd_exists; + break; + case MAILIMAP_MAILBOX_DATA_RECENT: + data->mbd_data.mbd_recent = mbd_recent; + break; + } + + return data; +} + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data) +{ + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (mb_data->mbd_data.mbd_flags != NULL) + mailimap_mailbox_data_flags_free(mb_data->mbd_data.mbd_flags); + break; + case MAILIMAP_MAILBOX_DATA_LIST: + if (mb_data->mbd_data.mbd_list != NULL) + mailimap_mailbox_data_list_free(mb_data->mbd_data.mbd_list); + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + if (mb_data->mbd_data.mbd_lsub != NULL) + mailimap_mailbox_data_lsub_free(mb_data->mbd_data.mbd_lsub); + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (mb_data->mbd_data.mbd_search != NULL) + mailimap_mailbox_data_search_free(mb_data->mbd_data.mbd_search); + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + if (mb_data->mbd_data.mbd_status != NULL) + mailimap_mailbox_data_status_free(mb_data->mbd_data.mbd_status); + break; + } + free(mb_data); +} + + + + + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, clist * mbf_oflags, + int mbf_sflag) +{ + struct mailimap_mbx_list_flags * mbx_list_flags; + + mbx_list_flags = malloc(sizeof(* mbx_list_flags)); + if (mbx_list_flags == NULL) + return NULL; + + mbx_list_flags->mbf_type = mbf_type; + mbx_list_flags->mbf_oflags = mbf_oflags; + mbx_list_flags->mbf_sflag = mbf_sflag; + + return mbx_list_flags; +} + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags) +{ + clist_foreach(mbx_list_flags->mbf_oflags, + (clist_func) mailimap_mbx_list_oflag_free, + NULL); + clist_free(mbx_list_flags->mbf_oflags); + + free(mbx_list_flags); +} + + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext) +{ + struct mailimap_mbx_list_oflag * oflag; + + oflag = malloc(sizeof(* oflag)); + if (oflag == NULL) + return NULL; + + oflag->of_type = of_type; + oflag->of_flag_ext = of_flag_ext; + + return oflag; +} + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag) +{ + if (oflag->of_flag_ext != NULL) + mailimap_flag_extension_free(oflag->of_flag_ext); + free(oflag); +} + + + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name) +{ + struct mailimap_mailbox_list * mb_list; + + mb_list = malloc(sizeof(* mb_list)); + if (mb_list == NULL) + return NULL; + + mb_list->mb_flag = mbx_flags; + mb_list->mb_delimiter = mb_delimiter; + mb_list->mb_name = mb_name; + + return mb_list; +} + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list) +{ + if (mb_list->mb_flag != NULL) + mailimap_mbx_list_flags_free(mb_list->mb_flag); + if (mb_list->mb_name != NULL) + mailimap_mailbox_free(mb_list->mb_name); + free(mb_list); +} + + + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype) +{ + struct mailimap_media_basic * media_basic; + + media_basic = malloc(sizeof(* media_basic)); + if (media_basic == NULL) + return NULL; + media_basic->med_type = med_type; + media_basic->med_basic_type = med_basic_type; + media_basic->med_subtype = med_subtype; + + return media_basic; +} + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic) +{ + mailimap_string_free(media_basic->med_basic_type); + mailimap_media_subtype_free(media_basic->med_subtype); + free(media_basic); +} + + + +void mailimap_media_subtype_free(char * media_subtype) +{ + mmap_string_unref(media_subtype); +} + + +void mailimap_media_text_free(char * media_text) +{ + mailimap_media_subtype_free(media_text); +} + + + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att) +{ + struct mailimap_message_data * msg_data; + + msg_data = malloc(sizeof(* msg_data)); + if (msg_data == NULL) + free(msg_data); + + msg_data->mdt_number = mdt_number; + msg_data->mdt_type = mdt_type; + msg_data->mdt_msg_att = mdt_msg_att; + + return msg_data; +} + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data) +{ + if (msg_data->mdt_msg_att != NULL) + mailimap_msg_att_free(msg_data->mdt_msg_att); + free(msg_data); +} + + + + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static) +{ + struct mailimap_msg_att_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return item; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + item->att_data.att_dyn = att_dyn; + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + item->att_data.att_static = att_static; + break; + } + + return item; +} + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_free(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_free(item->att_data.att_static); + break; + } + free(item); +} + + +struct mailimap_msg_att * +mailimap_msg_att_new(clist * att_list) +{ + struct mailimap_msg_att * msg_att; + + msg_att = malloc(sizeof(* msg_att)); + if (msg_att == NULL) + return NULL; + + msg_att->att_list = att_list; + msg_att->att_number = 0; + + return msg_att; +} + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att) +{ + clist_foreach(msg_att->att_list, + (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(msg_att->att_list); + free(msg_att); +} + + + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list) +{ + struct mailimap_msg_att_dynamic * msg_att_dyn; + + msg_att_dyn = malloc(sizeof(* msg_att_dyn)); + if (msg_att_dyn == NULL) + return NULL; + + msg_att_dyn->att_list = att_list; + + return msg_att_dyn; +} + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn) +{ + if (msg_att_dyn->att_list != NULL) { + clist_foreach(msg_att_dyn->att_list, + (clist_func) mailimap_flag_fetch_free, + NULL); + clist_free(msg_att_dyn->att_list); + } + free(msg_att_dyn); +} + + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * sec_section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length) +{ + struct mailimap_msg_att_body_section * msg_att_body_section; + + msg_att_body_section = malloc(sizeof(* msg_att_body_section)); + if (msg_att_body_section == NULL) + return NULL; + + msg_att_body_section->sec_section = sec_section; + msg_att_body_section->sec_origin_octet = sec_origin_octet; + msg_att_body_section->sec_body_part = sec_body_part; + msg_att_body_section->sec_length = sec_length; + + return msg_att_body_section; +} + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section) +{ + if (msg_att_body_section->sec_section != NULL) + mailimap_section_free(msg_att_body_section->sec_section); + if (msg_att_body_section->sec_body_part != NULL) + mailimap_nstring_free(msg_att_body_section->sec_body_part); + free(msg_att_body_section); +} + + + + + + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env) +{ + mailimap_envelope_free(env); +} + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time) +{ + mailimap_date_time_free(date_time); +} + +void +mailimap_msg_att_rfc822_free(char * str) +{ + mailimap_nstring_free(str); +} + + +void +mailimap_msg_att_rfc822_header_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_rfc822_text_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_body_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + + + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid) +{ + struct mailimap_msg_att_static * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return FALSE; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + item->att_data.att_env = att_env; + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + item->att_data.att_internal_date = att_internal_date; + break; + case MAILIMAP_MSG_ATT_RFC822: + item->att_data.att_rfc822.att_content = att_rfc822; + item->att_data.att_rfc822.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + item->att_data.att_rfc822_header.att_content = att_rfc822_header; + item->att_data.att_rfc822_header.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + item->att_data.att_rfc822_text.att_content = att_rfc822_text; + item->att_data.att_rfc822_text.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_SIZE: + item->att_data.att_rfc822_size = att_rfc822_size; + break; + case MAILIMAP_MSG_ATT_BODY: + item->att_data.att_body = att_body; + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + item->att_data.att_bodystructure = att_bodystructure; + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + item->att_data.att_body_section = att_body_section; + break; + case MAILIMAP_MSG_ATT_UID: + item->att_data.att_uid = att_uid; + break; + } + + return item; +} + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + if (item->att_data.att_env != NULL) + mailimap_msg_att_envelope_free(item->att_data.att_env); + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + if (item->att_data.att_internal_date != NULL) + mailimap_msg_att_internaldate_free(item->att_data.att_internal_date); + break; + case MAILIMAP_MSG_ATT_RFC822: + if (item->att_data.att_rfc822.att_content != NULL) + mailimap_msg_att_rfc822_free(item->att_data.att_rfc822.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + if (item->att_data.att_rfc822_header.att_content != NULL) + mailimap_msg_att_rfc822_header_free(item->att_data.att_rfc822_header.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + if (item->att_data.att_rfc822_text.att_content != NULL) + mailimap_msg_att_rfc822_text_free(item->att_data.att_rfc822_text.att_content); + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (item->att_data.att_bodystructure != NULL) + mailimap_msg_att_bodystructure_free(item->att_data.att_bodystructure); + break; + case MAILIMAP_MSG_ATT_BODY: + if (item->att_data.att_body != NULL) + mailimap_msg_att_body_free(item->att_data.att_body); + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (item->att_data.att_body_section != NULL) + mailimap_msg_att_body_section_free(item->att_data.att_body_section); + break; + } + free(item); +} + + + + +void mailimap_nstring_free(char * str) +{ + if (str != NULL) + mailimap_string_free(str); +} + + + + + + + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data) +{ + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = malloc(sizeof(* cont_req_or_resp_data)); + if (cont_req_or_resp_data == NULL) + return NULL; + + cont_req_or_resp_data->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + cont_req_or_resp_data->rsp_data.rsp_cont_req = rsp_cont_req; + break; + case MAILIMAP_RESP_RESP_DATA: + cont_req_or_resp_data->rsp_data.rsp_resp_data = rsp_resp_data; + break; + } + + return cont_req_or_resp_data; +} + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data) +{ + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + if (cont_req_or_resp_data->rsp_data.rsp_cont_req != NULL) + mailimap_continue_req_free(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + if (cont_req_or_resp_data->rsp_data.rsp_resp_data != NULL) + mailimap_response_data_free(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + free(cont_req_or_resp_data); +} + + + + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done) +{ + struct mailimap_response * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + + resp->rsp_cont_req_or_resp_data_list = rsp_cont_req_or_resp_data_list; + resp->rsp_resp_done = rsp_resp_done; + + return resp; +} + +void +mailimap_response_free(struct mailimap_response * resp) +{ + if (resp->rsp_cont_req_or_resp_data_list != NULL) { + clist_foreach(resp->rsp_cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(resp->rsp_cont_req_or_resp_data_list); + } + mailimap_response_done_free(resp->rsp_resp_done); + free(resp); +} + + + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data) +{ + struct mailimap_response_data * resp_data; + + resp_data = malloc(sizeof(* resp_data)); + if (resp_data == NULL) + return NULL; + resp_data->rsp_type = rsp_type; + + switch (rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_data->rsp_data.rsp_cond_state = rsp_cond_state; + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + resp_data->rsp_data.rsp_bye = rsp_bye; + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + resp_data->rsp_data.rsp_mailbox_data = rsp_mailbox_data; + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + resp_data->rsp_data.rsp_message_data = rsp_message_data; + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + resp_data->rsp_data.rsp_capability_data = rsp_capability_data; + break; + } + + return resp_data; +} + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data) +{ + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + if (resp_data->rsp_data.rsp_cond_state != NULL) + mailimap_resp_cond_state_free(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + if (resp_data->rsp_data.rsp_bye != NULL) + mailimap_resp_cond_bye_free(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + if (resp_data->rsp_data.rsp_mailbox_data != NULL) + mailimap_mailbox_data_free(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + if (resp_data->rsp_data.rsp_message_data != NULL) + mailimap_message_data_free(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (resp_data->rsp_data.rsp_capability_data != NULL) + mailimap_capability_data_free(resp_data->rsp_data.rsp_capability_data); + break; + } + free(resp_data); +} + + + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal) +{ + struct mailimap_response_done * resp_done; + + resp_done = malloc(sizeof(* resp_done)); + if (resp_done == NULL) + return NULL; + + resp_done->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + resp_done->rsp_data.rsp_tagged = rsp_tagged; + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + resp_done->rsp_data.rsp_fatal = rsp_fatal; + break; + } + + return resp_done; +} + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done) +{ + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_free(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_free(resp_done->rsp_data.rsp_fatal); + break; + } + free(resp_done); +} + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye) +{ + struct mailimap_response_fatal * resp_fatal; + + resp_fatal = malloc(sizeof(* resp_fatal)); + if (resp_fatal == NULL) + return NULL; + + resp_fatal->rsp_bye = rsp_bye; + + return NULL; +} + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal) +{ + mailimap_resp_cond_bye_free(resp_fatal->rsp_bye); + free(resp_fatal); +} + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state) +{ + struct mailimap_response_tagged * resp_tagged; + + resp_tagged = malloc(sizeof(* resp_tagged)); + if (resp_tagged == NULL) + return NULL; + + resp_tagged->rsp_tag = rsp_tag; + resp_tagged->rsp_cond_state = rsp_cond_state; + + return resp_tagged; +} + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged) +{ + mailimap_tag_free(tagged->rsp_tag); + mailimap_resp_cond_state_free(tagged->rsp_cond_state); + free(tagged); +} + + + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_auth * cond_auth; + + cond_auth = malloc(sizeof(* cond_auth)); + if (cond_auth == NULL) + return NULL; + + cond_auth->rsp_type = rsp_type; + cond_auth->rsp_text = rsp_text; + + return cond_auth; +} + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth) +{ + mailimap_resp_text_free(cond_auth->rsp_text); + free(cond_auth); +} + + + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_bye * cond_bye; + + cond_bye = malloc(sizeof(* cond_bye)); + if (cond_bye == NULL) + return NULL; + + cond_bye->rsp_text = rsp_text; + + return cond_bye; +} + + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye) +{ + mailimap_resp_text_free(cond_bye->rsp_text); + free(cond_bye); +} + + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_state * cond_state; + + cond_state = malloc(sizeof(* cond_state)); + if (cond_state == NULL) + return NULL; + + cond_state->rsp_type = rsp_type; + cond_state->rsp_text = rsp_text; + + return cond_state; +} + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state) +{ + mailimap_resp_text_free(cond_state->rsp_text); + free(cond_state); +} + + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * rsp_code, + char * rsp_text) +{ + struct mailimap_resp_text * resp_text; + + resp_text = malloc(sizeof(* resp_text)); + if (resp_text == NULL) + return NULL; + + resp_text->rsp_code = rsp_code; + resp_text->rsp_text = rsp_text; + + return resp_text; +} + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text) +{ + if (resp_text->rsp_code) + mailimap_resp_text_code_free(resp_text->rsp_code); + if (resp_text->rsp_text) + mailimap_text_free(resp_text->rsp_text); + free(resp_text); +} + + + + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = malloc(sizeof(* resp_text_code)); + if (resp_text_code == NULL) + return NULL; + + resp_text_code->rc_type = rc_type; + switch (rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + resp_text_code->rc_data.rc_badcharset = rc_badcharset; + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + resp_text_code->rc_data.rc_cap_data = rc_cap_data; + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + resp_text_code->rc_data.rc_perm_flags = rc_perm_flags; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code->rc_data.rc_uidnext = rc_uidnext; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code->rc_data.rc_uidvalidity = rc_uidvalidity; + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code->rc_data.rc_first_unseen = rc_first_unseen; + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + resp_text_code->rc_data.rc_atom.atom_name = rc_atom; + resp_text_code->rc_data.rc_atom.atom_value = rc_atom_value; + break; + } + + return resp_text_code; +} + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code) +{ + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (resp_text_code->rc_data.rc_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, + NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (resp_text_code->rc_data.rc_cap_data != NULL) + mailimap_capability_data_free(resp_text_code->rc_data.rc_cap_data); + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (resp_text_code->rc_data.rc_perm_flags != NULL) { + clist_foreach(resp_text_code->rc_data.rc_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(resp_text_code->rc_data.rc_perm_flags); + } + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (resp_text_code->rc_data.rc_atom.atom_name != NULL) + mailimap_atom_free(resp_text_code->rc_data.rc_atom.atom_name); + if (resp_text_code->rc_data.rc_atom.atom_value != NULL) + mailimap_custom_string_free(resp_text_code->rc_data.rc_atom.atom_value); + break; + } + free(resp_text_code); +} + + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec) +{ + struct mailimap_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_spec = sec_spec; + + return section; +} + +void mailimap_section_free(struct mailimap_section * section) +{ + if (section->sec_spec != NULL) + mailimap_section_spec_free(section->sec_spec); + free(section); +} + + + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list) +{ + struct mailimap_section_msgtext * msgtext; + + msgtext = malloc(sizeof(* msgtext)); + if (msgtext == NULL) + return FALSE; + + msgtext->sec_type = sec_type; + msgtext->sec_header_list = sec_header_list; + + return msgtext; +} + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext) +{ + if (msgtext->sec_header_list != NULL) + mailimap_header_list_free(msgtext->sec_header_list); + free(msgtext); +} + + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id) +{ + struct mailimap_section_part * section_part; + + section_part = malloc(sizeof(* section_part)); + if (section_part == NULL) + return NULL; + + section_part->sec_id = sec_id; + + return section_part; +} + +void +mailimap_section_part_free(struct mailimap_section_part * section_part) +{ + clist_foreach(section_part->sec_id, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_part->sec_id); + free(section_part); +} + + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text) +{ + struct mailimap_section_spec * section_spec; + + section_spec = malloc(sizeof(* section_spec)); + if (section_spec == NULL) + return NULL; + + section_spec->sec_type = sec_type; + switch (sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + section_spec->sec_data.sec_msgtext = sec_msgtext; + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + section_spec->sec_data.sec_part = sec_part; + break; + } + section_spec->sec_text = sec_text; + + return section_spec; +} + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec) +{ + if (section_spec->sec_text) + mailimap_section_text_free(section_spec->sec_text); + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_PART: + if (section_spec->sec_data.sec_part != NULL) + mailimap_section_part_free(section_spec->sec_data.sec_part); + break; + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + /* handle case where it can be detached */ + if (section_spec->sec_data.sec_msgtext != NULL) + mailimap_section_msgtext_free(section_spec->sec_data.sec_msgtext); + break; + } + free(section_spec); +} + + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext) +{ + struct mailimap_section_text * section_text; + + section_text = malloc(sizeof(* section_text)); + if (section_text == NULL) + return NULL; + + section_text->sec_type = sec_type; + section_text->sec_msgtext = sec_msgtext; + + return section_text; +} + +void +mailimap_section_text_free(struct mailimap_section_text * section_text) +{ + if (section_text->sec_msgtext != NULL) + mailimap_section_msgtext_free(section_text->sec_msgtext); + free(section_text); +} + + + + +void +mailimap_string_free(char * str) +{ + mmap_string_unref(str); +} + + + + + +void mailimap_tag_free(char * tag) +{ + mailimap_custom_string_free(tag); +} + + +void mailimap_text_free(char * text) +{ + mailimap_custom_string_free(text); +} + + + + + + + + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* sender only */ + + +/* COPY FETCH SEARCH STORE */ +/* set */ + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last) +{ + struct mailimap_set_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->set_first = set_first; + item->set_last = set_last; + + return item; +} + +void mailimap_set_item_free(struct mailimap_set_item * set_item) +{ + free(set_item); +} + +struct mailimap_set * mailimap_set_new(clist * set_list) +{ + struct mailimap_set * set; + + set = malloc(sizeof(* set)); + if (set == NULL) + return NULL; + + set->set_list = set_list; + + return set; +} + +void mailimap_set_free(struct mailimap_set * set) +{ + clist_foreach(set->set_list, (clist_func) mailimap_set_item_free, NULL); + clist_free(set->set_list); + free(set); +} + +/* SEARCH with date key */ +/* date */ + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year) +{ + struct mailimap_date * date; + + date = malloc(sizeof(* date)); + if (date == NULL) + return NULL; + + date->dt_day = dt_day; + date->dt_month = dt_month; + date->dt_year = dt_year; + + return date; +} + +void mailimap_date_free(struct mailimap_date * date) +{ + free(date); +} + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size) +{ + struct mailimap_fetch_att * fetch_att; + + fetch_att = malloc(sizeof(* fetch_att)); + if (fetch_att == NULL) + return NULL; + fetch_att->att_type = att_type; + fetch_att->att_section = att_section; + fetch_att->att_offset = att_offset; + fetch_att->att_size = att_size; + + return fetch_att; +} + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att) +{ + if (fetch_att->att_section != NULL) + mailimap_section_free(fetch_att->att_section); + free(fetch_att); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list) +{ + struct mailimap_fetch_type * fetch_type; + + fetch_type = malloc(sizeof(* fetch_type)); + if (fetch_type == NULL) + return NULL; + fetch_type->ft_type = ft_type; + switch (ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + fetch_type->ft_data.ft_fetch_att = ft_fetch_att; + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + fetch_type->ft_data.ft_fetch_att_list = ft_fetch_att_list; + break; + } + + return fetch_type; +} + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + mailimap_fetch_att_free(fetch_type->ft_data.ft_fetch_att); + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + clist_foreach(fetch_type->ft_data.ft_fetch_att_list, + (clist_func) mailimap_fetch_att_free, NULL); + clist_free(fetch_type->ft_data.ft_fetch_att_list); + break; + } + free(fetch_type); +} + + + + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list) +{ + struct mailimap_store_att_flags * store_att_flags; + + store_att_flags = malloc(sizeof(* store_att_flags)); + if (store_att_flags == NULL) + return NULL; + + store_att_flags->fl_sign = fl_sign; + store_att_flags->fl_silent = fl_silent; + store_att_flags->fl_flag_list = fl_flag_list; + + return store_att_flags; +} + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags) +{ + mailimap_flag_list_free(store_att_flags->fl_flag_list); + free(store_att_flags); +} + + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + switch (sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + key->sk_data.sk_bcc = sk_bcc; + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + key->sk_data.sk_before = sk_before; + break; + case MAILIMAP_SEARCH_KEY_BODY: + key->sk_data.sk_body = sk_body; + break; + case MAILIMAP_SEARCH_KEY_CC: + key->sk_data.sk_cc = sk_cc; + break; + case MAILIMAP_SEARCH_KEY_FROM: + key->sk_data.sk_from = sk_from; + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + key->sk_data.sk_keyword = sk_keyword; + break; + case MAILIMAP_SEARCH_KEY_ON: + key->sk_data.sk_on = sk_on; + break; + case MAILIMAP_SEARCH_KEY_SINCE: + key->sk_data.sk_since = sk_since; + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + key->sk_data.sk_subject = sk_subject; + break; + case MAILIMAP_SEARCH_KEY_TEXT: + key->sk_data.sk_text = sk_text; + break; + case MAILIMAP_SEARCH_KEY_TO: + key->sk_data.sk_to = sk_to; + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + key->sk_data.sk_unkeyword = sk_unkeyword; + break; + case MAILIMAP_SEARCH_KEY_HEADER: + key->sk_data.sk_header.sk_header_name = sk_header_name; + key->sk_data.sk_header.sk_header_value = sk_header_value; + break; + case MAILIMAP_SEARCH_KEY_LARGER: + key->sk_data.sk_larger = sk_larger; + break; + case MAILIMAP_SEARCH_KEY_NOT: + key->sk_data.sk_not = sk_not; + break; + case MAILIMAP_SEARCH_KEY_OR: + key->sk_data.sk_or.sk_or1 = sk_or1; + key->sk_data.sk_or.sk_or2 = sk_or2; + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + key->sk_data.sk_sentbefore = sk_sentbefore; + break; + case MAILIMAP_SEARCH_KEY_SENTON: + key->sk_data.sk_senton = sk_senton; + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + key->sk_data.sk_sentsince = sk_sentsince; + break; + case MAILIMAP_SEARCH_KEY_SMALLER: + key->sk_data.sk_smaller = sk_smaller; + break; + case MAILIMAP_SEARCH_KEY_UID: + key->sk_data.sk_uid = sk_uid; + break; + case MAILIMAP_SEARCH_KEY_SET: + key->sk_data.sk_set = sk_set; + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + key->sk_data.sk_multiple = sk_multiple; + break; + } + return key; +} + + +void mailimap_search_key_free(struct mailimap_search_key * key) +{ + switch (key->sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + mailimap_astring_free(key->sk_data.sk_bcc); + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + mailimap_date_free(key->sk_data.sk_before); + break; + case MAILIMAP_SEARCH_KEY_BODY: + mailimap_astring_free(key->sk_data.sk_body); + break; + case MAILIMAP_SEARCH_KEY_CC: + mailimap_astring_free(key->sk_data.sk_cc); + break; + case MAILIMAP_SEARCH_KEY_FROM: + mailimap_astring_free(key->sk_data.sk_from); + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_keyword); + break; + case MAILIMAP_SEARCH_KEY_ON: + mailimap_date_free(key->sk_data.sk_on); + break; + case MAILIMAP_SEARCH_KEY_SINCE: + mailimap_date_free(key->sk_data.sk_since); + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + mailimap_astring_free(key->sk_data.sk_subject); + break; + case MAILIMAP_SEARCH_KEY_TEXT: + mailimap_astring_free(key->sk_data.sk_text); + break; + case MAILIMAP_SEARCH_KEY_TO: + mailimap_astring_free(key->sk_data.sk_to); + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_unkeyword); + break; + case MAILIMAP_SEARCH_KEY_HEADER: + mailimap_header_fld_name_free(key->sk_data.sk_header.sk_header_name); + mailimap_astring_free(key->sk_data.sk_header.sk_header_value); + break; + case MAILIMAP_SEARCH_KEY_NOT: + mailimap_search_key_free(key->sk_data.sk_not); + break; + case MAILIMAP_SEARCH_KEY_OR: + mailimap_search_key_free(key->sk_data.sk_or.sk_or1); + mailimap_search_key_free(key->sk_data.sk_or.sk_or2); + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + mailimap_date_free(key->sk_data.sk_sentbefore); + break; + case MAILIMAP_SEARCH_KEY_SENTON: + mailimap_date_free(key->sk_data.sk_senton); + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + mailimap_date_free(key->sk_data.sk_sentsince); + break; + case MAILIMAP_SEARCH_KEY_UID: + mailimap_set_free(key->sk_data.sk_uid); + break; + case MAILIMAP_SEARCH_KEY_SET: + mailimap_set_free(key->sk_data.sk_set); + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + clist_foreach(key->sk_data.sk_multiple, + (clist_func) mailimap_search_key_free, NULL); + clist_free(key->sk_data.sk_multiple); + break; + } + + free(key); +} + + + + + + + + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list) +{ + struct mailimap_status_att_list * status_att_list; + + status_att_list = malloc(sizeof(* status_att_list)); + if (status_att_list == NULL) + return NULL; + status_att_list->att_list = att_list; + + return status_att_list; +} + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list) +{ + clist_foreach(status_att_list->att_list, (clist_func) free, NULL); + clist_free(status_att_list->att_list); + free(status_att_list); +} + + + + +/* main */ + + +struct mailimap_selection_info * +mailimap_selection_info_new(void) +{ + struct mailimap_selection_info * sel_info; + + sel_info = malloc(sizeof(* sel_info)); + if (sel_info == NULL) + return NULL; + + sel_info->sel_perm_flags = NULL; + sel_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + sel_info->sel_uidnext = 0; + sel_info->sel_uidvalidity = 0; + sel_info->sel_first_unseen = 0; + sel_info->sel_flags = NULL; + sel_info->sel_exists = 0; + sel_info->sel_recent = 0; + sel_info->sel_unseen = 0; + + return sel_info; +} + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info) +{ + if (sel_info->sel_perm_flags != NULL) { + clist_foreach(sel_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(sel_info->sel_perm_flags); + } + if (sel_info->sel_flags) + mailimap_flag_list_free(sel_info->sel_flags); + + free(sel_info); +} + +struct mailimap_connection_info * +mailimap_connection_info_new(void) +{ + struct mailimap_connection_info * conn_info; + + conn_info = malloc(sizeof(* conn_info)); + if (conn_info == NULL) + return NULL; + + conn_info->imap_capability = NULL; + + return conn_info; +} + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info) +{ + if (conn_info->imap_capability != NULL) + mailimap_capability_data_free(conn_info->imap_capability); + free(conn_info); +} + +struct mailimap_response_info * +mailimap_response_info_new(void) +{ + struct mailimap_response_info * resp_info; + + resp_info = malloc(sizeof(* resp_info)); + if (resp_info == NULL) + goto err; + + resp_info->rsp_alert = NULL; + resp_info->rsp_parse = NULL; + resp_info->rsp_badcharset = NULL; + resp_info->rsp_trycreate = FALSE; + resp_info->rsp_mailbox_list = clist_new(); + if (resp_info->rsp_mailbox_list == NULL) + goto free; + resp_info->rsp_mailbox_lsub = clist_new(); + if (resp_info->rsp_mailbox_lsub == NULL) + goto free_mb_list; + resp_info->rsp_search_result = clist_new(); + if (resp_info->rsp_search_result == NULL) + goto free_mb_lsub; + resp_info->rsp_status = NULL; + resp_info->rsp_expunged = clist_new(); + if (resp_info->rsp_expunged == NULL) + goto free_search_result; + resp_info->rsp_fetch_list = clist_new(); + if (resp_info->rsp_fetch_list == NULL) + goto free_expunged; + + return resp_info; + + free_expunged: + clist_free(resp_info->rsp_expunged); + free_search_result: + clist_free(resp_info->rsp_search_result); + free_mb_lsub: + clist_free(resp_info->rsp_mailbox_lsub); + free_mb_list: + clist_free(resp_info->rsp_mailbox_list); + free: + free(resp_info); + err: + return NULL; +} + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info) +{ + if (resp_info->rsp_alert != NULL) + free(resp_info->rsp_alert); + if (resp_info->rsp_parse != NULL) + free(resp_info->rsp_parse); + if (resp_info->rsp_badcharset != NULL) { + clist_foreach(resp_info->rsp_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_info->rsp_badcharset); + } + if (resp_info->rsp_mailbox_list != NULL) { + clist_foreach(resp_info->rsp_mailbox_list, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_list); + } + if (resp_info->rsp_mailbox_lsub != NULL) { + clist_foreach(resp_info->rsp_mailbox_lsub, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_lsub); + } + if (resp_info->rsp_search_result != NULL) + mailimap_mailbox_data_search_free(resp_info->rsp_search_result); + if (resp_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(resp_info->rsp_status); + if (resp_info->rsp_expunged != NULL) { + clist_foreach(resp_info->rsp_expunged, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(resp_info->rsp_expunged); + } + if (resp_info->rsp_fetch_list != NULL) { + clist_foreach(resp_info->rsp_fetch_list, + (clist_func) mailimap_msg_att_free, NULL); + clist_free(resp_info->rsp_fetch_list); + } + + free(resp_info); +} diff --git a/kmicromail/libetpan/imap/mailimap_types.h b/kmicromail/libetpan/imap/mailimap_types.h new file mode 100644 index 0000000..2996b53 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types.h @@ -0,0 +1,3274 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] + + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" + + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + lsub = "LSUB" SP mailbox SP list-mailbox + + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. + + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" + + section = "[" [section-spec] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. + + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1* + + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" ', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" ', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" ', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART, /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST, /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* != NULL */ +}; + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER, /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME, /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64, /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* != NULL */ +}; + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION, /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER, /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE, /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of + unseen messages */ +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or + MAILIMAP_STATUS_ATT_UNSEEN + + - value is the value of the given information +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; +}; + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value); + +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + } mbd_data; +}; + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent); + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG, /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER, /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes + (message content) */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC + + - msg_att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - msg_att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + } att_data; +}; + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static); + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID, /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA, /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a reponse data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data); + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL, /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH, /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state reponse + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + } rc_data; +}; + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value); + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT, /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART, /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME, /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +struct mailimap_set * mailimap_set_new(clist * list); + +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without + marking the message as read */ +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; +}; + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size); + + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the + conditions is AND */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + + +void mailimap_search_key_free(struct mailimap_search_key * key); + + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number); + +void mailimap_number_alloc_free(uint32_t * pnumber); + + +void mailimap_addr_host_free(char * addr_host); + +void mailimap_addr_mailbox_free(char * addr_mailbox); + +void mailimap_addr_adl_free(char * addr_adl); + +void mailimap_addr_name_free(char * addr_name); + +void mailimap_astring_free(char * astring); + +void mailimap_atom_free(char * atom); + +void mailimap_auth_type_free(char * auth_type); + +void mailimap_base64_free(char * base64); + +void mailimap_body_fld_desc_free(char * body_fld_desc); + +void mailimap_body_fld_id_free(char * body_fld_id); + +void mailimap_body_fld_md5_free(char * body_fld_md5); + +void mailimap_env_date_free(char * date); + +void mailimap_env_in_reply_to_free(char * in_reply_to); + +void mailimap_env_message_id_free(char * message_id); + +void mailimap_env_subject_free(char * subject); + +void mailimap_flag_extension_free(char * flag_extension); + +void mailimap_flag_keyword_free(char * flag_keyword); + +void +mailimap_header_fld_name_free(char * header_fld_name); + +void mailimap_literal_free(char * literal); + +void mailimap_mailbox_free(char * mailbox); + +void +mailimap_mailbox_data_search_free(clist * data_search); + +void mailimap_media_subtype_free(char * media_subtype); + +void mailimap_media_text_free(char * media_text); + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +void +mailimap_msg_att_rfc822_free(char * str); + +void +mailimap_msg_att_rfc822_header_free(char * str); + +void +mailimap_msg_att_rfc822_text_free(char * str); + +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +void mailimap_nstring_free(char * str); + +void +mailimap_string_free(char * str); + +void mailimap_tag_free(char * tag); + +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a reponse, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; +}; + +typedef struct mailimap mailimap; + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; +}; + +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ +}; + +struct mailimap_response_info * +mailimap_response_info_new(void); + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/imap/mailimap_types_helper.c b/kmicromail/libetpan/imap/mailimap_types_helper.c new file mode 100644 index 0000000..8fe273e --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types_helper.c @@ -0,0 +1,1269 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimap_types.h" +#include "mail.h" + +#include + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* in helper */ + + + + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index) +{ + return mailimap_set_item_new(index, index); +} + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item) +{ + struct mailimap_set * set; + clist * list; + int r; + + list = clist_new(); + if (list == NULL) + return NULL; + + r = clist_append(list, item); + if (r < 0) { + clist_free(list); + return NULL; + } + + set = mailimap_set_new(list); + if (set == NULL) { + clist_free(list); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + struct mailimap_set * set; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return NULL; + + set = mailimap_set_new_single_item(item); + if (set == NULL) { + mailimap_set_item_free(item); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_single(uint32_t index) +{ + return mailimap_set_new_interval(index, index); +} + + +struct mailimap_set * mailimap_set_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_set_new(list); +} + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item) +{ + int r; + + r = clist_append(set->set_list, set_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + int r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = mailimap_set_add(set, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + return r; + } + else + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index) +{ + return mailimap_set_add_interval(set, index, index); +} + +/* CHECK */ +/* no args */ + +/* CLOSE */ +/* no args */ + +/* EXPUNGE */ +/* no args */ + +/* COPY */ +/* set and gchar */ + +/* FETCH */ +/* set and gchar fetch_type */ + + + +/* section */ + +#if 0 +/* not correct XXX */ + +struct mailimap_section * mailimap_section_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_section_new(list); +} +#endif + +static struct mailimap_section * +mailimap_section_new_msgtext(struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, + msgtext, NULL, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + spec->sec_data.sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +static struct mailimap_section * +mailimap_section_new_part_msgtext(struct mailimap_section_part * part, + struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, + msgtext); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +/* +HEADER +HEADER.FIELDS fields +HEADER.FIELDS.NOT fields +TEXT +*/ + +struct mailimap_section * mailimap_section_new_header(void) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * mailimap_section_new_text(void) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* +section-part +section-part . MIME +section-part . HEADER +section-part . HEADER.FIELDS fields +section-part . HEADER.FIELDS.NOT fields +section-part . TEXT +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_MIME, NULL); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* end of section */ + + + + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_ENVELOPE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_FLAGS, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_INTERNALDATE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_HEADER, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_SIZE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_TEXT, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODYSTRUCTURE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_UID, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, + offset, size); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, + offset, size); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_ALL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FULL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FAST, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT, fetch_att, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, fetch_att_list); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, list); +} + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + r = clist_append(fetch_type->ft_data.ft_fetch_att_list, fetch_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* STORE */ +/* set and store_att_flags */ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(0, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(0, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(1, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(-1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(-1, TRUE, flags); +} + +/* SEARCH */ +/* date search-key set */ + +/* + return mailimap_search_key_new(type, bcc, before, + body, cc, from, keyword, on, since, + subject, text, to, unkeyword, header_name, + header_value, larger, not, + or1, or2, sentbefore, senton, sentsince, + smaller, uid, set, multiple); +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ALL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BCC, sk_bcc, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BEFORE, NULL, sk_before, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BODY, NULL, NULL, + sk_body, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_CC, NULL, NULL, + NULL, sk_cc, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, sk_from, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, NULL, sk_keyword, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ON, NULL, NULL, + NULL, NULL, NULL, NULL, sk_on, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, sk_since, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + sk_subject, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TEXT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, sk_text, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TO, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, sk_to, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNKEYWORD, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, sk_unkeyword, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_HEADER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, sk_header_name, + sk_header_value, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_LARGER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, sk_larger, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, sk_not, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_OR, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + sk_or1, sk_or2, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, sk_sentbefore, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTON, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, sk_senton, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTSINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, sk_sentsince, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SMALLER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + sk_smaller, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UID, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, sk_uid, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SET, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, sk_set, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_MULTIPLE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, sk_multiple); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_search_key_new_multiple(list); +} + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item) +{ + int r; + + r = clist_append(keys->sk_data.sk_multiple, key_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* CAPABILITY */ +/* no args */ + +/* LOGOUT */ +/* no args */ + +/* NOOP */ +/* no args */ + +/* APPEND */ +/* gchar flag_list date_time gchar */ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_flag_list_new(list); +} + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f) +{ + int r; + + r = clist_append(flag_list->fl_list, f); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +struct mailimap_flag * mailimap_flag_new_answered(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_ANSWERED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flagged(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_FLAGGED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_deleted(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DELETED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_seen(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_SEEN, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_draft(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DRAFT, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword) +{ + return mailimap_flag_new(MAILIMAP_FLAG_KEYWORD, flag_keyword, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension) +{ + return mailimap_flag_new(MAILIMAP_FLAG_EXTENSION, NULL, flag_extension); +} + + + + +/* CREATE */ +/* gchar */ + +/* DELETE */ +/* gchar */ + +/* EXAMINE */ +/* gchar */ + +/* LIST */ +/* gchar gchar */ + +/* LSUB */ +/* gchar gchar */ + +/* RENAME */ +/* gchar gchar */ + +/* SELECT */ +/* gchar */ + +/* STATUS */ +/* gchar GList of status_att */ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_status_att_list_new(list); +} + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att) +{ + int * pstatus_att; + int r; + + pstatus_att = malloc(sizeof(* pstatus_att)); + * pstatus_att = status_att; + + r = clist_append(sa_list->att_list, pstatus_att); + if (r < 0) { + free(pstatus_att); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +/* SUBSCRIBE */ +/* gchar */ + +/* UNSUBSCRIBE */ +/* gchar */ + +/* LOGIN */ +/* gchar gchar */ + +/* AUTHENTICATE */ +/* gchar */ + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result); + +static int try_build_part(struct mailimap_body * root_part, + struct mailimap_body * part, uint32_t count, + clist ** result) +{ + int r; + clist * imap_id_list; + uint32_t * id; + + r = recursive_build_path(root_part, part, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + id = malloc(sizeof(* id)); + if (id == NULL) { + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * id = count; + + r = clist_prepend(imap_id_list, id); + if (r < 0) { + free(id); + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; +} + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result) +{ + clistiter * cur; + uint32_t count; + int r; + clist * imap_id_list; + + if (part == root_part) { + imap_id_list = clist_new(); + if (imap_id_list == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; + } + + switch (root_part->bd_type) { + case MAILIMAP_BODY_MPART: + count = 0; + for(cur = clist_begin(root_part->bd_data.bd_body_mpart->bd_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_body * current_part; + + current_part = clist_content(cur); + count ++; + + r = try_build_part(current_part, part, count, &imap_id_list); + if (r == MAILIMAP_ERROR_INVAL) { + continue; + } if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + return MAILIMAP_ERROR_INVAL; + + case MAILIMAP_BODY_1PART: + if (root_part->bd_data.bd_body_1part->bd_type == + MAILIMAP_BODY_TYPE_1PART_MSG) { + struct mailimap_body * current_part; + + current_part = + root_part->bd_data.bd_body_1part->bd_data.bd_type_msg->bd_body; + + r = try_build_part(current_part, part, 1, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + else { + return MAILIMAP_ERROR_INVAL; + } + break; + + default: + return MAILIMAP_ERROR_INVAL; + } +} + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result) +{ + struct mailimap_section_part * section_part; + clist * id_list; + int r; + int res; + + r = recursive_build_path(root_part, part, &id_list); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(id_list); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = section_part; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(id_list, (clist_func) free, NULL); + clist_free(id_list); + err: + return res; +} diff --git a/kmicromail/libetpan/imap/mailimap_types_helper.h b/kmicromail/libetpan/imap/mailimap_types_helper.h new file mode 100644 index 0000000..bb0bb99 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types_helper.h @@ -0,0 +1,758 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by index +*/ + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index); + +/* + this function creates a new set with one set item + */ + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +struct mailimap_set * mailimap_set_new_single(uint32_t index); + +/* + this function creates an empty set of messages +*/ + +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +struct mailimap_section * mailimap_section_new_header(void); + +/* + this functions creates a mailimap_section structure to describe + a list of headers +*/ + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this functions creates a mailimap_section structure to describe headers + other than those given +*/ + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + +/* + this function creates an empty list of flags +*/ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imf/.libs/libmailimf.a b/kmicromail/libetpan/imf/.libs/libmailimf.a new file mode 100644 index 0000000..833c4f3 --- a/dev/null +++ b/kmicromail/libetpan/imf/.libs/libmailimf.a Binary files differ diff --git a/kmicromail/libetpan/imf/TODO b/kmicromail/libetpan/imf/TODO new file mode 100644 index 0000000..8fcd271 --- a/dev/null +++ b/kmicromail/libetpan/imf/TODO @@ -0,0 +1,16 @@ +- define a EP_parserstate_s +- structure to union +- remove clist usage +- add a errorcode to string function +- error codes are EP_errornr_s +- prefix everything with EP_ +- replace mailimf_write to fnprintf-like + fnprintf = fnprintf( int (*)(void *Data, char * + Buf, long l ), void * Data, char * Format, ... ) +- mailimf_dot_atom_text_free +- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr) +- in fact that data structure should then also contain a + 'dynamically' allocated flag + +- RFC 822 : test the examples +- RFC 2822 : obsolete syntax diff --git a/kmicromail/libetpan/imf/mailimf.c b/kmicromail/libetpan/imf/mailimf.c new file mode 100644 index 0000000..84d81a1 --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf.c @@ -0,0 +1,7585 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimf.h" + +/* + RFC 2822 + + RFC 2821 ... + A message-originating SMTP system SHOULD NOT send a message that + already contains a Return-path header. SMTP servers performing a + relay function MUST NOT inspect the message data, and especially not + to the extent needed to determine if Return-path headers are present. + SMTP servers making final delivery MAY remove Return-path headers + before adding their own. +*/ + +#include +#include +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + + + + + + +static inline int is_dtext(char ch); + +static int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result); + +static int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index); + +static int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index); + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * ch); + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear); + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * zone); +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec); + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr); + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result); + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** address); + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result); +#endif + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result); +#endif + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result); + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int +mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result); + +#if 0 +static int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** + result); +#endif + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result); + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result); + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result); + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result); + +static int +mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result); + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result); + + + + + + + + + + + + + + + + + + + + + + + + + +/* *************************************************************** */ + +static inline int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimf_digit_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_digit(message[cur_token])) { + * result = message[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * index; + parsed = FALSE; + + number = 0; + while (1) { + r = mailimf_digit_parse(message, length, &cur_token, &digit); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + number *= 10; + number += digit; + parsed = TRUE; + } + + if (!parsed) + return MAILIMF_ERROR_PARSE; + + * result = number; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + token_length - 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (strncasecmp(message + cur_token, token, token_length) == 0) { + cur_token += token_length; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +static int mailimf_oparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '('); +} + +static int mailimf_cparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, ')'); +} + +static int mailimf_comma_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ','); +} + +static int mailimf_dquote_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '\"'); +} + +static int mailimf_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ':'); +} + +static int mailimf_semi_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ';'); +} + +static int mailimf_plus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '+'); +} + +static int mailimf_minus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '-'); +} + +static int mailimf_lower_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '<'); +} + +static int mailimf_greater_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '>'); +} + +#if 0 +static int mailimf_obracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '['); +} + +static int mailimf_cbracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ']'); +} +#endif + +static int mailimf_at_sign_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '@'); +} + +static int mailimf_point_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '.'); +} + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + + end = begin; + + if (end >= length) + return MAILIMF_ERROR_PARSE; + + while (is_custom_char(message[end])) { + end ++; + if (end >= length) + break; + } + + if (end != begin) { + /* + gstr = strndup(message + begin, end - begin); + */ + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(gstr, message + begin, end - begin); + gstr[end - begin] = '\0'; + + * index = end; + * result = gstr; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + + + + + + + +typedef int mailimf_struct_parser(const char * message, size_t length, + size_t * index, void * result); + +typedef int mailimf_struct_destructor(void * result); + + +static int +mailimf_struct_multiple_parse(const char * message, size_t length, + size_t * index, clist ** result, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + while (1) { + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + r = clist_append(struct_list, value); + if (r < 0) { + (* destructor)(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + * result = struct_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + + + +static int +mailimf_struct_list_parse(const char * message, size_t length, + size_t * index, clist ** result, + char symbol, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + + while (1) { + r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + } + + * result = struct_list; + * index = final_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static inline int mailimf_wsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if ((message[cur_token] != ' ') && (message[cur_token] != '\t')) + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_crlf_parse(const char * message, + size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +/* ************************************************************************ */ + + + +/* RFC 2822 grammar */ + +/* +NO-WS-CTL = %d1-8 / ; US-ASCII control characters + %d11 / ; that do not include the + %d12 / ; carriage return, line feed, + %d14-31 / ; and white space characters + %d127 +*/ + +static inline int is_no_ws_ctl(char ch) +{ + if ((ch == 9) || (ch == 10) || (ch == 13)) + return FALSE; + + if (ch == 127) + return TRUE; + + return (ch >= 1) && (ch <= 31); +} + +/* +text = %d1-9 / ; Characters excluding CR and LF + %d11 / + %d12 / + %d14-127 / + obs-text +*/ + +/* +specials = "(" / ")" / ; Special characters used in + "<" / ">" / ; other parts of the syntax + "[" / "]" / + ":" / ";" / + "@" / "\" / + "," / "." / + DQUOTE +*/ + +/* +quoted-pair = ("\" text) / obs-qp +*/ + +static inline int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] != '\\') + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * result = message[cur_token]; + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + obs-FWS +*/ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + size_t final_token; + int fws_1; + int fws_2; + int fws_3; + int r; + + cur_token = * index; + + fws_1 = FALSE; + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_1 = TRUE; + } + final_token = cur_token; + + r = mailimf_crlf_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + fws_2 = TRUE; + break; + case MAILIMF_ERROR_PARSE: + fws_2 = FALSE; + break; + default: + return r; + } + + fws_3 = FALSE; + if (fws_2) { + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_3 = TRUE; + } + } + + if ((!fws_1) && (!fws_3)) + return MAILIMF_ERROR_PARSE; + + if (!fws_3) + cur_token = final_token; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +/* +ctext = NO-WS-CTL / ; Non white space controls + + %d33-39 / ; The rest of the US-ASCII + %d42-91 / ; characters not including "(", + %d93-126 ; ")", or "\" +*/ + +static inline int is_ctext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch == 40) || (uch == 41)) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +ccontent = ctext / quoted-pair / comment +*/ + +static inline int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_ctext(message[cur_token])) { + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_comment_parse(message, length, &cur_token); + + if (r == MAILIMF_ERROR_PARSE) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] ccontent +*/ + +static inline int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +comment = "(" *([FWS] ccontent) [FWS] ")" +*/ + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_oparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] comment +*/ + +static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CFWS = *([FWS] comment) (([FWS] comment) / FWS) +*/ + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int has_comment; + int r; + + cur_token = * index; + + has_comment = FALSE; + while (1) { + r = mailimf_cfws_fws_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + has_comment = TRUE; + } + + if (!has_comment) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static inline int is_atext(char ch) +{ + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': +#if 0 + case '(': + case ')': +#endif + case '<': + case '>': +#if 0 + case '@': +#endif + case ',': + case '"': + case ':': + case ';': + return FALSE; + default: + return TRUE; + } +} + +/* +atom = [CFWS] 1*atext [CFWS] +*/ + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +/* +dot-atom = [CFWS] dot-atom-text [CFWS] +*/ + +#if 0 +static int mailimf_dot_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +dot-atom-text = 1*atext *("." 1*atext) +*/ + +#if 0 +static int +mailimf_dot_atom_text_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +qtext = NO-WS-CTL / ; Non white space controls + + %d33 / ; The rest of the US-ASCII + %d35-91 / ; characters not including "\" + %d93-126 ; or the quote character +*/ + +static inline int is_qtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if (uch == 34) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +qcontent = qtext / quoted-pair +*/ + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * result = ch; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +quoted-string = [CFWS] + DQUOTE *([FWS] qcontent) [FWS] DQUOTE + [CFWS] +*/ + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +/* +word = atom / quoted-string +*/ + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_fws_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +phrase = 1*word / obs-phrase +*/ + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + MMAPString * gphrase; + char * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + r = mailimf_fws_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + if (mmap_string_append(gphrase, word) == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mailimf_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +/* +utext = NO-WS-CTL / ; Non white space controls + %d33-126 / ; The rest of US-ASCII + obs-utext + +added : WSP +*/ + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int state; + size_t begin; + size_t terminal; + char * str; + + cur_token = * index; + + + while (1) { + int r; + + r = mailimf_wsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + return r; + } + } + + state = UNSTRUCTURED_START; + begin = cur_token; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + str = malloc(terminal - begin + 1); + if (str == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(str, message + begin, terminal - begin); + str[terminal - begin] = '\0'; + + * index = terminal; + * result = str; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int state; + size_t terminal; + + cur_token = * index; + + state = UNSTRUCTURED_START; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index) +{ + int has_field; + size_t cur_token; + int state; + size_t terminal; + + has_field = FALSE; + cur_token = * index; + + terminal = cur_token; + state = UNSTRUCTURED_START; + + /* check if this is not a beginning CRLF */ + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '\r': + return MAILIMF_ERROR_PARSE; + case '\n': + return MAILIMF_ERROR_PARSE; + } + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + if (!has_field) + return MAILIMF_ERROR_PARSE; + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +/* +date-time = [ day-of-week "," ] date FWS time [CFWS] +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result) +{ + size_t cur_token; + int day_of_week; + struct mailimf_date_time * date_time; + int day; + int month; + int year; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + day_of_week = -1; + r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_comma_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r != MAILIMF_ERROR_PARSE) + return r; + + r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_time_parse(message, length, &cur_token, + &hour, &min, &sec, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMF_ERROR_MEMORY; + + * index = cur_token; + * result = date_time; + + return MAILIMF_NO_ERROR; +} + +/* +day-of-week = ([FWS] day-name) / obs-day-of-week +*/ + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = day_of_week; + + return MAILIMF_NO_ERROR; +} + +/* +day-name = "Mon" / "Tue" / "Wed" / "Thu" / + "Fri" / "Sat" / "Sun" +*/ + +struct mailimf_token_value { + int value; + char * str; +}; + +static struct mailimf_token_value day_names[] = { + {1, "Mon"}, + {2, "Tue"}, + {3, "Wed"}, + {4, "Thu"}, + {5, "Fri"}, + {6, "Sat"}, + {7, "Sun"}, +}; + +enum { + DAY_NAME_START, + DAY_NAME_T, + DAY_NAME_S +}; + +static int guess_day_name(const char * message, size_t length, size_t index) +{ + int state; + + state = DAY_NAME_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case DAY_NAME_START: + switch((char) toupper((unsigned char) message[index])) { + case 'M': /* Mon */ + return 1; + break; + case 'T': /* Tue Thu */ + state = DAY_NAME_T; + break; + case 'W': /* Wed */ + return 3; + case 'F': + return 5; + case 'S': /* Sat Sun */ + state = DAY_NAME_S; + break; + default: + return -1; + } + break; + case DAY_NAME_T: + switch((char) toupper((unsigned char) message[index])) { + case 'U': + return 2; + case 'H': + return 4; + default: + return -1; + } + break; + case DAY_NAME_S: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 6; + case 'U': + return 7; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int guessed_day; + int r; + + cur_token = * index; + + guessed_day = guess_day_name(message, length, cur_token); + if (guessed_day == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + day_names[guessed_day - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + day_of_week = guessed_day; + + * result = day_of_week; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +date = day month year +*/ + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear) +{ + size_t cur_token; + int day; + int month; + int year; + int r; + + cur_token = * index; + + r = mailimf_day_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_month_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_year_parse(message, length, &cur_token, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + * pday = day; + * pmonth = month; + * pyear = year; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +year = 4*DIGIT / obs-year +*/ + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t number; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &number); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = number; + + return MAILIMF_NO_ERROR; +} + +/* +month = (FWS month-name FWS) / obs-month +*/ + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_month_name_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +month-name = "Jan" / "Feb" / "Mar" / "Apr" / + "May" / "Jun" / "Jul" / "Aug" / + "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static struct mailimf_token_value month_names[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"}, +}; + +enum { + MONTH_START, + MONTH_J, + MONTH_JU, + MONTH_M, + MONTH_MA, + MONTH_A +}; + +static int guess_month(const char * message, size_t length, size_t index) +{ + int state; + + state = MONTH_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case MONTH_START: + switch((char) toupper((unsigned char) message[index])) { + case 'J': /* Jan Jun Jul */ + state = MONTH_J; + break; + case 'F': /* Feb */ + return 2; + case 'M': /* Mar May */ + state = MONTH_M; + break; + case 'A': /* Apr Aug */ + state = MONTH_A; + break; + case 'S': /* Sep */ + return 9; + case 'O': /* Oct */ + return 10; + case 'N': /* Nov */ + return 11; + case 'D': /* Dec */ + return 12; + default: + return -1; + } + break; + case MONTH_J: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 1; + case 'U': + state = MONTH_JU; + break; + default: + return -1; + } + break; + case MONTH_JU: + switch((char) toupper((unsigned char) message[index])) { + case 'N': + return 6; + case 'L': + return 7; + default: + return -1; + } + break; + case MONTH_M: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + state = MONTH_MA; + break; + default: + return -1; + } + break; + case MONTH_MA: + switch((char) toupper((unsigned char) message[index])) { + case 'Y': + return 5; + case 'R': + return 3; + default: + return -1; + } + break; + case MONTH_A: + switch((char) toupper((unsigned char) message[index])) { + case 'P': + return 4; + case 'U': + return 8; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int guessed_month; + int r; + + cur_token = * index; + + guessed_month = guess_month(message, length, cur_token); + if (guessed_month == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + month_names[guessed_month - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + month = guessed_month; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +day = ([FWS] 1*2DIGIT) / obs-day +*/ + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + uint32_t day; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = day; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time = time-of-day FWS zone +*/ + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * pzone) +{ + size_t cur_token; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_time_of_day_parse(message, length, &cur_token, + &hour, &min, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_zone_parse(message, length, &cur_token, &zone); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + zone = 0; + } + else { + return r; + } + + * phour = hour; + * pmin = min; + * psec = sec; + * pzone = zone; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time-of-day = hour ":" minute [ ":" second ] +*/ + +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec) +{ + int hour; + int min; + int sec; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_hour_parse(message, length, &cur_token, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_minute_parse(message, length, &cur_token, &min); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_second_parse(message, length, &cur_token, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r == MAILIMF_ERROR_PARSE) + sec = 0; + else + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +hour = 2DIGIT / obs-hour +*/ + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t hour; + int r; + + r = mailimf_number_parse(message, length, index, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = hour; + + return MAILIMF_NO_ERROR; +} + +/* +minute = 2DIGIT / obs-minute +*/ + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t minute; + int r; + + r = mailimf_number_parse(message, length, index, &minute); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = minute; + + return MAILIMF_NO_ERROR; +} + +/* +second = 2DIGIT / obs-second +*/ + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t second; + int r; + + r = mailimf_number_parse(message, length, index, &second); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = second; + + return MAILIMF_NO_ERROR; +} + +/* +zone = (( "+" / "-" ) 4DIGIT) / obs-zone +*/ + +/* +obs-zone = "UT" / "GMT" / ; Universal Time + ; North American UT + ; offsets + "EST" / "EDT" / ; Eastern: - 5/ - 4 + "CST" / "CDT" / ; Central: - 6/ - 5 + "MST" / "MDT" / ; Mountain: - 7/ - 6 + "PST" / "PDT" / ; Pacific: - 8/ - 7 + + %d65-73 / ; Military zones - "A" + %d75-90 / ; through "I" and "K" + %d97-105 / ; through "Z", both + %d107-122 ; upper and lower case +*/ + +enum { + STATE_ZONE_1 = 0, + STATE_ZONE_2 = 1, + STATE_ZONE_3 = 2, + STATE_ZONE_OK = 3, + STATE_ZONE_ERR = 4, + STATE_ZONE_CONT = 5, +}; + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t zone; + int sign; + size_t cur_token; + int r; + + cur_token = * index; + + if (cur_token + 1 < length) { + if ((message[cur_token] == 'U') && (message[cur_token] == 'T')) { + * result = TRUE; + * index = cur_token + 2; + + return MAILIMF_NO_ERROR; + } + } + + if (cur_token + 2 < length) { + int state; + + state = STATE_ZONE_1; + + while (state <= 2) { + switch (state) { + case STATE_ZONE_1: + switch (message[cur_token]) { + case 'G': + if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') { + zone = 0; + state = STATE_ZONE_OK; + } + else { + state = STATE_ZONE_ERR; + } + break; + case 'E': + zone = -5; + state = STATE_ZONE_2; + break; + case 'C': + zone = -6; + state = STATE_ZONE_2; + break; + case 'M': + zone = -7; + state = STATE_ZONE_2; + break; + case 'P': + zone = -8; + state = STATE_ZONE_2; + break; + default: + state = STATE_ZONE_CONT; + break; + } + break; + case STATE_ZONE_2: + switch (message[cur_token + 1]) { + case 'S': + state = STATE_ZONE_3; + break; + case 'D': + zone ++; + state = STATE_ZONE_3; + break; + default: + state = STATE_ZONE_ERR; + break; + } + break; + case STATE_ZONE_3: + if (message[cur_token + 2] == 'T') { + zone *= 100; + state = STATE_ZONE_OK; + } + else + state = STATE_ZONE_ERR; + break; + } + } + + switch (state) { + case STATE_ZONE_OK: + * result = zone; + * index = cur_token + 3; + return MAILIMF_NO_ERROR; + + case STATE_ZONE_ERR: + return MAILIMF_ERROR_PARSE; + } + } + + sign = 1; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = 1; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_minus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = -1; + } + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + sign = 1; + else + return r; + + r = mailimf_number_parse(message, length, &cur_token, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + zone = zone * sign; + + * index = cur_token; + * result = zone; + + return MAILIMF_NO_ERROR; +} + +/* +address = mailbox / group +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result) +{ + int type; + size_t cur_token; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * address; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; + group = NULL; + + type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */ + r = mailimf_group_parse(message, length, &cur_token, &group); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_GROUP; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_MAILBOX; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address = mailimf_address_new(type, mailbox, group); + if (address == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = address; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + err: + return res; +} + + +/* +mailbox = name-addr / addr-spec +*/ + + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox * mailbox; + char * addr_spec; + int r; + int res; + + cur_token = * index; + display_name = NULL; + addr_spec = NULL; + + r = mailimf_name_addr_parse(message, length, &cur_token, + &display_name, &addr_spec); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox = mailimf_mailbox_new(display_name, addr_spec); + if (mailbox == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mailbox; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (display_name != NULL) + mailimf_display_name_free(display_name); + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +name-addr = [display-name] angle-addr +*/ + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr) +{ + char * display_name; + char * angle_addr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + display_name = NULL; + angle_addr = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + * pdisplay_name = display_name; + * pangle_addr = angle_addr; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_display_name: + if (display_name != NULL) + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr +*/ + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * addr_spec; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(addr_spec); + return r; + } + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +group = display-name ":" [mailbox-list / CFWS] ";" + [CFWS] +*/ + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox_list * mailbox_list; + struct mailimf_group * group; + int r; + int res; + + cur_token = * index; + + mailbox_list = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + break; + default: + return r; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mailbox_list; + } + + group = mailimf_group_new(display_name, mailbox_list); + if (group == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mailbox_list; + } + + * index = cur_token; + * result = group; + + return MAILIMF_NO_ERROR; + + free_mailbox_list: + mailimf_mailbox_list_free(mailbox_list); + free_display_name: + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +display-name = phrase +*/ + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_phrase_parse(message, length, index, result); +} + +/* +mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_mailbox_list * mailbox_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_mailbox_parse, + (mailimf_struct_destructor *) + mailimf_mailbox_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox_list = mailimf_mailbox_list_new(list); + if (mailbox_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mailbox_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +/* +address-list = (address *("," address)) / obs-addr-list +*/ + + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_address_list * address_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_address_parse, + (mailimf_struct_destructor *) + mailimf_address_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address_list = mailimf_address_list_new(list); + if (address_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = address_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* +addr-spec = local-part "@" domain +*/ + + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * local_part; + char * domain; +#endif + char * addr_spec; + int r; + int res; + size_t begin; + size_t end; + int final; + size_t count; + const char * src; + char * dest; + size_t i; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + begin = cur_token; + + final = FALSE; + while (1) { + switch (message[end]) { + case '>': + case ',': + case '\r': + case '\n': + case '(': + case ')': + case ':': + case ';': + final = TRUE; + break; + } + + if (final) + break; + + end ++; + if (end >= length) + break; + } + + if (end == begin) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + addr_spec = malloc(end - cur_token + 1); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + count = end - cur_token; + src = message + cur_token; + dest = addr_spec; + for(i = 0 ; i < count ; i ++) { + if ((* src != ' ') && (* src != '\t')) { + * dest = * src; + dest ++; + } + src ++; + } + * dest = '\0'; + +#if 0 + strncpy(addr_spec, message + cur_token, end - cur_token); + addr_spec[end - cur_token] = '\0'; +#endif + + cur_token = end; + +#if 0 + r = mailimf_local_part_parse(message, length, &cur_token, &local_part); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_domain_parse(message, length, &cur_token, &domain); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_local_part; + } + break; + + case MAILIMF_ERROR_PARSE: + domain = NULL; + break; + + default: + res = r; + goto free_local_part; + } + + if (domain) { + addr_spec = malloc(strlen(local_part) + strlen(domain) + 2); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_domain; + } + + strcpy(addr_spec, local_part); + strcat(addr_spec, "@"); + strcat(addr_spec, domain); + + mailimf_domain_free(domain); + mailimf_local_part_free(local_part); + } + else { + addr_spec = local_part; + } +#endif + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_domain: + mailimf_domain_free(domain); + free_local_part: + mailimf_local_part_free(local_part); +#endif + err: + return res; +} + +/* +local-part = dot-atom / quoted-string / obs-local-part +*/ + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_quoted_string_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain = dot-atom / domain-literal / obs-domain +*/ + +#if 0 +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_domain_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +[FWS] dcontent +*/ + +#if 0 +static int +mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_dcontent_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] +*/ + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int len; + int begin; + char * domain_literal; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_domain_literal_fws_dcontent_parse(message, length, + &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + len = cur_token - begin; + + domain_literal = malloc(len + 1); + if (domain_literal == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(domain_literal, message + begin, len); + domain_literal[len] = '\0'; + + * result = domain_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +dcontent = dtext / quoted-pair +*/ + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + + +/* +dtext = NO-WS-CTL / ; Non white space controls + + %d33-90 / ; The rest of the US-ASCII + %d94-126 ; characters not including "[", + ; "]", or "\" +*/ + +static inline int is_dtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch >= 91) && (uch <= 93)) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +message = (fields / obs-fields) + [CRLF body] +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result) +{ + struct mailimf_fields * fields; + struct mailimf_body * body; + struct mailimf_message * msg; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_fields_parse(message, length, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_body_parse(message, length, &cur_token, &body); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_fields; + } + + msg = mailimf_message_new(fields, body); + if (msg == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + + * index = cur_token; + * result = msg; + + return MAILIMF_NO_ERROR; + + free_body: + mailimf_body_free(body); + free_fields: + mailimf_fields_free(fields); + err: + return res; +} + +/* +body = *(*998text CRLF) *998text +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result) +{ + size_t cur_token; + struct mailimf_body * body; + + cur_token = * index; + + body = mailimf_body_new(message + cur_token, length - cur_token); + if (body == NULL) + return MAILIMF_ERROR_MEMORY; + + cur_token = length; + + * result = body; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CHANGE TO THE RFC 2822 + +original : + +fields = *(trace + *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) + *(orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) + +INTO THE FOLLOWING : +*/ + +/* +resent-fields-list = *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) +*/ + +#if 0 +enum { + RESENT_HEADER_START, +}; + +static int guess_resent_header_type(char * message, + size_t length, size_t index) +{ + int r; + + r = mailimf_token_case_insensitive_parse(message, + length, &index, "Resent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_RESENT_FIELD_NONE; + + if (index >= length) + return MAILIMF_RESENT_FIELD_NONE; + + switch(toupper(message[index])) { + case 'D': + return MAILIMF_RESENT_FIELD_DATE; + case 'F': + return MAILIMF_RESENT_FIELD_FROM; + case 'S': + return MAILIMF_RESENT_FIELD_SENDER; + case 'T': + return MAILIMF_RESENT_FIELD_TO; + case 'C': + return MAILIMF_RESENT_FIELD_CC; + case 'B': + return MAILIMF_RESENT_FIELD_BCC; + case 'M': + return MAILIMF_RESENT_FIELD_MSG_ID; + default: + return MAILIMF_RESENT_FIELD_NONE; + } +} +#endif + +#if 0 +static int +mailimf_resent_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_field ** result) +{ + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + size_t cur_token; + int type; + struct mailimf_resent_field * resent_field; + int r; + int res; + + cur_token = * index; + + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + + type = guess_resent_header_type(message, length, cur_token); + + switch(type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + default: + res = MAILIMF_ERROR_PARSE; + goto err; + } + + resent_field = mailimf_resent_field_new(type, resent_date, + resent_from, resent_sender, + resent_to, resent_cc, + resent_bcc, resent_msg_id); + if (resent_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent; + } + + * result = resent_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent: + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + err: + return res; +} +#endif + +#if 0 +static int +mailimf_resent_fields_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_fields_list ** result) +{ + clist * list; + size_t cur_token; + struct mailimf_resent_fields_list * resent_fields_list; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, &list, + (mailimf_struct_parser *) + mailimf_resent_field_parse, + (mailimf_struct_destructor *) + mailimf_resent_field_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + resent_fields_list = mailimf_resent_fields_list_new(list); + if (resent_fields_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = resent_fields_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* + ([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_trace_resent_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace_resent_fields ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + struct mailimf_resent_fields_list * resent_fields; + struct mailimf_trace_resent_fields * trace_resent_fields; + int res; + int r; + + cur_token = * index; + + return_path = NULL; + resent_fields = NULL; + + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_resent_fields_list_parse(message, length, &cur_token, + &resent_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((return_path == NULL) && (resent_fields == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + trace_resent_fields = mailimf_trace_resent_fields_new(return_path, + resent_fields); + if (trace_resent_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent_fields; + } + + * result = trace_resent_fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent_fields: + if (resent_fields != NULL) + mailimf_resent_fields_list_free(resent_fields); + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +delivering-info = *([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_delivering_info_parse(const char * message, size_t length, + size_t * index, + struct mailimf_delivering_info ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_delivering_info * delivering_info; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_trace_resent_fields_parse, + (mailimf_struct_destructor *) + mailimf_trace_resent_fields_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + delivering_info = mailimf_delivering_info_new(list); + if (delivering_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = delivering_info; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* +field = delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field +*/ + +enum { + HEADER_START, + HEADER_C, + HEADER_R, + HEADER_RE, + HEADER_S, + HEADER_RES, +}; + +static int guess_header_type(const char * message, size_t length, size_t index) +{ + int state; + int r; + + state = HEADER_START; + + while (1) { + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch(state) { + case HEADER_START: + switch((char) toupper((unsigned char) message[index])) { + case 'B': + return MAILIMF_FIELD_BCC; + case 'C': + state = HEADER_C; + break; + case 'D': + return MAILIMF_FIELD_ORIG_DATE; + case 'F': + return MAILIMF_FIELD_FROM; + case 'I': + return MAILIMF_FIELD_IN_REPLY_TO; + case 'K': + return MAILIMF_FIELD_KEYWORDS; + case 'M': + return MAILIMF_FIELD_MESSAGE_ID; + case 'R': + state = HEADER_R; + break; + case 'T': + return MAILIMF_FIELD_TO; + break; + case 'S': + state = HEADER_S; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_C: + switch((char) toupper((unsigned char) message[index])) { + case 'O': + return MAILIMF_FIELD_COMMENTS; + case 'C': + return MAILIMF_FIELD_CC; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_R: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + state = HEADER_RE; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_RE: + switch((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILIMF_FIELD_REFERENCES; + case 'P': + return MAILIMF_FIELD_REPLY_TO; + case 'S': + state = HEADER_RES; + break; + case 'T': + return MAILIMF_FIELD_RETURN_PATH; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_S: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + return MAILIMF_FIELD_SENDER; + case 'U': + return MAILIMF_FIELD_SUBJECT; + default: + return MAILIMF_FIELD_NONE; + } + break; + + case HEADER_RES: + r = mailimf_token_case_insensitive_parse(message, + length, &index, "ent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_FIELD_NONE; + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch((char) toupper((unsigned char) message[index])) { + case 'D': + return MAILIMF_FIELD_RESENT_DATE; + case 'F': + return MAILIMF_FIELD_RESENT_FROM; + case 'S': + return MAILIMF_FIELD_RESENT_SENDER; + case 'T': + return MAILIMF_FIELD_RESENT_TO; + case 'C': + return MAILIMF_FIELD_RESENT_CC; + case 'B': + return MAILIMF_FIELD_RESENT_BCC; + case 'M': + return MAILIMF_FIELD_RESENT_MSG_ID; + default: + return MAILIMF_FIELD_NONE; + } + break; + } + index ++; + } +} + +static int mailimf_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_return * return_path; + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_comments * comments; + struct mailimf_keywords * keywords; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + return_path = NULL; + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + comments = NULL; + keywords = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_FIELD_ORIG_DATE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_parse(message, length, &cur_token, + &comments); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_parse(message, length, &cur_token, + &keywords); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMF_FIELD_OPTIONAL_FIELD; + } + + field = mailimf_field_new(type, return_path, resent_date, + resent_from, resent_sender, resent_to, resent_cc, resent_bcc, + resent_msg_id, orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, comments, keywords, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (return_path != NULL) + mailimf_return_free(return_path); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (comments != NULL) + mailimf_comments_free(comments); + if (keywords != NULL) + mailimf_keywords_free(keywords); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + + +/* +fields = *(delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) +*/ + +#if 0 +int +mailimf_unparsed_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_unparsed_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_unparsed_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_optional_field_free); + /* + if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_unparsed_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + /* + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* +orig-date = "Date:" date-time CRLF +*/ + + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Date:"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_ignore_unstructured_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +from = "From:" mailbox-list CRLF +*/ + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +sender = "Sender:" mailbox CRLF +*/ + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +reply-to = "Reply-To:" address-list CRLF +*/ + + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +to = "To:" address-list CRLF +*/ + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +cc = "Cc:" address-list CRLF +*/ + + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +bcc = "Bcc:" (address-list / [CFWS]) CRLF +*/ + + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + addr_list = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +message-id = "Message-ID:" msg-id CRLF +*/ + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +in-reply-to = "In-Reply-To:" 1*msg-id CRLF +*/ + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result) +{ + return mailimf_struct_multiple_parse(message, length, index, + result, + (mailimf_struct_parser *) + mailimf_unstrict_msg_id_parse, + (mailimf_struct_destructor *) + mailimf_msg_id_free); +} + +static int mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result) +{ + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + int res; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "In-Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = in_reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +references = "References:" 1*msg-id CRLF +*/ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result) +{ + struct mailimf_references * references; + size_t cur_token; + clist * msg_id_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "References"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = references; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] +*/ + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * id_left; + char * id_right; +#endif + char * msg_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msg_id); + res = r; + goto err; + } + +#if 0 + r = mailimf_id_left_parse(message, length, &cur_token, &id_left); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_id_right_parse(message, length, &cur_token, &id_right); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_right; + } + + msg_id = malloc(strlen(id_left) + strlen(id_right) + 2); + if (msg_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_id_right; + } + strcpy(msg_id, id_left); + strcat(msg_id, "@"); + strcat(msg_id, id_right); + + mailimf_id_left_free(id_left); + mailimf_id_right_free(id_right); +#endif + + * result = msg_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_id_right: + mailimf_id_right_free(id_right); + free_id_left: + mailimf_id_left_free(id_left); +#endif + /* + free: + mailimf_atom_free(msg_id); + */ + err: + return res; +} + +static int mailimf_parse_unwanted_msg_id(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + char * word; + int token_parsed; + + cur_token = * index; + + token_parsed = TRUE; + while (token_parsed) { + token_parsed = FALSE; + r = mailimf_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + mailimf_word_free(word); + token_parsed = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_comma_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_point_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + char * msgid; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_parse(message, length, &cur_token, &msgid); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = msgid; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +id-left = dot-atom-text / no-fold-quote / obs-id-left +*/ + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_quote_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +id-right = dot-atom-text / no-fold-literal / obs-id-right +*/ + +#if 0 +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE +*/ + +#if 0 +static int mailimf_no_fold_quote_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_qtext_parse(message, length, &cur_token, &ch); +#endif + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_quote; + int r; + int res; + + begin = cur_token; + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* no_fold_quote = strndup(message + begin, cur_token - begin); */ + no_fold_quote = malloc(cur_token - begin + 1); + if (no_fold_quote == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(no_fold_quote, message + begin, cur_token - begin); + no_fold_quote[cur_token - begin] = '\0'; + + * result = no_fold_quote; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +no-fold-literal = "[" *(dtext / quoted-pair) "]" +*/ + +#if 0 +static inline int +mailimf_no_fold_literal_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_dtext_parse(message, length, &cur_token, &ch); +#endif + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_literal; + int r; + int res; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_literal_char_parse(message, length, + &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* + no_fold_literal = strndup(message + begin, cur_token - begin); + */ + no_fold_literal = malloc(cur_token - begin + 1); + if (no_fold_literal == NULL) { + res = MAILIMF_NO_ERROR; + goto err; + } + strncpy(no_fold_literal, message + begin, cur_token - begin); + no_fold_literal[cur_token - begin] = '\0'; + + * result = no_fold_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +subject = "Subject:" unstructured CRLF +*/ + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result) +{ + struct mailimf_subject * subject; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Subject"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + subject = mailimf_subject_new(value); + if (subject == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = subject; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +comments = "Comments:" unstructured CRLF +*/ + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result) +{ + struct mailimf_comments * comments; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Comments"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + comments = mailimf_comments_new(value); + if (comments == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = comments; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +keywords = "Keywords:" phrase *("," phrase) CRLF +*/ + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result) +{ + struct mailimf_keywords * keywords; + clist * list; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Keywords"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_struct_list_parse(message, length, &cur_token, + &list, ',', + (mailimf_struct_parser *) + mailimf_phrase_parse, + (mailimf_struct_destructor *) + mailimf_phrase_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + keywords = mailimf_keywords_new(list); + if (keywords == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = keywords; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_phrase_free, NULL); + clist_free(list); + err: + return res; +} + +/* +resent-date = "Resent-Date:" date-time CRLF +*/ + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_orig_date * orig_date; + struct mailimf_date_time * date_time; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Date"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +resent-from = "Resent-From:" mailbox-list CRLF +*/ + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +resent-sender = "Resent-Sender:" mailbox CRLF +*/ + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = length; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +resent-to = "Resent-To:" address-list CRLF +*/ + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-cc = "Resent-Cc:" address-list CRLF +*/ + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF +*/ + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + bcc = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * index = cur_token; + + return TRUE; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-msg-id = "Resent-Message-ID:" msg-id CRLF +*/ + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +trace = [return] + 1*received +*/ + +#if 0 +static int mailimf_trace_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + clist * received_list; + struct mailimf_trace * trace; + int r; + int res; + + cur_token = * index; + return_path = NULL; + received_list = NULL; + + r = mailimf_return_parse(message, length, &cur_token, &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &received_list, + (mailimf_struct_parser *) + mailimf_received_parse, + (mailimf_struct_destructor *) + mailimf_received_free); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((received_list == NULL) && (return_path == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto free_return; + } + + trace = mailimf_trace_new(return_path, received_list); + if (trace == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = trace; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(received_list, (clist_func) mailimf_received_free, NULL); + clist_free(received_list); + free_return: + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +return = "Return-Path:" path CRLF +*/ + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result) +{ + struct mailimf_path * path; + struct mailimf_return * return_path; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Return-Path"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_path_parse(message, length, &cur_token, &path); + if ( r!= MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_path; + } + + return_path = mailimf_return_new(path); + if (return_path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_path; + } + + * result = return_path; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_path: + mailimf_path_free(path); + err: + return res; +} + +/* +path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / + obs-path +*/ + +static int mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result) +{ + size_t cur_token; + char * addr_spec; + struct mailimf_path * path; + int res; + int r; + + cur_token = * index; + addr_spec = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + return r; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = mailimf_path_new(addr_spec); + if (path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_spec; + } + + * index = cur_token; + * result = path; + + return MAILIMF_NO_ERROR; + + free_addr_spec: + if (addr_spec == NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +received = "Received:" name-val-list ";" date-time CRLF +*/ + +#if 0 +static int mailimf_received_parse(const char * message, size_t length, + size_t * index, + struct mailimf_received ** result) +{ + size_t cur_token; + struct mailimf_received * received; + struct mailimf_name_val_list * name_val_list; + struct mailimf_date_time * date_time; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Received"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_name_val_list_parse(message, length, + &cur_token, &name_val_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + received = mailimf_received_new(name_val_list, date_time); + if (received == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * index = cur_token; + * result = received; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + free_name_val_list: + mailimf_name_val_list_free(name_val_list); + err: + return res; +} +#endif + +/* +name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)] +*/ + +#if 0 +static int +mailimf_name_val_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_list ** result) +{ + size_t cur_token; + struct mailimf_name_val_pair * pair; + struct mailimf_name_val_list * name_val_list; + clist* list; + int res; + int r; + + cur_token = * index; + list = NULL; + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + + if (r == MAILIMF_NO_ERROR){ + size_t final_token; + + list = clist_new(); + if (list == NULL) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_list; + } + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_list; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + cur_token = final_token; + } + + name_val_list = mailimf_name_val_list_new(list); + if (name_val_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * index = cur_token; + * result = name_val_list; + + return MAILIMF_NO_ERROR; + + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +/* +name-val-pair = item-name CFWS item-value +*/ + +#if 0 +static int +mailimf_name_val_pair_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_pair ** result) +{ + size_t cur_token; + char * item_name; + struct mailimf_item_value * item_value; + struct mailimf_name_val_pair * name_val_pair; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_item_name_parse(message, length, &cur_token, &item_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + r = mailimf_item_value_parse(message, length, &cur_token, &item_value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + name_val_pair = mailimf_name_val_pair_new(item_name, item_value); + if (name_val_pair == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_item_value; + } + + * result = name_val_pair; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_item_value: + mailimf_item_value_free(item_value); + free_item_name: + mailimf_item_name_free(item_name); + err: + return res; +} +#endif + +/* +item-name = ALPHA *(["-"] (ALPHA / DIGIT)) +*/ + +#if 0 +static int mailimf_item_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char * item_name; + char ch; + int digit; + int r; + int res; + + cur_token = * index; + + begin = cur_token; + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + int minus_sign; + + minus_sign = mailimf_minus_parse(message, length, &cur_token); + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_digit_parse(message, length, &cur_token, &digit); + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + if (r == MAILIMF_ERROR_PARSE) + break; + else if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + } + + item_name = strndup(message + begin, cur_token - begin); + if (item_name == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * index = cur_token; + * result = item_name; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +item-value = 1*angle-addr / addr-spec / + atom / domain / msg-id +*/ + +#if 0 +static int is_item_value_atext(char ch) +{ + switch (ch) { + case '\t': + case ' ': + case '\r': + case '\n': + case ';': + return FALSE; + default: + return TRUE; + } +} + +static int mailimf_item_value_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * atom; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_custom_string_parse(message, length, &cur_token, + &atom, is_item_value_atext); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_item_value_parse(const char * message, size_t length, + size_t * index, + struct mailimf_item_value ** result) +{ + size_t cur_token; + clist * angle_addr_list; + char * addr_spec; + char * atom; + char * domain; + char * msg_id; + int type; + struct mailimf_item_value * item_value; + int r; + int res; + + cur_token = * index; + + angle_addr_list = NULL; + addr_spec = NULL; + atom = NULL; + domain = NULL; + msg_id = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &angle_addr_list, + (mailimf_struct_parser *) + mailimf_angle_addr_parse, + (mailimf_struct_destructor *) + mailimf_angle_addr_free); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_addr_spec_parse(message, length, &cur_token, + &addr_spec); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ADDR_SPEC; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_msg_id_parse(message, length, &cur_token, + &msg_id); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_MSG_ID; + } + + /* + else if (mailimf_domain_parse(message, length, &cur_token, + &domain)) + type = MAILIMF_ITEM_VALUE_DOMAIN; + */ + /* + else if (mailimf_atom_parse(message, length, &cur_token, + &atom)) + type = MAILIMF_ITEM_VALUE_ATOM; + */ + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_item_value_atom_parse(message, length, &cur_token, + &atom); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ATOM; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec, + atom, domain, msg_id); + if (item_value == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = item_value; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (angle_addr_list != NULL) { + clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL); + clist_free(angle_addr_list); + } + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + if (atom != NULL) + mailimf_atom_free(atom); + if (domain != NULL) + mailimf_domain_free(domain); + if (msg_id != NULL) + mailimf_msg_id_free(msg_id); + err: + return res; +} +#endif + +/* +optional-field = field-name ":" unstructured CRLF +*/ + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result) +{ + char * name; + char * value; + struct mailimf_optional_field * optional_field; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_field_name_parse(message, length, &cur_token, &name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + optional_field = mailimf_optional_field_new(name, value); + if (optional_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = optional_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + free_name: + mailimf_field_name_free(name); + err: + return res; +} + +/* +field-name = 1*ftext +*/ + +static inline int is_ftext(char ch); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * field_name; + size_t cur_token; + size_t end; + + cur_token = * index; + + end = cur_token; + if (end >= length) { + return MAILIMF_ERROR_PARSE; + } + + while (is_ftext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + return MAILIMF_ERROR_PARSE; + } + + /* field_name = strndup(message + cur_token, end - cur_token); */ + field_name = malloc(end - cur_token + 1); + if (field_name == NULL) { + return MAILIMF_ERROR_MEMORY; + } + strncpy(field_name, message + cur_token, end - cur_token); + field_name[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = field_name; + + return MAILIMF_NO_ERROR; +} + +/* +ftext = %d33-57 / ; Any character except + %d59-126 ; controls, SP, and + ; ":". +*/ + +static inline int is_ftext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 33) + return FALSE; + + if (uch == 58) + return FALSE; + + return TRUE; +} + +/* +static int mailimf_ftext_parse(const char * message, size_t length, + size_t * index, gchar * result) +{ + return mailimf_typed_text_parse(message, length, index, result, is_ftext); +} +*/ + + + + +static int mailimf_envelope_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, NULL, NULL, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + struct mailimf_field * elt; + + r = mailimf_envelope_field_parse(message, length, &cur_token, &elt); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + else { + res = r; + goto free; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + +static int +mailimf_envelope_or_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + r = mailimf_envelope_field_parse(message, length, index, result); + if (r == MAILIMF_NO_ERROR) + return MAILIMF_NO_ERROR; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_envelope_or_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +mailimf_only_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_only_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} diff --git a/kmicromail/libetpan/imf/mailimf.h b/kmicromail/libetpan/imf/mailimf.h new file mode 100644 index 0000000..3248e73 --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf.h @@ -0,0 +1,345 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param index this is a pointer to the start of the message in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param index this is a pointer to the start of the message text part in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param index this is a pointer to the start of the address list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param index this is a pointer to the start of the address in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param index this is a pointer to the start of the date in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param index this is a pointer to the start of the header field in + the given string, (* index) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index); + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index); + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index); + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)); + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, index, token) \ + mailimf_token_case_insensitive_len_parse(message, length, index, token, \ + sizeof(token) - 1) + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result); + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result); + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* exported for IMAP */ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imf/mailimf_types.c b/kmicromail/libetpan/imf/mailimf_types.c new file mode 100644 index 0000000..fbef8f0 --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_types.c @@ -0,0 +1,868 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimf_types.h" +#include "mmapstring.h" +#include + +void mailimf_atom_free(char * atom) +{ + free(atom); +} + +void mailimf_dot_atom_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_dot_atom_text_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_quoted_string_free(char * quoted_string) +{ + free(quoted_string); +} + +void mailimf_word_free(char * word) +{ + free(word); +} + +void mailimf_phrase_free(char * phrase) +{ + free(phrase); +} + +void mailimf_unstructured_free(char * unstructured) +{ + free(unstructured); +} + + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone) +{ + struct mailimf_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_sec = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + + +void mailimf_date_time_free(struct mailimf_date_time * date_time) +{ + free(date_time); +} + + + + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group) +{ + struct mailimf_address * address; + + address = malloc(sizeof(* address)); + if (address == NULL) + return NULL; + + address->ad_type = ad_type; + switch (ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + address->ad_data.ad_mailbox = ad_mailbox; + break; + case MAILIMF_ADDRESS_GROUP: + address->ad_data.ad_group = ad_group; + break; + } + + return address; +} + +void mailimf_address_free(struct mailimf_address * address) +{ + switch (address->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + mailimf_mailbox_free(address->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + mailimf_group_free(address->ad_data.ad_group); + } + free(address); +} + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec) +{ + struct mailimf_mailbox * mb; + + mb = malloc(sizeof(* mb)); + if (mb == NULL) + return NULL; + + mb->mb_display_name = mb_display_name; + mb->mb_addr_spec = mb_addr_spec; + + return mb; +} + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox) +{ + if (mailbox->mb_display_name != NULL) + mailimf_display_name_free(mailbox->mb_display_name); + mailimf_addr_spec_free(mailbox->mb_addr_spec); + free(mailbox); +} + + +void mailimf_angle_addr_free(char * angle_addr) +{ + free(angle_addr); +} + + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list) +{ + struct mailimf_group * group; + + group = malloc(sizeof(* group)); + if (group == NULL) + return NULL; + + group->grp_display_name = grp_display_name; + group->grp_mb_list = grp_mb_list; + + return group; +} + +void mailimf_group_free(struct mailimf_group * group) +{ + if (group->grp_mb_list) + mailimf_mailbox_list_free(group->grp_mb_list); + mailimf_display_name_free(group->grp_display_name); + free(group); +} + +void mailimf_display_name_free(char * display_name) +{ + mailimf_phrase_free(display_name); +} + + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list) +{ + struct mailimf_mailbox_list * mbl; + + mbl = malloc(sizeof(* mbl)); + if (mbl == NULL) + return NULL; + + mbl->mb_list = mb_list; + + return mbl; +} + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list) +{ + clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(mb_list->mb_list); + free(mb_list); +} + + + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list) +{ + struct mailimf_address_list * addr_list; + + addr_list = malloc(sizeof(* addr_list)); + if (addr_list == NULL) + return NULL; + + addr_list->ad_list = ad_list; + + return addr_list; +} + +void mailimf_address_list_free(struct mailimf_address_list * addr_list) +{ + clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL); + clist_free(addr_list->ad_list); + free(addr_list); +} + + +void mailimf_addr_spec_free(char * addr_spec) +{ + free(addr_spec); +} + +void mailimf_local_part_free(char * local_part) +{ + free(local_part); +} + +void mailimf_domain_free(char * domain) +{ + free(domain); +} + +void mailimf_domain_literal_free(char * domain_literal) +{ + free(domain_literal); +} + + + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body) +{ + struct mailimf_message * message; + + message = malloc(sizeof(* message)); + if (message == NULL) + return NULL; + + message->msg_fields = msg_fields; + message->msg_body = msg_body; + + return message; +} + +void mailimf_message_free(struct mailimf_message * message) +{ + mailimf_body_free(message->msg_body); + mailimf_fields_free(message->msg_fields); + free(message); +} + + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size) +{ + struct mailimf_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + body->bd_text = bd_text; + body->bd_size = bd_size; + + return body; +} + +void mailimf_body_free(struct mailimf_body * body) +{ + free(body); +} + + + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field) +{ + struct mailimf_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + + field->fld_type = fld_type; + switch (fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + field->fld_data.fld_return_path = fld_return_path; + break; + case MAILIMF_FIELD_RESENT_DATE: + field->fld_data.fld_resent_date = fld_resent_date; + break; + case MAILIMF_FIELD_RESENT_FROM: + field->fld_data.fld_resent_from = fld_resent_from; + break; + case MAILIMF_FIELD_RESENT_SENDER: + field->fld_data.fld_resent_sender = fld_resent_sender; + break; + case MAILIMF_FIELD_RESENT_TO: + field->fld_data.fld_resent_to = fld_resent_to; + break; + case MAILIMF_FIELD_RESENT_CC: + field->fld_data.fld_resent_cc = fld_resent_cc; + break; + case MAILIMF_FIELD_RESENT_BCC: + field->fld_data.fld_resent_bcc = fld_resent_bcc; + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + field->fld_data.fld_resent_msg_id = fld_resent_msg_id; + break; + case MAILIMF_FIELD_ORIG_DATE: + field->fld_data.fld_orig_date = fld_orig_date; + break; + case MAILIMF_FIELD_FROM: + field->fld_data.fld_from = fld_from; + break; + case MAILIMF_FIELD_SENDER: + field->fld_data.fld_sender = fld_sender; + break; + case MAILIMF_FIELD_REPLY_TO: + field->fld_data.fld_reply_to = fld_reply_to; + break; + case MAILIMF_FIELD_TO: + field->fld_data.fld_to = fld_to; + break; + case MAILIMF_FIELD_CC: + field->fld_data.fld_cc = fld_cc; + break; + case MAILIMF_FIELD_BCC: + field->fld_data.fld_bcc = fld_bcc; + break; + case MAILIMF_FIELD_MESSAGE_ID: + field->fld_data.fld_message_id = fld_message_id; + break; + case MAILIMF_FIELD_IN_REPLY_TO: + field->fld_data.fld_in_reply_to = fld_in_reply_to; + break; + case MAILIMF_FIELD_REFERENCES: + field->fld_data.fld_references = fld_references; + break; + case MAILIMF_FIELD_SUBJECT: + field->fld_data.fld_subject = fld_subject; + break; + case MAILIMF_FIELD_COMMENTS: + field->fld_data.fld_comments = fld_comments; + break; + case MAILIMF_FIELD_KEYWORDS: + field->fld_data.fld_keywords = fld_keywords; + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + field->fld_data.fld_optional_field = fld_optional_field; + break; + } + + return field; +} + +void mailimf_field_free(struct mailimf_field * field) +{ + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + mailimf_return_free(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + mailimf_orig_date_free(field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + mailimf_from_free(field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + mailimf_sender_free(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + mailimf_to_free(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + mailimf_cc_free(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + mailimf_bcc_free(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + mailimf_message_id_free(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + mailimf_orig_date_free(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + mailimf_from_free(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + mailimf_sender_free(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + mailimf_reply_to_free(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + mailimf_to_free(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + mailimf_cc_free(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + mailimf_bcc_free(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + mailimf_message_id_free(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + mailimf_references_free(field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + mailimf_subject_free(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + mailimf_comments_free(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + mailimf_keywords_free(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + mailimf_optional_field_free(field->fld_data.fld_optional_field); + break; + } + + free(field); +} + +struct mailimf_fields * mailimf_fields_new(clist * fld_list) +{ + struct mailimf_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailimf_fields_free(struct mailimf_fields * fields) +{ + if (fields->fld_list != NULL) { + clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL); + clist_free(fields->fld_list); + } + free(fields); +} + + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time) +{ + struct mailimf_orig_date * orig_date; + + orig_date = malloc(sizeof(* orig_date)); + if (orig_date == NULL) + return NULL; + + orig_date->dt_date_time = dt_date_time; + + return orig_date; +} + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date) +{ + if (orig_date->dt_date_time != NULL) + mailimf_date_time_free(orig_date->dt_date_time); + free(orig_date); +} + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list) +{ + struct mailimf_from * from; + + from = malloc(sizeof(* from)); + if (from == NULL) + return NULL; + + from->frm_mb_list = frm_mb_list; + + return from; +} + +void mailimf_from_free(struct mailimf_from * from) +{ + if (from->frm_mb_list != NULL) + mailimf_mailbox_list_free(from->frm_mb_list); + free(from); +} + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb) +{ + struct mailimf_sender * sender; + + sender = malloc(sizeof(* sender)); + if (sender == NULL) + return NULL; + + sender->snd_mb = snd_mb; + + return sender; +} + +void mailimf_sender_free(struct mailimf_sender * sender) +{ + if (sender->snd_mb != NULL) + mailimf_mailbox_free(sender->snd_mb); + free(sender); +} + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list) +{ + struct mailimf_reply_to * reply_to; + + reply_to = malloc(sizeof(* reply_to)); + if (reply_to == NULL) + return NULL; + + reply_to->rt_addr_list = rt_addr_list; + + return reply_to; +} + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to) +{ + if (reply_to->rt_addr_list != NULL) + mailimf_address_list_free(reply_to->rt_addr_list); + free(reply_to); +} + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list) +{ + struct mailimf_to * to; + + to = malloc(sizeof(* to)); + if (to == NULL) + return NULL; + + to->to_addr_list = to_addr_list; + + return to; +} + +void mailimf_to_free(struct mailimf_to * to) +{ + if (to->to_addr_list != NULL) + mailimf_address_list_free(to->to_addr_list); + free(to); +} + +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list) +{ + struct mailimf_cc * cc; + + cc = malloc(sizeof(* cc)); + if (cc == NULL) + return NULL; + + cc->cc_addr_list = cc_addr_list; + + return cc; +} + +void mailimf_cc_free(struct mailimf_cc * cc) +{ + if (cc->cc_addr_list != NULL) + mailimf_address_list_free(cc->cc_addr_list); + free(cc); +} + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list) +{ + struct mailimf_bcc * bcc; + + bcc = malloc(sizeof(* bcc)); + if (bcc == NULL) + return NULL; + + bcc->bcc_addr_list = bcc_addr_list; + + return bcc; +} + +void mailimf_bcc_free(struct mailimf_bcc * bcc) +{ + if (bcc->bcc_addr_list != NULL) + mailimf_address_list_free(bcc->bcc_addr_list); + free(bcc); +} + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value) +{ + struct mailimf_message_id * message_id; + + message_id = malloc(sizeof(* message_id)); + if (message_id == NULL) + return NULL; + + message_id->mid_value = mid_value; + + return message_id; +} + +void mailimf_message_id_free(struct mailimf_message_id * message_id) +{ + if (message_id->mid_value != NULL) + mailimf_msg_id_free(message_id->mid_value); + free(message_id); +} + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list) +{ + struct mailimf_in_reply_to * in_reply_to; + + in_reply_to = malloc(sizeof(* in_reply_to)); + if (in_reply_to == NULL) + return NULL; + + in_reply_to->mid_list = mid_list; + + return in_reply_to; +} + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to) +{ + clist_foreach(in_reply_to->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(in_reply_to->mid_list); + free(in_reply_to); +} + +struct mailimf_references * mailimf_references_new(clist * mid_list) +{ + struct mailimf_references * ref; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + return NULL; + + ref->mid_list = mid_list; + + return ref; +} + +void mailimf_references_free(struct mailimf_references * references) +{ + clist_foreach(references->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(references->mid_list); + free(references); +} + +void mailimf_msg_id_free(char * msg_id) +{ + free(msg_id); +} + +void mailimf_id_left_free(char * id_left) +{ + free(id_left); +} + +void mailimf_id_right_free(char * id_right) +{ + free(id_right); +} + +void mailimf_no_fold_quote_free(char * nfq) +{ + free(nfq); +} + +void mailimf_no_fold_literal_free(char * nfl) +{ + free(nfl); +} + +struct mailimf_subject * mailimf_subject_new(char * sbj_value) +{ + struct mailimf_subject * subject; + + subject = malloc(sizeof(* subject)); + if (subject == NULL) + return NULL; + + subject->sbj_value = sbj_value; + + return subject; +} + +void mailimf_subject_free(struct mailimf_subject * subject) +{ + mailimf_unstructured_free(subject->sbj_value); + free(subject); +} + +struct mailimf_comments * mailimf_comments_new(char * cm_value) +{ + struct mailimf_comments * comments; + + comments = malloc(sizeof(* comments)); + if (comments == NULL) + return NULL; + + comments->cm_value = cm_value; + + return comments; +} + +void mailimf_comments_free(struct mailimf_comments * comments) +{ + mailimf_unstructured_free(comments->cm_value); + free(comments); +} + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list) +{ + struct mailimf_keywords * keywords; + + keywords = malloc(sizeof(* keywords)); + if (keywords == NULL) + return NULL; + + keywords->kw_list = kw_list; + + return keywords; +} + +void mailimf_keywords_free(struct mailimf_keywords * keywords) +{ + clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL); + clist_free(keywords->kw_list); + free(keywords); +} + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path) +{ + struct mailimf_return * return_path; + + return_path = malloc(sizeof(* return_path)); + if (return_path == NULL) + return NULL; + + return_path->ret_path = ret_path; + + return return_path; +} + +void mailimf_return_free(struct mailimf_return * return_path) +{ + mailimf_path_free(return_path->ret_path); + free(return_path); +} + + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec) +{ + struct mailimf_path * path; + + path = malloc(sizeof(* path)); + if (path == NULL) + return NULL; + + path->pt_addr_spec = pt_addr_spec; + + return path; +} + +void mailimf_path_free(struct mailimf_path * path) +{ + if (path->pt_addr_spec != NULL) + mailimf_addr_spec_free(path->pt_addr_spec); + free(path); +} + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value) +{ + struct mailimf_optional_field * opt_field; + + opt_field = malloc(sizeof(* opt_field)); + if (opt_field == NULL) + return NULL; + + opt_field->fld_name = fld_name; + opt_field->fld_value = fld_value; + + return opt_field; +} + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field) +{ + mailimf_field_name_free(opt_field->fld_name); + mailimf_unstructured_free(opt_field->fld_value); + free(opt_field); +} + +void mailimf_field_name_free(char * field_name) +{ + free(field_name); +} diff --git a/kmicromail/libetpan/imf/mailimf_types.h b/kmicromail/libetpan/imf/mailimf_types.h new file mode 100644 index 0000000..288feb6 --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_types.h @@ -0,0 +1,793 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP, /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +void mailimf_atom_free(char * atom); + +void mailimf_dot_atom_free(char * dot_atom); + +void mailimf_dot_atom_text_free(char * dot_atom); + +void mailimf_quoted_string_free(char * quoted_string); + +void mailimf_word_free(char * word); + +void mailimf_phrase_free(char * phrase); + +void mailimf_unstructured_free(char * unstructured); + +void mailimf_angle_addr_free(char * angle_addr); + +void mailimf_display_name_free(char * display_name); + +void mailimf_addr_spec_free(char * addr_spec); + +void mailimf_local_part_free(char * local_part); + +void mailimf_domain_free(char * domain); + +void mailimf_domain_literal_free(char * domain); + +void mailimf_msg_id_free(char * msg_id); + +void mailimf_id_left_free(char * id_left); + +void mailimf_id_right_free(char * id_right); + +void mailimf_no_fold_quote_free(char * nfq); + +void mailimf_no_fold_literal_free(char * nfl); + +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE, +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imf/mailimf_types_helper.c b/kmicromail/libetpan/imf/mailimf_types_helper.c new file mode 100644 index 0000000..065b132 --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_types_helper.c @@ -0,0 +1,1636 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mailimf_types_helper.h" + +#include +#include +#include +#include + +#include "mailimf.h" + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty() +{ + clist * list; + struct mailimf_mailbox_list * mb_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) + return NULL; + + return mb_list; +} + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb) +{ + int r; + + r = clist_append(mailbox_list->mb_list, mb); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str) +{ + int r; + size_t cur_token; + struct mailimf_mailbox * mb; + int res; + + cur_token = 0; + r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + + + +struct mailimf_address_list * +mailimf_address_list_new_empty() +{ + clist * list; + struct mailimf_address_list * addr_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) + return NULL; + + return addr_list; +} + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr) +{ + int r; + + r = clist_append(address_list->ad_list, addr); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str) +{ + int r; + size_t cur_token; + struct mailimf_address * addr; + int res; + + cur_token = 0; + r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_address_free(addr); + err: + return res; +} + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr; + } + + return MAILIMF_NO_ERROR; + + free_addr: + mailimf_address_free(addr); + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + + +#if 0 +struct mailimf_resent_fields_list * +mailimf_resent_fields_list_new_empty() +{ + clist * list; + struct mailimf_resent_fields_list * rf_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + rf_list = mailimf_resent_fields_list_new(list); + if (rf_list == NULL) + return NULL; + + return rf_list; +} + +int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields, + struct mailimf_resent_field * field) +{ + int r; + + r = clist_append(fields->list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} +#endif + + +static void detach_free_common_fields(struct mailimf_orig_date * imf_date, + struct mailimf_from * imf_from, + struct mailimf_sender * imf_sender, + struct mailimf_to * imf_to, + struct mailimf_cc * imf_cc, + struct mailimf_bcc * imf_bcc, + struct mailimf_message_id * imf_msg_id) +{ + if (imf_date != NULL) { + imf_date->dt_date_time = NULL; + mailimf_orig_date_free(imf_date); + } + if (imf_from != NULL) { + imf_from->frm_mb_list = NULL; + mailimf_from_free(imf_from); + } + if (imf_sender != NULL) { + imf_sender->snd_mb = NULL; + mailimf_sender_free(imf_sender); + } + if (imf_to != NULL) { + imf_to->to_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_cc != NULL) { + imf_cc->cc_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_bcc != NULL) { + imf_bcc->bcc_addr_list = NULL; + mailimf_bcc_free(imf_bcc); + } + if (imf_msg_id != NULL) { + imf_msg_id->mid_value = NULL; + mailimf_message_id_free(imf_msg_id); + } +} + +static void detach_resent_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id) +{ + struct mailimf_orig_date * imf_resent_date; + struct mailimf_from * imf_resent_from; + struct mailimf_sender * imf_resent_sender; + struct mailimf_to * imf_resent_to; + struct mailimf_cc * imf_resent_cc; + struct mailimf_bcc * imf_resent_bcc; + struct mailimf_message_id * imf_resent_msg_id; + struct mailimf_field * field; + int r; + + imf_resent_date = NULL; + imf_resent_from = NULL; + imf_resent_sender = NULL; + imf_resent_to = NULL; + imf_resent_cc = NULL; + imf_resent_bcc = NULL; + imf_resent_msg_id = NULL; + field = NULL; + + if (resent_date != NULL) { + imf_resent_date = mailimf_orig_date_new(resent_date); + if (imf_resent_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE, + NULL /* return-path */, + imf_resent_date /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_from != NULL) { + imf_resent_from = mailimf_from_new(resent_from); + if (imf_resent_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM, + NULL /* return-path */, + NULL /* resent date */, + imf_resent_from /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_sender != NULL) { + imf_resent_sender = mailimf_sender_new(resent_sender); + if (imf_resent_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + imf_resent_sender /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_to != NULL) { + imf_resent_to = mailimf_to_new(resent_to); + if (imf_resent_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + imf_resent_to /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_cc != NULL) { + imf_resent_cc = mailimf_cc_new(resent_cc); + if (imf_resent_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + imf_resent_cc /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_bcc != NULL) { + imf_resent_bcc = mailimf_bcc_new(resent_bcc); + if (imf_resent_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + imf_resent_bcc /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_msg_id != NULL) { + imf_resent_msg_id = mailimf_message_id_new(resent_msg_id); + if (imf_resent_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + imf_resent_msg_id /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_resent_field(field); + mailimf_field_free(field); + } + free: + detach_free_common_fields(imf_resent_date, + imf_resent_from, + imf_resent_sender, + imf_resent_to, + imf_resent_cc, + imf_resent_bcc, + imf_resent_msg_id); + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, + struct mailimf_mailbox_list * + resent_from, + struct mailimf_mailbox * + resent_sender, + struct mailimf_address_list * + resent_to, + struct mailimf_address_list * + resent_cc, + struct mailimf_address_list * + resent_bcc, + char * resent_msg_id) +{ + struct mailimf_fields * resent_fields; + int r; + + resent_fields = mailimf_fields_new_empty(); + if (resent_fields == NULL) + goto err; + + r = mailimf_resent_fields_add_data(resent_fields, + resent_date, resent_from, + resent_sender, resent_to, + resent_cc, resent_bcc, + resent_msg_id); + if (r != MAILIMF_NO_ERROR) + goto free; + + return resent_fields; + + free: + mailimf_fields_free(resent_fields); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_resent_fields_new_with_data_all(date, + from, sender, to, cc, bcc, msg_id); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_fields_new_empty(void) +{ + clist * list; + struct mailimf_fields * fields_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + fields_list = mailimf_fields_new(list); + if (fields_list == NULL) + return NULL; + + return fields_list; +} + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void detach_free_fields(struct mailimf_orig_date * date, + struct mailimf_from * from, + struct mailimf_sender * sender, + struct mailimf_reply_to * reply_to, + struct mailimf_to * to, + struct mailimf_cc * cc, + struct mailimf_bcc * bcc, + struct mailimf_message_id * msg_id, + struct mailimf_in_reply_to * in_reply_to, + struct mailimf_references * references, + struct mailimf_subject * subject) +{ + detach_free_common_fields(date, + from, + sender, + to, + cc, + bcc, + msg_id); + + if (reply_to != NULL) { + reply_to->rt_addr_list = NULL; + mailimf_reply_to_free(reply_to); + } + + if (in_reply_to != NULL) { + in_reply_to->mid_list = NULL; + mailimf_in_reply_to_free(in_reply_to); + } + + if (references != NULL) { + references->mid_list = NULL; + mailimf_references_free(references); + } + + if (subject != NULL) { + subject->sbj_value = NULL; + mailimf_subject_free(subject); + } +} + + +static void detach_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_orig_date * imf_date; + struct mailimf_from * imf_from; + struct mailimf_sender * imf_sender; + struct mailimf_reply_to * imf_reply_to; + struct mailimf_to * imf_to; + struct mailimf_cc * imf_cc; + struct mailimf_bcc * imf_bcc; + struct mailimf_message_id * imf_msg_id; + struct mailimf_references * imf_references; + struct mailimf_in_reply_to * imf_in_reply_to; + struct mailimf_subject * imf_subject; + struct mailimf_field * field; + int r; + + imf_date = NULL; + imf_from = NULL; + imf_sender = NULL; + imf_reply_to = NULL; + imf_to = NULL; + imf_cc = NULL; + imf_bcc = NULL; + imf_msg_id = NULL; + imf_references = NULL; + imf_in_reply_to = NULL; + imf_subject =NULL; + field = NULL; + + if (date != NULL) { + imf_date = mailimf_orig_date_new(date); + if (imf_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + imf_date /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (from != NULL) { + imf_from = mailimf_from_new(from); + if (imf_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + imf_from /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (sender != NULL) { + imf_sender = mailimf_sender_new(sender); + if (imf_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + imf_sender /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (reply_to != NULL) { + imf_reply_to = mailimf_reply_to_new(reply_to); + if (imf_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + imf_reply_to /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (to != NULL) { + imf_to = mailimf_to_new(to); + if (imf_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + imf_to /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (cc != NULL) { + imf_cc = mailimf_cc_new(cc); + if (imf_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + imf_cc /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (bcc != NULL) { + imf_bcc = mailimf_bcc_new(bcc); + if (imf_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + imf_bcc /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (msg_id != NULL) { + imf_msg_id = mailimf_message_id_new(msg_id); + if (imf_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + imf_msg_id /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (in_reply_to != NULL) { + imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to); + if (imf_in_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + imf_in_reply_to /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (references != NULL) { + imf_references = mailimf_references_new(references); + if (imf_references == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + imf_references /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (subject != NULL) { + imf_subject = mailimf_subject_new(subject); + if (imf_subject == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + imf_subject /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_field(field); + mailimf_field_free(field); + } + free: + detach_free_fields(imf_date, + imf_from, + imf_sender, + imf_reply_to, + imf_to, + imf_cc, + imf_bcc, + imf_msg_id, + imf_in_reply_to, + imf_references, + imf_subject); + + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_fields * fields; + int r; + + fields = mailimf_fields_new_empty(); + if (fields == NULL) + goto err; + + r = mailimf_fields_add_data(fields, + date, + from, + sender, + reply_to, + to, + cc, + bcc, + message_id, + in_reply_to, + references, + subject); + if (r != MAILIMF_NO_ERROR) + goto free; + + return fields; + + free: + mailimf_fields_free(fields); + err: + return NULL; +} + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_fields_new_with_data_all(date, + from, sender, reply_to, + to, cc, bcc, + msg_id, + in_reply_to, references, + subject); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + + +#define MAX_MESSAGE_ID 512 + +char * mailimf_get_message_id(void) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s", + now, value, getpid(), name); + + return strdup(id); +} + + + +static time_t mkgmtime(struct tm * tmp); + + +struct mailimf_date_time * mailimf_get_current_date(void) +{ + struct tm gmt; + struct tm lt; + int off; + time_t now; + struct mailimf_date_time * date_time; + + now = time(NULL); + + if (gmtime_r(&now, &gmt) == NULL) + return NULL; + + if (localtime_r(&now, <) == NULL) + return NULL; + + off = (mkgmtime(<) - mkgmtime(&gmt)) / (60 * 60) * 100; + + date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + + + +/* mkgmtime.c - make time corresponding to a GMT timeval struct + $Id$ + + * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + */ +/* + * Copyright (c) 1987, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +/* + adapted for libEtPan! by DINH V. Hoa +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + mytm = gmtime(&t); + dir = tmcomp(mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} + + + + + + + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailimf_single_fields)); + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + if (single_fields->fld_orig_date == NULL) + single_fields->fld_orig_date = field->fld_data.fld_orig_date; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_FROM: + if (single_fields->fld_from == NULL) { + single_fields->fld_from = field->fld_data.fld_from; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_from->frm_mb_list->mb_list, + field->fld_data.fld_from->frm_mb_list->mb_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_SENDER: + if (single_fields->fld_sender == NULL) + single_fields->fld_sender = field->fld_data.fld_sender; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REPLY_TO: + if (single_fields->fld_reply_to == NULL) { + single_fields->fld_reply_to = field->fld_data.fld_reply_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list, + field->fld_data.fld_reply_to->rt_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_TO: + if (single_fields->fld_to == NULL) { + single_fields->fld_to = field->fld_data.fld_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_to->to_addr_list->ad_list, + field->fld_data.fld_to->to_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_CC: + if (single_fields->fld_cc == NULL) { + single_fields->fld_cc = field->fld_data.fld_cc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_cc->cc_addr_list->ad_list, + field->fld_data.fld_cc->cc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_BCC: + if (single_fields->fld_bcc == NULL) { + single_fields->fld_bcc = field->fld_data.fld_bcc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list, + field->fld_data.fld_bcc->bcc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + if (single_fields->fld_message_id == NULL) + single_fields->fld_message_id = field->fld_data.fld_message_id; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + if (single_fields->fld_in_reply_to == NULL) + single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REFERENCES: + if (single_fields->fld_references == NULL) + single_fields->fld_references = field->fld_data.fld_references; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_SUBJECT: + if (single_fields->fld_subject == NULL) + single_fields->fld_subject = field->fld_data.fld_subject; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_COMMENTS: + if (single_fields->fld_comments == NULL) + single_fields->fld_comments = field->fld_data.fld_comments; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_KEYWORDS: + if (single_fields->fld_keywords == NULL) + single_fields->fld_keywords = field->fld_data.fld_keywords; + cur = clist_next(cur); + break; + default: + cur = clist_next(cur); + break; + } + } +} + + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields) +{ + struct mailimf_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailimf_single_fields)); + if (single_fields == NULL) + goto err; + + mailimf_single_fields_init(single_fields, fields); + + return single_fields; + + err: + return NULL; +} + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value) +{ + struct mailimf_optional_field * opt_field; + struct mailimf_field * field; + + opt_field = mailimf_optional_field_new(name, value); + if (opt_field == NULL) + goto err; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, opt_field); + if (field == NULL) + goto free_opt_field; + + return field; + + free_opt_field: + mailimf_optional_field_free(opt_field); + err: + return NULL; +} diff --git a/kmicromail/libetpan/imf/mailimf_types_helper.h b/kmicromail/libetpan/imf/mailimf_types_helper.h new file mode 100644 index 0000000..e542b4b --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_types_helper.h @@ -0,0 +1,370 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +struct mailimf_address_list * +mailimf_address_list_new_empty(); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +struct mailimf_date_time * mailimf_get_current_date(void); + + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imf/mailimf_write.c b/kmicromail/libetpan/imf/mailimf_write.c new file mode 100644 index 0000000..2935f7f --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_write.c @@ -0,0 +1,2021 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimf_write.h" + +#include +#include +#include + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from); +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to); +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write(FILE * f, int * col, + clist * list); +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references); +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr); +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write(FILE * f, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(FILE * f, const char * str, size_t length) +{ + if (length != 0) { + int r; + + r = fwrite(str, 1, length, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write(FILE * f, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write(f, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write(f, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write(f, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write(f, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + const char * word_end; + const char * next_word; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + word_end = p; + next_word = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write(f, col, word_begin, p - word_begin); + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write(f, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write(FILE * f, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write(f, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write(f, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write(f, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write(f, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write(f, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write(f, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write(f, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write(f, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write(f, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write(f, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write(f, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write(f, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write(f, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write(f, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write(f, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write(f, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + fputc('\"', f); + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = fputc('\\', f); + if (r < 0) + return MAILIMF_ERROR_FILE; + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + fputc('\"', f); + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write(f, col, "<", 1); + else + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write(f, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write(f, col, " (X)", 4); +#endif + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write(f, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write(FILE * f, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write(FILE * f, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write(f, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write(f, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write(f, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write(f, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write(FILE * f, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write(FILE * f, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write(f, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write(f, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write(f, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write(f, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write(f, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} diff --git a/kmicromail/libetpan/imf/mailimf_write.h b/kmicromail/libetpan/imf/mailimf_write.h new file mode 100644 index 0000000..b3e61ab --- a/dev/null +++ b/kmicromail/libetpan/imf/mailimf_write.h @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/carray.h b/kmicromail/libetpan/include/libetpan/carray.h new file mode 100644 index 0000000..06003aa --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/carray.h @@ -0,0 +1,124 @@ + +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CARRAY_H +#define CARRAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct carray_s { + void ** array; + unsigned int len; + unsigned int max; +}; + +typedef struct carray_s carray; + +/* Creates a new array of pointers, with initsize preallocated cells */ +carray * carray_new(unsigned int initsize); + +/* Adds the pointer to data in the array. + Returns the index of the pointer in the array or -1 on error */ +int carray_add(carray * array, void * data, unsigned int * index); + +int carray_set_size(carray * array, unsigned int new_size); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS changed. */ +int carray_delete(carray * array, unsigned int indx); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS not changed. */ +int carray_delete_slow(carray * array, unsigned int indx); + +/* remove without decreasing the size of the array */ +int carray_delete_fast(carray * array, unsigned int indx); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns the array itself */ +void ** carray_data(carray *); + +/* Returns the number of elements in the array */ +int carray_count(carray *); + +/* Returns the contents of one cell */ +void * carray_get(carray * array, unsigned int indx); + +/* Sets the contents of one cell */ +void carray_set(carray * array, unsigned int indx, void * value); + +#else + +#if 0 +#define carray_data(a) (a->array) +#define carray_count(a) (a->len) +#define carray_get(a, indx) (a->array[indx]) +#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0) +#endif + +static inline void ** carray_data(carray * array) { + return array->array; +} + +static inline unsigned int carray_count(carray * array) { + return array->len; +} + +static inline void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +static inline void carray_set(carray * array, + unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +void carray_free(carray * array); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/charconv.h b/kmicromail/libetpan/include/libetpan/charconv.h new file mode 100644 index 0000000..5a435ff --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/charconv.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CHARCONV_H + +#define CHARCONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum { + MAIL_CHARCONV_NO_ERROR = 0, + MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET, + MAIL_CHARCONV_ERROR_MEMORY, + MAIL_CHARCONV_ERROR_CONV, +}; + +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result); + +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len); + +void charconv_buffer_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/chash.h b/kmicromail/libetpan/include/libetpan/chash.h new file mode 100644 index 0000000..3b2b7d3 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/chash.h @@ -0,0 +1,166 @@ + +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CHASH_H +#define CHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void * data; + unsigned int len; +} chashdatum; + +struct chash { + unsigned int size; + unsigned int count; + int copyvalue; + int copykey; + struct chashcell ** cells; +}; + +typedef struct chash chash; + +struct chashcell { + unsigned int func; + chashdatum key; + chashdatum value; + struct chashcell * next; +}; + +typedef struct chashcell chashiter; + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +#define CHASH_DEFAULTSIZE 13 + +/* Allocates a new (empty) hash using this initial size and the given flags, + specifying which data should be copied in the hash. + CHASH_COPYNONE : Keys/Values are not copied. + CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. + CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. + CHASH_COPYALL : Both keys and values are dupped in the hash. + */ +chash * chash_new(unsigned int size, int flags); + +/* Frees a hash */ +void chash_free(chash * hash); + +/* Removes all elements from a hash */ +void chash_clear(chash * hash); + +/* Adds an entry in the hash table. + Length can be 0 if key/value are strings. + If an entry already exists for this key, it is replaced, and its value + is returned. Otherwise, the data pointer will be NULL and the length + field be set to TRUE or FALSe to indicate success or failure. */ +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue); + +/* Retrieves the data associated to the key if it is found in the hash table. + The data pointer and the length will be NULL if not found*/ +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + +/* Removes the entry associated to this key if it is found in the hash table, + and returns its contents if not dupped (otherwise, pointer will be NULL + and len TRUE). If entry is not found both pointer and len will be NULL. */ +int chash_delete(chash * hash, + chashdatum * key, + chashdatum * oldvalue); + +/* Resizes the hash table to the passed size. */ +int chash_resize(chash * hash, unsigned int size); + +/* Returns an iterator to the first non-empty entry of the hash table */ +chashiter * chash_begin(chash * hash); + +/* Returns the next non-empty entry of the hash table */ +chashiter * chash_next(chash * hash, chashiter * iter); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS +/* Returns the size of the hash table */ +unsigned int chash_size(chash * hash); + +/* Returns the number of entries in the hash table */ +unsigned int chash_count(chash * hash); + +/* Returns the key part of the entry pointed by the iterator */ +void chash_key(chashiter * iter, chashdatum * result); + +/* Returns the value part of the entry pointed by the iterator */ +void chash_value(chashiter * iter, chashdatum * result); + +#else +static inline unsigned int chash_size(chash * hash) +{ + return hash->size; +} + +static inline unsigned int chash_count(chash * hash) +{ + return hash->count; +} + +static inline void chash_key(chashiter * iter, chashdatum * result) +{ + * result = iter->key; +} + +static inline void chash_value(chashiter * iter, chashdatum * result) +{ + * result = iter->value; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/cinthash.h b/kmicromail/libetpan/include/libetpan/cinthash.h new file mode 100644 index 0000000..7e59dff --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/cinthash.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CINTHASH_H + +#define CINTHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cinthash_t { + struct cinthash_list * table; + unsigned long hashtable_size ; + unsigned long count; +} cinthash_t; + +cinthash_t * cinthash_new(unsigned long hashtable_size); +void cinthash_free(cinthash_t * table); + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data); +int cinthash_remove(cinthash_t * table, unsigned long hash); +void * cinthash_find(cinthash_t * table, unsigned long hash); + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data); + +void cinthash_foreach_data(cinthash_t * table, + void (* fun)(void *, void *), + void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/clist.h b/kmicromail/libetpan/include/libetpan/clist.h new file mode 100644 index 0000000..bd97f59 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/clist.h @@ -0,0 +1,134 @@ + +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CLIST_H +#define CLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clistcell_s { + void * data; + struct clistcell_s * previous; + struct clistcell_s * next; +} clistcell; + +struct clist_s { + clistcell * first; + clistcell * last; + int count; +}; + +typedef struct clist_s clist; +typedef clistcell clistiter; + +/* Allocate a new pointer list */ +clist * clist_new(); + +/* Destroys a list. Data pointed by data pointers is NOT freed. */ +void clist_free(clist *); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns TRUE if list is empty */ +int clist_isempty(clist *); + +/* Returns the number of elements in the list */ +int clist_count(clist *); + +/* Returns an iterator to the first element of the list */ +clistiter * clist_begin(clist *); + +/* Returns an iterator to the last element of the list */ +clistiter * clist_end(clist *); + +/* Returns an iterator to the next element of the list */ +clistiter * clist_next(clistiter *); + +/* Returns an iterator to the previous element of the list */ +clistiter * clist_previous(clistiter *); + +/* Returns the data pointer of this element of the list */ +void* clist_content(clistiter *); + +/* Inserts this data pointer at the beginning of the list */ +int clist_prepend(clist *, void *); + +/* Inserts this data pointer at the end of the list */ +int clist_append(clist *, void *); +#else +#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL)) +#define clist_count(lst) (lst->count) +#define clist_begin(lst) (lst->first) +#define clist_end(lst) (lst->last) +#define clist_next(iter) (iter ? iter->next : NULL) +#define clist_previous(iter) (iter ? iter->previous : NULL) +#define clist_content(iter) (iter ? iter->data : NULL) +#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data)) +#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data)) +#endif + +/* Inserts this data pointer before the element pointed by the iterator */ +int clist_insert_before(clist *, clistiter *, void *); + +/* Inserts this data pointer after the element pointed by the iterator */ +int clist_insert_after(clist *, clistiter *, void *); + +/* Deletes the element pointed by the iterator. + Returns an iterator to the next element. */ +clistiter * clist_delete(clist *, clistiter *); + +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + +void clist_concat(clist * dest, clist * src); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/data_message_driver.h b/kmicromail/libetpan/include/libetpan/data_message_driver.h new file mode 100644 index 0000000..e0ee752 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/data_message_driver.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef DATA_MESSAGE_DRIVER_H + +#define DATA_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_DATA_MESSAGE + +extern mailmessage_driver * data_message_driver; + +mailmessage * data_message_init(char * data, size_t len); + +void data_message_detach_mime(mailmessage * msg); + +#endif diff --git a/kmicromail/libetpan/include/libetpan/generic_cache_types.h b/kmicromail/libetpan/include/libetpan/generic_cache_types.h new file mode 100644 index 0000000..8803a42 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/generic_cache_types.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef GENERIC_CACHE_TYPE_H + +#define GENERIC_CACHE_TYPE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_flags_store { + carray * fls_tab; + chash * fls_hash; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapdriver.h b/kmicromail/libetpan/include/libetpan/imapdriver.h new file mode 100644 index 0000000..2bf36c7 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_H + +#define IMAPDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * imap_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapdriver_cached.h b/kmicromail/libetpan/include/libetpan/imapdriver_cached.h new file mode 100644 index 0000000..92bb60d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_CACHED_H + +#define IMAPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * imap_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapdriver_cached_message.h b/kmicromail/libetpan/include/libetpan/imapdriver_cached_message.h new file mode 100644 index 0000000..49d63cb --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_CACHED_MESSAGE_H + +#define IMAPDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapdriver_message.h b/kmicromail/libetpan/include/libetpan/imapdriver_message.h new file mode 100644 index 0000000..9142633 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_MESSAGE_H + +#define IMAPDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapdriver_types.h b/kmicromail/libetpan/include/libetpan/imapdriver_types.h new file mode 100644 index 0000000..d4e216d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapdriver_types.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPDRIVER_TYPES_H + +#define IMAPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IMAP driver for session */ + +struct imap_session_state_data { + mailimap * imap_session; + char * imap_mailbox; + struct mail_flags_store * imap_flags_store; +}; + +enum { + IMAP_SECTION_MESSAGE, + IMAP_SECTION_HEADER, + IMAP_SECTION_MIME, + IMAP_SECTION_BODY +}; + +/* cached IMAP driver for session */ + +enum { + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, +}; + +struct imap_cached_session_state_data { + mailsession * imap_ancestor; + char * imap_quoted_mb; + char imap_cache_directory[PATH_MAX]; + carray * imap_uid_list; +}; + + +/* IMAP storage */ + +/* + imap_mailstorage is the state data specific to the IMAP4rev1 storage. + + - servername this is the name of the IMAP4rev1 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - command, if non-NULL the command used to connect to the + server instead of allowing normal TCP connections to be used. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or + CONNECTION_TYPE_COMMAND. + + - auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + - login is the login of the IMAP4rev1 account. + + - password is the password of the IMAP4rev1 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache +*/ + +struct imap_mailstorage { + char * imap_servername; + uint16_t imap_port; + char * imap_command; + int imap_connection_type; + + int imap_auth_type; + char * imap_login; + char * imap_password; + + int imap_cached; + char * imap_cache_directory; +}; + +/* this is the type of IMAP4rev1 authentication */ + +enum { + IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */ + IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/imapstorage.h b/kmicromail/libetpan/include/libetpan/imapstorage.h new file mode 100644 index 0000000..ebc42b0 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/imapstorage.h @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef IMAPSTORAGE_H + +#define IMAPSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + imap_mailstorage_init is the constructor for a IMAP4rev1 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the IMAP4rev1 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + @param login is the login of the IMAP4rev1 account. + + @param password is the password of the IMAP4rev1 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache +*/ + +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/libetpan-config.h b/kmicromail/libetpan/include/libetpan/libetpan-config.h new file mode 100644 index 0000000..20d1e62 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/libetpan-config.h @@ -0,0 +1,7 @@ +#ifndef LIBETPAN_CONFIG_H +#define LIBETPAN_CONFIG_H +#include +#include +#define MAIL_DIR_SEPARATOR '/' +#define MAIL_DIR_SEPARATOR_S "/" +#endif diff --git a/kmicromail/libetpan/include/libetpan/libetpan.h b/kmicromail/libetpan/include/libetpan/libetpan.h new file mode 100644 index 0000000..3b4a107 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/libetpan.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef LIBETPAN_H + +#define LIBETPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +/* mbox driver */ +#include +#include +#include +#include +#include + +/* MH driver */ +#include +#include +#include +#include +#include + +/* IMAP4rev1 driver */ +#include +#include +#include +#include +#include + +/* POP3 driver */ +#include +#include +#include +#include +#include + +/* NNTP driver */ +#include +#include +#include +#include +#include + +/* maildir driver */ +#include +#include +#include +#include +#include + +/* message which content is given by a MIME structure */ +#include + +/* message which content given by a string */ +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/libetpan_version.h b/kmicromail/libetpan/include/libetpan/libetpan_version.h new file mode 100644 index 0000000..5f9e5cf --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/libetpan_version.h @@ -0,0 +1,51 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR 0 +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR 32 +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mail.h b/kmicromail/libetpan/include/libetpan/mail.h new file mode 100644 index 0000000..d4c63c4 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mail.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_H + +#define MAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildir.h b/kmicromail/libetpan/include/libetpan/maildir.h new file mode 100644 index 0000000..b782484 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildir.h @@ -0,0 +1,60 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIR_H + +#define MAILDIR_H + +#include + +struct maildir * maildir_new(const char * path); + +void maildir_free(struct maildir * md); + +int maildir_update(struct maildir * md); + +int maildir_message_add(struct maildir * md, + const char * message, size_t size); + +int maildir_message_add_file(struct maildir * md, int fd); + +char * maildir_message_get(struct maildir * md, const char * uid); + +int maildir_message_remove(struct maildir * md, const char * uid); + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags); + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildir_types.h b/kmicromail/libetpan/include/libetpan/maildir_types.h new file mode 100644 index 0000000..c7e368e --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildir_types.h @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIR_TYPES_H + +#define MAILDIR_TYPES_H + +#include +#include +#include +#include +#include + +#include + +#define LIBETPAN_MAILDIR + +enum { + MAILDIR_NO_ERROR = 0, + MAILDIR_ERROR_CREATE, + MAILDIR_ERROR_DIRECTORY, + MAILDIR_ERROR_MEMORY, + MAILDIR_ERROR_FILE, + MAILDIR_ERROR_NOT_FOUND, +}; + +#define MAILDIR_FLAG_NEW (1 << 0) +#define MAILDIR_FLAG_SEEN (1 << 1) +#define MAILDIR_FLAG_REPLIED (1 << 2) +#define MAILDIR_FLAG_FLAGGED (1 << 3) +#define MAILDIR_FLAG_TRASHED (1 << 4) + +struct maildir_msg { + char * msg_uid; + char * msg_filename; + int msg_flags; +}; + +/* + work around for missing #define HOST_NAME_MAX in Linux +*/ + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +struct maildir { + pid_t mdir_pid; + char mdir_hostname[HOST_NAME_MAX]; + char mdir_path[PATH_MAX]; + uint32_t mdir_counter; + time_t mdir_mtime_new; + time_t mdir_mtime_cur; + carray * mdir_msg_list; + chash * mdir_msg_hash; +}; + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirdriver.h b/kmicromail/libetpan/include/libetpan/maildirdriver.h new file mode 100644 index 0000000..f59cf3e --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_H + +#define MAILDIRDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirdriver_cached.h b/kmicromail/libetpan/include/libetpan/maildirdriver_cached.h new file mode 100644 index 0000000..81de3c3 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirdriver_cached.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_CACHED_H + +#define MAILDIRDRIVER_CACHED_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirdriver_cached_message.h b/kmicromail/libetpan/include/libetpan/maildirdriver_cached_message.h new file mode 100644 index 0000000..399ecaa --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H + +#define MAILDIRDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirdriver_message.h b/kmicromail/libetpan/include/libetpan/maildirdriver_message.h new file mode 100644 index 0000000..cb378bc --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_MESSAGE_H + +#define MAILDIRDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirdriver_types.h b/kmicromail/libetpan/include/libetpan/maildirdriver_types.h new file mode 100644 index 0000000..cb3661f --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirdriver_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRDRIVER_TYPES_H + +#define MAILDIRDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct maildir_session_state_data { + struct maildir * md_session; + struct mail_flags_store * md_flags_store; +}; + +enum { + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct maildir_cached_session_state_data { + mailsession * md_ancestor; + char * md_quoted_mb; + struct mail_flags_store * md_flags_store; + char md_cache_directory[PATH_MAX]; + char md_flags_directory[PATH_MAX]; +}; + +/* maildir storage */ + +/* + maildir_mailstorage is the state data specific to the maildir storage. + + - pathname is the path of the maildir storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct maildir_mailstorage { + char * md_pathname; + + int md_cached; + char * md_cache_directory; + char * md_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildirstorage.h b/kmicromail/libetpan/include/libetpan/maildirstorage.h new file mode 100644 index 0000000..d17ea2c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildirstorage.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIRSTORAGE_H + +#define MAILDIRSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + maildir_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int maildir_mailstorage_init(struct mailstorage * storage, + char * md_pathname, int md_cached, + char * md_cache_directory, char * md_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildriver.h b/kmicromail/libetpan/include/libetpan/maildriver.h new file mode 100644 index 0000000..7da9aea --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildriver.h @@ -0,0 +1,543 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_H + +#define MAILDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mailsession */ + +/* + mailsession_new creates a new session, using the given driver + + @return the created session is returned +*/ + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +/* + mailsession_free release the memory used by the session +*/ + +void mailsession_free(mailsession * session); + +/* + mailsession_parameters is used to make calls specific to the driver + + @param id is the command to send to the driver, + usually, commands can be found in the header of the driver + + @param value is the parameter of the specific call + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_parameters(mailsession * session, + int id, void * value); + +/* + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) + + The following function can only be used by stream drivers. + mailsession_connect_stream connects a stream to the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_connect_stream(mailsession * session, mailstream * s); + +/* + The following function can only be used by file drivers. + mailsession_connect_path selects the main path of the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_connect_path(mailsession * session, char * path); + +/* + NOTE: works only on stream drivers + + mailsession_starttls switches the current connection to TLS (secure layer) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_starttls(mailsession * session); + +/* + mailsession_login notifies the login and the password to authenticate + to the session + + @param userid the given string is only needed at this function call + (it will be duplicated if necessary) + @param password the given string is only needed at this function call + (it will be duplicated if necessary) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_login(mailsession * session, + char * userid, char * password); + +/* + NOTE: this function doesn't often work on filsystem drivers + + mailsession_logout deconnects the session and closes the stream. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_logout(mailsession * session); + +/* + mailsession_noop does no operation on the session, but it can be + used to poll for the status of the connection. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_noop(mailsession * session); + +/* + NOTE: driver's specific should be used + + mailsession_build_folder_name will return an allocated string with + that contains the complete path of the folder to create + + @param session the sesion + @param mb is the parent mailbox + @param name is the name of the folder to create + @param result the complete path of the folder to create will be + stored in (* result), this name have to be freed with free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_build_folder_name(mailsession * session, char * mb, + char * name, char ** result); + +/* + NOTE: driver's specific should be used + + mailsession_create_folder creates the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_create_folder(mailsession * session, char * mb); + + +/* + NOTE: driver's specific should be used + + mailsession_delete_folder deletes the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_delete_folder(mailsession * session, char * mb); + + +/* + mailsession_rename_folder changes the name of the folder + + @param session the session + @param mb is the name of the mailbox whose name has to be changed + @param new_name is the destination name (the parent + of the new folder folder can be other) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_rename_folder(mailsession * session, + char * mb, char * new_name); + +/* + mailsession_check_folder makes a checkpoint of the session + + @param session the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_check_folder(mailsession * session); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_examine_folder selects a mailbox as readonly + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_examine_folder(mailsession * session, char * mb); + + +/* + mailsession_select_folder selects a mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_select_folder(mailsession * session, char * mb); + + +/* + mailsession_expunge_folder deletes all messages marked \Deleted + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_expunge_folder(mailsession * session); + + +/* + mailsession_status_folder queries the status of the folder + (number of messages, number of recent messages, number of unseen messages) + + @param session the session + @param mb mailbox to query + @param result_messages the number of messages is stored + in (* result_messages) + @param result_recent the number of messages is stored + in (* result_recent) + @param result_unseen the number of messages is stored + in (* result_unseen) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + +/* + mailsession_messages_number queries the number of messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + +/* + mailsession_recent_number queries the number of recent messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of recent messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + +/* + mailsession_unseen_number queries the number of unseen messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of unseen messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + +/* + NOTE: driver's specific should be used + + mailsession_list_folders returns the list of all sub-mailboxes + of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_list_folders(mailsession * session, char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_lsub_folders returns the list of subscribed + sub-mailboxes of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_lsub_folders(mailsession * session, char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_subscribe_folder subscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_subscribe_folder(mailsession * session, char * mb); + +/* + NOTE: driver's specific should be used + + mailsession_unsubscribe_folder unsubscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_unsubscribe_folder(mailsession * session, char * mb); + +/* + mailsession_append_message adds a RFC 2822 message to the current + given mailbox + + @param session the session + @param message is a string that contains the RFC 2822 message + @param size this is the size of the message + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + +/* + NOTE: some drivers does not implement this + + mailsession_copy_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_copy_message(mailsession * session, + uint32_t num, char * mb); + +/* + NOTE: some drivers does not implement this + + mailsession_move_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_move_message(mailsession * session, + uint32_t num, char * mb); + +/* + mailsession_get_messages_list returns the list of message numbers + of the current mailbox. + + @param session the session + @param result the list of message numbers will be stored in (* result), + this structure have to be freed with mailmessage_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +/* + mailsession_get_envelopes_list fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + @param session the session + @param result this is the list of mailmessage structures + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + +/* + NOTE: some drivers does not implement this + + mailsession_remove_message removes the given message from the mailbox. + The message is permanently deleted. + + @param session the session + @param num is the message number + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_remove_message(mailsession * session, uint32_t num); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_search_message returns a list of message numbers that + corresponds to the given criteria. + + @param session the session + @param charset is the charset to use (it can be NULL) + @param key is the list of criteria + @param result the search result is stored in (* result), + this structure have to be freed with mail_search_result_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +#if 0 +int mailsession_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +/* + mailsession_get_message returns a mailmessage structure that corresponds + to the given message number. + * WARNING * mailsession_get_message_by_uid() should be used instead. + + @param session the session + @param num the message number + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +/* + mailsession_get_message_by_uid returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + * WARNING * That will deprecates the use of mailsession_get_message() + + @param session the session + @param uid the message unique identifier + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildriver_errors.h b/kmicromail/libetpan/include/libetpan/maildriver_errors.h new file mode 100644 index 0000000..118b259 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildriver_errors.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_ERRORS_H + +#define MAILDRIVER_ERRORS_H + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildriver_types.h b/kmicromail/libetpan/include/libetpan/maildriver_types.h new file mode 100644 index 0000000..3ff9440 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildriver_types.h @@ -0,0 +1,793 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_TYPES_H + +#define MAILDRIVER_TYPES_H + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mailsession_driver mailsession_driver; + +typedef struct mailsession mailsession; + +typedef struct mailmessage_driver mailmessage_driver; + +typedef struct mailmessage mailmessage; + + +/* + mailmessage_list is a list of mailmessage + + - tab is an array of mailmessage structures +*/ + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); +void mailmessage_list_free(struct mailmessage_list * env_list); + +/* + mail_list is a list of mailbox names + + - list is a list of mailbox names +*/ + +struct mail_list { + clist * mb_list; /* elements are (char *) */ +}; + +struct mail_list * mail_list_new(clist * mb_list); +void mail_list_free(struct mail_list * resp); + +/* + This is a flag value. + Flags can be combined with OR operation +*/ + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +/* + mail_flags is the value of a flag related to a message. + + - flags is the standard flags value + + - extension is a list of unknown flags for libEtPan! +*/ + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); +void mail_flags_free(struct mail_flags * flags); + +/* + This function creates a flag for a new message +*/ + +struct mail_flags * mail_flags_new_empty(void); + + +/* + mailimf_date_time_comp compares two dates + + +*/ + +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2); + +/* + this is type type of the search criteria +*/ + +enum { + MAIL_SEARCH_KEY_ALL, /* all messages correspond */ + MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */ + MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains + a given string */ + MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier + than the specified date */ + MAIL_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAIL_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAIL_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAIL_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAIL_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAIL_SEARCH_KEY_NOT, /* not operation of the condition */ + MAIL_SEARCH_KEY_OR, /* or operation between two conditions */ + MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mail_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAIL_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAIL_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAIL_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAIL_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAIL_SEARCH_KEY_FROM, should be allocated with malloc() + + - on is a date when type is MAIL_SEARCH_KEY_ON + + - since is a date when type is MAIL_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +#if 0 +struct mail_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimf_date_time * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + struct mailimf_date_time * sk_on; + struct mailimf_date_time * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_header_name; + char * sk_header_value; + size_t sk_larger; + struct mail_search_key * sk_not; + struct mail_search_key * sk_or1; + struct mail_search_key * sk_or2; + size_t sk_smaller; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + + +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, struct mailimf_date_time * sk_before, + char * sk_body, char * sk_cc, char * sk_from, + struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_header_name, char * sk_header_value, size_t sk_larger, + struct mail_search_key * sk_not, struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, size_t sk_smaller, + clist * sk_multiple); + +void mail_search_key_free(struct mail_search_key * key); +#endif + +/* + mail_search_result is a list of message numbers that is returned + by the mailsession_search_messages function() +*/ + +#if 0 +struct mail_search_result { + clist * sr_list; /* list of (uint32_t *) */ +}; + +struct mail_search_result * mail_search_result_new(clist * sr_list); + +void mail_search_result_free(struct mail_search_result * search_result); +#endif + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - build_folder_name() will return an allocated string with + that contains the complete path of the folder to create + + - create_folder() creates the folder that corresponds to the + given name + + - delete_folder() deletes the folder that corresponds to the + given name + + - rename_folder() change the name of the folder + + - check_folder() makes a checkpoint of the session + + - examine_folder() selects a mailbox as readonly + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - messages_number() queries the number of messages in the folder + + - recent_number() queries the number of recent messages in the folder + + - unseen_number() queries the number of unseen messages in the folder + + - list_folders() returns the list of all sub-mailboxes + of the given mailbox + + - lsub_folders() returns the list of subscribed + sub-mailboxes of the given mailbox + + - subscribe_folder() subscribes to the given mailbox + + - unsubscribe_folder() unsubscribes to the given mailbox + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - copy_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from + the same session. + + - move_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the + same session. + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - search_message() returns a list of message numbers that + corresponds to the given criteria. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + - get_message_by_uid returns a mailmessage structure that corresponds + to the given message unique identifier. + + * mandatory functions are the following : + + - connect_stream() of connect_path() + - logout() + - get_messages_list() + - get_envelopes_list() + + * we advise you to implement these functions : + + - select_folder() (in case a session can access several folders) + - noop() (to check if the server is responding) + - check_folder() (to make a checkpoint of the session) + - status_folder(), messages_number(), recent_number(), unseen_number() + (to get stat of the folder) + - append_message() (but can't be done in the case of POP3 at least) + - login() in a case of an authenticated driver. + - starttls() in a case of a stream driver, if the procotol supports + STARTTLS. + - get_message_by_uid() so that the application can remember the message + by UID and build its own list of messages. + + * drivers' specific : + + Everything that is specific to the driver will be implemented in this + function : + + - parameters() +*/ + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +#if 0 + int (* sess_search_messages)(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif +}; + + +/* + session is the data structure for a mail session. + + - data is the internal data structure used by the driver + It is called when initializing the mailsession structure. + + - driver is the driver used for the session +*/ + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + + + + +/* + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. +*/ + +#define LIBETPAN_MAIL_MESSAGE_CHECK + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + +/* + mailmessage is a data structure to get information from messages + + - session is the session linked to the given message, it can be NULL + + - driver is the message driver + + - index is the message number + + - uid, when it is not NULL, it means that the folder + the folder has persistant message numbers, the string is + the unique message number in the folder. + uid should be implemented if possible. + for drivers where we cannot generate real uid, + a suggestion is "AAAA-IIII" where AAAA is some + random session number and IIII the content of index field. + + - size, when it is not 0, is the size of the message content. + + - fields, when it is not NULL, are the header fields of the message. + + - flags, when it is not NULL, are the flags related to the message. + + - single_fields, when resolved != 0, is filled with the data of fields. + + - mime, when it is not NULL + + - cached is != 0 when the header fields were read from the cache. + + - data is data specific to the driver, this is internal data structure, + some state of the message. +*/ + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + +/* + mailmessage_tree is a node in the messages tree (thread) + + - parent is the parent of the message, it is NULL if the message + is the root of the message tree. + + - date is the date of the message in number of second elapsed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + + - msg is the message structure that is stored referenced by the node. + is msg is NULL, this is a dummy node. + + - children is an array that contains all the children of the node. + children are mailmessage_tree structures. + + - is_reply is != 0 when the message is a reply or a forward + + - base_subject is the extracted subject of the message. + + - index is the message number. +*/ + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +/* + mailmessage_tree_free_recursive + + if you want to release memory of the given tree and all the sub-trees, + you can use this function. +*/ + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + +struct generic_message_t { + int (* msg_prefetch)(mailmessage * msg_info); + void (* msg_prefetch_free)(struct generic_message_t * msg); + int msg_fetched; + char * msg_message; + size_t msg_length; + void * msg_data; +}; + + +const char * maildriver_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/maildriver_types_helper.h b/kmicromail/libetpan/include/libetpan/maildriver_types_helper.h new file mode 100644 index 0000000..2e74dea --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/maildriver_types_helper.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDRIVER_TYPES_HELPER_H + +#define MAILDRIVER_TYPES_HELPER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_flags_add_extension adds the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is duplicated and is no more needed after + the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_remove_extension removes the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_has_extension returns 1 if the flags is in the given flags, + 0 is returned otherwise. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailfolder.h b/kmicromail/libetpan/include/libetpan/mailfolder.h new file mode 100644 index 0000000..3ecad23 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailfolder.h @@ -0,0 +1,32 @@ +#ifndef MAILFOLDER_H + +#define MAILFOLDER_H + +#include "mailstorage_types.h" + +int mailfolder_noop(struct mailfolder * folder); + +int mailfolder_check(struct mailfolder * folder); + +int mailfolder_expunge(struct mailfolder * folder); + +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimap.h b/kmicromail/libetpan/include/libetpan/mailimap.h new file mode 100644 index 0000000..8dfa3d4 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap.h @@ -0,0 +1,598 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +void mailimap_free(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimap_helper.h b/kmicromail/libetpan/include/libetpan/mailimap_helper.h new file mode 100644 index 0000000..d73cf5f --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap_helper.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +int mailimap_append_simple(mailimap * session, char * mailbox, + char * content, uint32_t size); + +int mailimap_login_simple(mailimap * session, + char * userid, char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimap_socket.h b/kmicromail/libetpan/include/libetpan/mailimap_socket.h new file mode 100644 index 0000000..aadc67e --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap_socket.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimap_ssl.h b/kmicromail/libetpan/include/libetpan/mailimap_ssl.h new file mode 100644 index 0000000..76906a0 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap_ssl.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimap_types.h b/kmicromail/libetpan/include/libetpan/mailimap_types.h new file mode 100644 index 0000000..2996b53 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap_types.h @@ -0,0 +1,3274 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] + + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" + + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + lsub = "LSUB" SP mailbox SP list-mailbox + + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. + + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" + + section = "[" [section-spec] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. + + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1* + + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" ', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" ', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" ', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART, /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST, /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* != NULL */ +}; + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER, /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME, /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64, /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* != NULL */ +}; + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION, /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER, /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE, /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of + unseen messages */ +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or + MAILIMAP_STATUS_ATT_UNSEEN + + - value is the value of the given information +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; +}; + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value); + +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + } mbd_data; +}; + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent); + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG, /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER, /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes + (message content) */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC + + - msg_att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - msg_att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + } att_data; +}; + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static); + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID, /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA, /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a reponse data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data); + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL, /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH, /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state reponse + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + } rc_data; +}; + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value); + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT, /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART, /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME, /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +struct mailimap_set * mailimap_set_new(clist * list); + +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without + marking the message as read */ +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; +}; + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size); + + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the + conditions is AND */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + + +void mailimap_search_key_free(struct mailimap_search_key * key); + + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number); + +void mailimap_number_alloc_free(uint32_t * pnumber); + + +void mailimap_addr_host_free(char * addr_host); + +void mailimap_addr_mailbox_free(char * addr_mailbox); + +void mailimap_addr_adl_free(char * addr_adl); + +void mailimap_addr_name_free(char * addr_name); + +void mailimap_astring_free(char * astring); + +void mailimap_atom_free(char * atom); + +void mailimap_auth_type_free(char * auth_type); + +void mailimap_base64_free(char * base64); + +void mailimap_body_fld_desc_free(char * body_fld_desc); + +void mailimap_body_fld_id_free(char * body_fld_id); + +void mailimap_body_fld_md5_free(char * body_fld_md5); + +void mailimap_env_date_free(char * date); + +void mailimap_env_in_reply_to_free(char * in_reply_to); + +void mailimap_env_message_id_free(char * message_id); + +void mailimap_env_subject_free(char * subject); + +void mailimap_flag_extension_free(char * flag_extension); + +void mailimap_flag_keyword_free(char * flag_keyword); + +void +mailimap_header_fld_name_free(char * header_fld_name); + +void mailimap_literal_free(char * literal); + +void mailimap_mailbox_free(char * mailbox); + +void +mailimap_mailbox_data_search_free(clist * data_search); + +void mailimap_media_subtype_free(char * media_subtype); + +void mailimap_media_text_free(char * media_text); + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +void +mailimap_msg_att_rfc822_free(char * str); + +void +mailimap_msg_att_rfc822_header_free(char * str); + +void +mailimap_msg_att_rfc822_text_free(char * str); + +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +void mailimap_nstring_free(char * str); + +void +mailimap_string_free(char * str); + +void mailimap_tag_free(char * tag); + +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a reponse, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; +}; + +typedef struct mailimap mailimap; + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; +}; + +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ +}; + +struct mailimap_response_info * +mailimap_response_info_new(void); + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/include/libetpan/mailimap_types_helper.h b/kmicromail/libetpan/include/libetpan/mailimap_types_helper.h new file mode 100644 index 0000000..bb0bb99 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimap_types_helper.h @@ -0,0 +1,758 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by index +*/ + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index); + +/* + this function creates a new set with one set item + */ + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +struct mailimap_set * mailimap_set_new_single(uint32_t index); + +/* + this function creates an empty set of messages +*/ + +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +struct mailimap_section * mailimap_section_new_header(void); + +/* + this functions creates a mailimap_section structure to describe + a list of headers +*/ + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this functions creates a mailimap_section structure to describe headers + other than those given +*/ + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + +/* + this function creates an empty list of flags +*/ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimf.h b/kmicromail/libetpan/include/libetpan/mailimf.h new file mode 100644 index 0000000..3248e73 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimf.h @@ -0,0 +1,345 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param index this is a pointer to the start of the message in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param index this is a pointer to the start of the message text part in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param index this is a pointer to the start of the address list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param index this is a pointer to the start of the address in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param index this is a pointer to the start of the date in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param index this is a pointer to the start of the header field in + the given string, (* index) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index); + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index); + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index); + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)); + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, index, token) \ + mailimf_token_case_insensitive_len_parse(message, length, index, token, \ + sizeof(token) - 1) + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result); + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result); + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* exported for IMAP */ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimf_types.h b/kmicromail/libetpan/include/libetpan/mailimf_types.h new file mode 100644 index 0000000..288feb6 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimf_types.h @@ -0,0 +1,793 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP, /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +void mailimf_atom_free(char * atom); + +void mailimf_dot_atom_free(char * dot_atom); + +void mailimf_dot_atom_text_free(char * dot_atom); + +void mailimf_quoted_string_free(char * quoted_string); + +void mailimf_word_free(char * word); + +void mailimf_phrase_free(char * phrase); + +void mailimf_unstructured_free(char * unstructured); + +void mailimf_angle_addr_free(char * angle_addr); + +void mailimf_display_name_free(char * display_name); + +void mailimf_addr_spec_free(char * addr_spec); + +void mailimf_local_part_free(char * local_part); + +void mailimf_domain_free(char * domain); + +void mailimf_domain_literal_free(char * domain); + +void mailimf_msg_id_free(char * msg_id); + +void mailimf_id_left_free(char * id_left); + +void mailimf_id_right_free(char * id_right); + +void mailimf_no_fold_quote_free(char * nfq); + +void mailimf_no_fold_literal_free(char * nfl); + +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE, +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimf_types_helper.h b/kmicromail/libetpan/include/libetpan/mailimf_types_helper.h new file mode 100644 index 0000000..e542b4b --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimf_types_helper.h @@ -0,0 +1,370 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +struct mailimf_address_list * +mailimf_address_list_new_empty(); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +struct mailimf_date_time * mailimf_get_current_date(void); + + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailimf_write.h b/kmicromail/libetpan/include/libetpan/mailimf_write.h new file mode 100644 index 0000000..b3e61ab --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailimf_write.h @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmbox.h b/kmicromail/libetpan/include/libetpan/mailmbox.h new file mode 100644 index 0000000..8be086c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmbox.h @@ -0,0 +1,140 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMBOX_H + +#define MAILMBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab); + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len); + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +void mailmbox_fetch_result_free(char * msg); + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab); + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid); + +int mailmbox_expunge(struct mailmbox_folder * folder); + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid); + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder); + +void mailmbox_done(struct mailmbox_folder * folder); + +/* low-level access primitives */ + +int mailmbox_write_lock(struct mailmbox_folder * folder); + +int mailmbox_write_unlock(struct mailmbox_folder * folder); + +int mailmbox_read_lock(struct mailmbox_folder * folder); + +int mailmbox_read_unlock(struct mailmbox_folder * folder); + + +/* memory map */ + +int mailmbox_map(struct mailmbox_folder * folder); + +void mailmbox_unmap(struct mailmbox_folder * folder); + +void mailmbox_sync(struct mailmbox_folder * folder); + + +/* open & close file */ + +int mailmbox_open(struct mailmbox_folder * folder); + +void mailmbox_close(struct mailmbox_folder * folder); + + +/* validate cache */ + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder); + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder); + + +/* fetch message */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +/* append message */ + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab); + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmbox_types.h b/kmicromail/libetpan/include/libetpan/mailmbox_types.h new file mode 100644 index 0000000..dd6758c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmbox_types.h @@ -0,0 +1,142 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMBOX_TYPES_H + +#define MAILMBOX_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include +#include + +enum { + MAILMBOX_NO_ERROR = 0, + MAILMBOX_ERROR_PARSE, + MAILMBOX_ERROR_INVAL, + MAILMBOX_ERROR_FILE_NOT_FOUND, + MAILMBOX_ERROR_MEMORY, + MAILMBOX_ERROR_TEMPORARY_FILE, + MAILMBOX_ERROR_FILE, + MAILMBOX_ERROR_MSG_NOT_FOUND, + MAILMBOX_ERROR_READONLY, +}; + + +struct mailmbox_folder { + char mb_filename[PATH_MAX]; + + time_t mb_mtime; + + int mb_fd; + int mb_read_only; + int mb_no_uid; + + int mb_changed; + unsigned int mb_deleted_count; + + char * mb_mapping; + size_t mb_mapping_size; + + uint32_t mb_written_uid; + uint32_t mb_max_uid; + + chash * mb_hash; + carray * mb_tab; +}; + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename); +void mailmbox_folder_free(struct mailmbox_folder * folder); + + +struct mailmbox_msg_info { + unsigned int msg_index; + uint32_t msg_uid; + int msg_written_uid; + int msg_deleted; + + size_t msg_start; + size_t msg_start_len; + + size_t msg_headers; + size_t msg_headers_len; + + size_t msg_body; + size_t msg_body_len; + + size_t msg_size; + + size_t msg_padding; +}; + + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info); + +struct mailmbox_append_info { + const char * ai_message; + size_t ai_size; +}; + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size); + +void mailmbox_append_info_free(struct mailmbox_append_info * info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmessage.h b/kmicromail/libetpan/include/libetpan/mailmessage.h new file mode 100644 index 0000000..df9b790 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmessage.h @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include + +#ifndef MAILMESSAGE_H + +#define MAILMESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailmessage_new + + This function will initializes a new empty message. + + @return a new empty message will be returned. +*/ + +mailmessage * mailmessage_new(void); + +/* + mailmessage_free + + This function will release the memory used by this message. +*/ + +void mailmessage_free(mailmessage * info); + +/* + mailmessage_init + + This function will initializes a mailmessage structure + with a message from a given session. + + @param msg_info This is the message to initialize. + + @param session This is the source session of the message. It + can be NULL if the message does not get the information + through the session. + + @param driver This is the driver to use for the message. + + @param index This is the message number in the session. 0 can + be given if the message is not attached to a session. + + @param size is an optional parameter, 0 can be given. + This is informational. This is the size of message content. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + +/* + mailmessage_flush + + This function will release all the temporary resources that are not + necessary to use the mailmessage structure from memory. These + resources are for example cached information, such as the MIME + structure. + + @param info is the message to clean. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_flush(mailmessage * info); + +/* + mailmessage_check + + This function will notify the new value of the flags to the session, + it must be called before mailsession_check_folder() in case the flags have + been changed. + + @param info is the message to checkpoint. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_check(mailmessage * info); + +/* + mailmessage_fetch_result_free + + This function releases the memory used by a message returned + by any of the fetch function that returns a (char *). + + @param msg_info is the message which the given buffer is from. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + +/* + mailmessage_fetch + + This function returns the content of the message (headers and text). + + @param msg_info is the message from which we want to fetch information. + + @param result The content of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_header + + This function returns the header of the message as a string. + + @param msg_info is the message from which we want to fetch information. + + @param result The header of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_body + + This function returns the content of the message (without headers). + + @param msg_info is the message from which we want to fetch information. + @param result The message text (without headers) is returned + in (* result) + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_size + + This function returns the size of the message content. + + @param msg_info is the message from which we want to fetch information. + + @param result The length of the message content is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + +/* + mailmessage_get_bodystructure + + This functions returns the MIME structure of the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The MIME structure is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +/* + mailmessage_fetch_section + + This function returns the content of a MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The content is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_section_header + + This function returns the header of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_mime + + This function returns the MIME header of the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The MIME header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_body + + This function returns the text part of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The message text is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_envelope + + This function returns a list of parsed fields of the message, + chosen by the driver. + The returned structure must be freed with mailimf_fields_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The headers list is returned in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + +/* + mailmessage_get_flags + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The flags are stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +/* + mailmessage_resolve_single_fields + + This function will use the fields information to fill the single_fields + structure in the mailmessage structure. + + @param msg_info This is the msg_info to process. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmessage_types.h b/kmicromail/libetpan/include/libetpan/mailmessage_types.h new file mode 100644 index 0000000..655ed2c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmessage_types.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMESSAGE_TYPES_H + +#define MAILMESSAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmh.h b/kmicromail/libetpan/include/libetpan/mailmh.h new file mode 100644 index 0000000..40432cb --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmh.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMH_H + +#define MAILMH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +enum { + MAILMH_NO_ERROR = 0, + MAILMH_ERROR_FOLDER, + MAILMH_ERROR_MEMORY, + MAILMH_ERROR_FILE, + MAILMH_ERROR_COULD_NOT_ALLOC_MSG, + MAILMH_ERROR_RENAME, + MAILMH_ERROR_MSG_NOT_FOUND, +}; + +struct mailmh { + struct mailmh_folder * mh_main; +}; + +struct mailmh_msg_info { + unsigned int msg_array_index; + uint32_t msg_index; + size_t msg_size; + time_t msg_mtime; +}; + +struct mailmh_folder { + char * fl_filename; + unsigned int fl_array_index; + + char * fl_name; + time_t fl_mtime; + struct mailmh_folder * fl_parent; + uint32_t fl_max_index; + + carray * fl_msgs_tab; +#if 0 + cinthash_t * fl_msgs_hash; +#endif + chash * fl_msgs_hash; + + carray * fl_subfolders_tab; + chash * fl_subfolders_hash; +}; + +struct mailmh * mailmh_new(const char * foldername); +void mailmh_free(struct mailmh * f); + +struct mailmh_msg_info * +mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime); +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info); + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name); +void mailmh_folder_free(struct mailmh_folder * folder); + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name); + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename); + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder); + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name); + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t index, char ** result); + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t index, int flags, int * result); + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t index, size_t * result); + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size); + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd); + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t index); + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t index); + +int mailmh_folder_update(struct mailmh_folder * folder); + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime.h b/kmicromail/libetpan/include/libetpan/mailmime.h new file mode 100644 index 0000000..c834967 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime_content.h b/kmicromail/libetpan/include/libetpan/mailmime_content.h new file mode 100644 index 0000000..df4b232 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_content.h @@ -0,0 +1,89 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime_decode.h b/kmicromail/libetpan/include/libetpan/mailmime_decode.h new file mode 100644 index 0000000..034db6f --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_decode.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime_disposition.h b/kmicromail/libetpan/include/libetpan/mailmime_disposition.h new file mode 100644 index 0000000..e3bba15 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_disposition.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime_types.h b/kmicromail/libetpan/include/libetpan/mailmime_types.h new file mode 100644 index 0000000..3bb3b10 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_types.h @@ -0,0 +1,440 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +void mailmime_attribute_free(char * attribute); + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + +void mailmime_description_free(char * description); + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +void mailmime_extension_token_free(char * extension); + +void mailmime_id_free(char * id); + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +void mailmime_subtype_free(char * subtype); + +void mailmime_token_free(char * token); + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +void mailmime_charset_free(char * charset); + +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +void mailmime_filename_parm_free(char * filename); + +void mailmime_creation_date_parm_free(char * date); + +void mailmime_modification_date_parm_free(char * date); + +void mailmime_read_date_parm_free(char * date); + +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +struct mailmime_section * mailmime_section_new(clist * list); + +void mailmime_section_free(struct mailmime_section * section); + + +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/include/libetpan/mailmime_types_helper.h b/kmicromail/libetpan/include/libetpan/mailmime_types_helper.h new file mode 100644 index 0000000..608acca --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_types_helper.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_content * mailmime_get_content_message(void); +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +struct mailmime * mailmime_multiple_new(const char * type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailmime_write.h b/kmicromail/libetpan/include/libetpan/mailmime_write.h new file mode 100644 index 0000000..96f8777 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailmime_write.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailpop3.h b/kmicromail/libetpan/include/libetpan/mailpop3.h new file mode 100644 index 0000000..b8552ab --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailpop3.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_H + +#define MAILPOP3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include + +#define POP3_STRING_SIZE 513 + +mailpop3 * mailpop3_new(size_t pop3_progr_rate, + progress_function * pop3_progr_fun); + +void mailpop3_free(mailpop3 * f); + +int mailpop3_connect(mailpop3 * f, mailstream * s); + +int mailpop3_quit(mailpop3 * f); + + +int mailpop3_apop(mailpop3 * f, const char * user, const char * password); + +int mailpop3_user(mailpop3 * f, const char * user); + +int mailpop3_pass(mailpop3 * f, const char * password); + +void mailpop3_list(mailpop3 * f, carray ** result); + +int mailpop3_retr(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len); + +int mailpop3_top(mailpop3 * f, uint32_t index, uint32_t count, + char ** result, size_t * result_len); + +int mailpop3_dele(mailpop3 * f, uint32_t index); + +int mailpop3_noop(mailpop3 * f); + +int mailpop3_rset(mailpop3 * f); + +void mailpop3_top_free(char * str); + +void mailpop3_retr_free(char * str); + +int mailpop3_get_msg_info(mailpop3 * f, uint32_t index, + struct mailpop3_msg_info ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result); + +void mailpop3_capa_resp_free(clist * capa_list); + +int mailpop3_stls(mailpop3 * f); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailpop3_helper.h b/kmicromail/libetpan/include/libetpan/mailpop3_helper.h new file mode 100644 index 0000000..7337ad8 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailpop3_helper.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_HELPER_H + +#define MAILPOP3_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3.h" + +int mailpop3_login_apop(mailpop3 * f, + char * user, + char * password); + +int mailpop3_login(mailpop3 * f, + char * user, + char * password); + +int mailpop3_header(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len); + +void mailpop3_header_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/include/libetpan/mailpop3_socket.h b/kmicromail/libetpan/include/libetpan/mailpop3_socket.h new file mode 100644 index 0000000..06f16f5 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailpop3_socket.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_SOCKET_H + +#define MAILPOP3_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailpop3_ssl.h b/kmicromail/libetpan/include/libetpan/mailpop3_ssl.h new file mode 100644 index 0000000..926001c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailpop3_ssl.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_SSL_H + +#define MAILPOP3_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailpop3_types.h b/kmicromail/libetpan/include/libetpan/mailpop3_types.h new file mode 100644 index 0000000..20500f6 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailpop3_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_TYPES_H + +#define MAILPOP3_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include + +enum { + MAILPOP3_NO_ERROR = 0, + MAILPOP3_ERROR_BAD_STATE, + MAILPOP3_ERROR_UNAUTHORIZED, + MAILPOP3_ERROR_STREAM, + MAILPOP3_ERROR_DENIED, + MAILPOP3_ERROR_BAD_USER, + MAILPOP3_ERROR_BAD_PASSWORD, + MAILPOP3_ERROR_CANT_LIST, + MAILPOP3_ERROR_NO_SUCH_MESSAGE, + MAILPOP3_ERROR_MEMORY, + MAILPOP3_ERROR_CONNECTION_REFUSED, + MAILPOP3_ERROR_APOP_NOT_SUPPORTED, + MAILPOP3_ERROR_CAPA_NOT_SUPPORTED, + MAILPOP3_ERROR_STLS_NOT_SUPPORTED, +}; + +struct mailpop3 +{ + char * pop3_response; /* response message */ + char * pop3_timestamp; /* connection timestamp */ + + /* internals */ + mailstream * pop3_stream; + size_t pop3_progr_rate; + progress_function * pop3_progr_fun; + + MMAPString * pop3_stream_buffer; /* buffer for lines reading */ + MMAPString * pop3_response_buffer; /* buffer for responses */ + + carray * pop3_msg_tab; /* list of pop3_msg_info structures */ + int pop3_state; /* state */ + + unsigned int pop3_deleted_count; +}; + +typedef struct mailpop3 mailpop3; + +struct mailpop3_msg_info +{ + unsigned int msg_index; + uint32_t msg_size; + char * msg_uidl; + int msg_deleted; +}; + + +struct mailpop3_capa { + char * cap_name; + clist * cap_param; /* (char *) */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailsmtp.h b/kmicromail/libetpan/include/libetpan/mailsmtp.h new file mode 100644 index 0000000..548a5b7 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailsmtp.h @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_H + +#define MAILSMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun); +void mailsmtp_free(mailsmtp * session); + +int mailsmtp_connect(mailsmtp * session, mailstream * s); +int mailsmtp_quit(mailsmtp * session); + +/** + * Tries AUTH with detected method - "better" method first: + * CRAM-MD5 -> PLAIN -> LOGIN + */ +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass); + +/** + * tries to autenticate with the server using given auth-type + * returns MAILSMTP_NO_ERROR on success + */ +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type); + +int mailsmtp_helo(mailsmtp * session); +int mailsmtp_mail(mailsmtp * session, const char * from); +int mailsmtp_rcpt(mailsmtp * session, const char * to); +int mailsmtp_data(mailsmtp * session); +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size); +int mailesmtp_ehlo(mailsmtp * session); +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid); +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt); +int mailesmtp_starttls(mailsmtp * session); + +const char * mailsmtp_strerror(int errnum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailsmtp_helper.h b/kmicromail/libetpan/include/libetpan/mailsmtp_helper.h new file mode 100644 index 0000000..6bbe3c9 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailsmtp_helper.h @@ -0,0 +1,74 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_HELPER_H + +#define MAILSMTP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailsmtp_types.h" +#include "clist.h" + +int mailsmtp_init(mailsmtp * session); + +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size); + +clist * esmtp_address_list_new(); +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt); +void esmtp_address_list_free(clist * l); + +clist * smtp_address_list_new(); +int smtp_address_list_add(clist * list, char * address); +void smtp_address_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailsmtp_socket.h b/kmicromail/libetpan/include/libetpan/mailsmtp_socket.h new file mode 100644 index 0000000..6691d9e --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailsmtp_socket.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_SOCKET_H + +#define MAILSMTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port); +int mailsmtp_socket_starttls(mailsmtp * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailsmtp_ssl.h b/kmicromail/libetpan/include/libetpan/mailsmtp_ssl.h new file mode 100644 index 0000000..9de9732 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailsmtp_ssl.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_SSL_H + +#define MAILSMTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailsmtp_types.h b/kmicromail/libetpan/include/libetpan/mailsmtp_types.h new file mode 100644 index 0000000..b63d5ea --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailsmtp_types.h @@ -0,0 +1,126 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_TYPES_H + +#define MAILSMTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" +#include "mmapstring.h" + +enum { + MAILSMTP_NO_ERROR = 0, + MAILSMTP_ERROR_UNEXPECTED_CODE, + MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE, + MAILSMTP_ERROR_STREAM, + MAILSMTP_ERROR_HOSTNAME, + MAILSMTP_ERROR_NOT_IMPLEMENTED, + MAILSMTP_ERROR_ACTION_NOT_TAKEN, + MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION, + MAILSMTP_ERROR_IN_PROCESSING, + MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE, + MAILSMTP_ERROR_MAILBOX_UNAVAILABLE, + MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED, + MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND, + MAILSMTP_ERROR_USER_NOT_LOCAL, + MAILSMTP_ERROR_TRANSACTION_FAILED, + MAILSMTP_ERROR_MEMORY, + MAILSMTP_ERROR_AUTH_NOT_SUPPORTED, + MAILSMTP_ERROR_AUTH_LOGIN, + MAILSMTP_ERROR_AUTH_REQUIRED, + MAILSMTP_ERROR_AUTH_TOO_WEAK, + MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED, + MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE, + MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED, + MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE, + MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED, + MAILSMTP_ERROR_CONNECTION_REFUSED +}; + +enum { + MAILSMTP_AUTH_NOT_CHECKED = 0, + MAILSMTP_AUTH_CHECKED = 1, + MAILSMTP_AUTH_CRAM_MD5 = 2, + MAILSMTP_AUTH_PLAIN = 4, + MAILSMTP_AUTH_LOGIN = 8 +}; + +enum { + MAILSMTP_ESMTP = 1, + MAILSMTP_ESMTP_EXPN = 2, + MAILSMTP_ESMTP_8BITMIME = 4, + MAILSMTP_ESMTP_SIZE = 8, + MAILSMTP_ESMTP_ETRN = 16, + MAILSMTP_ESMTP_STARTTLS = 32, + MAILSMTP_ESMTP_DSN = 64, +}; + +struct mailsmtp { + mailstream * stream; + + size_t progr_rate; + progress_function * progr_fun; + + char * response; + + MMAPString * line_buffer; + MMAPString * response_buffer; + + int esmtp; // contains flags MAILSMTP_ESMTP_* + int auth; // contains flags MAILSMTP_AUTH_* +}; + +typedef struct mailsmtp mailsmtp; + +#define MAILSMTP_DSN_NOTIFY_SUCCESS 1 +#define MAILSMTP_DSN_NOTIFY_FAILURE 2 +#define MAILSMTP_DSN_NOTIFY_DELAY 4 +#define MAILSMTP_DSN_NOTIFY_NEVER 8 + +struct esmtp_address { + char * address; + int notify; + char * orcpt; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstorage.h b/kmicromail/libetpan/include/libetpan/mailstorage.h new file mode 100644 index 0000000..d56aef1 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstorage.h @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_STORAGE_H + +#define MAIL_STORAGE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* storage */ + +/* + mailstorage_new + + This function creates an empty storage. This storage have to be initialized. + The "driver" and "data" fields should be initialized. + + @param id is the name of the storage. It can be NULL. + The given parameter is no more needed when the creation is finished. + The given string is duplicated. + + @return The mail storage is returned. +*/ + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + +/* + session will be initialized on success. +*/ + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + + +/* folder */ + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child); + +int mailfolder_detach_parent(struct mailfolder * folder); + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/kmicromail/libetpan/include/libetpan/mailstorage_types.h b/kmicromail/libetpan/include/libetpan/mailstorage_types.h new file mode 100644 index 0000000..5e08f80 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstorage_types.h @@ -0,0 +1,203 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTORAGE_TYPES_H + +#define MAILSTORAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailstorage; + +typedef struct mailstorage_driver mailstorage_driver; + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + mailstorage_driver is the driver structure for mail storages + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - uninitialize() frees the data created with mailstorage constructor. +*/ + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + +/* + mailstorage is the data structure for a storage + + - id is the name of the storage, it can be NULL. + + - data is the data specific to the driver. + This is the internal state of the storage. + + - session is the session related to the storage. + + - driver is the driver for the storage. + + - shared_folders is the list of folders returned by the storage. +*/ + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + +/* + mailfolder is the data structure for a mailbox + + - pathname is the path of the mailbox on the storage + + - virtual_name is the folder identifier, it can be a path, + a name or NULL. + + - storage is the storage to which the folder belongs to. + + - session is the session related to the folder. It can be + different of the session of the storage. + + - shared_session is != 0 if the session is the same as the + session of the storage. + + - pos is the position of the folder in the "shared_folders" field + of the storage. + + folders can be chained into a tree. + + - parent is the parent of the folder. + + - sibling_index is the index of the folder in the list of children + of the parent. + + - children is the folder. +*/ + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + +/* + this is the type of socket connection +*/ + +enum { + CONNECTION_TYPE_PLAIN, /* when the connection is plain text */ + CONNECTION_TYPE_STARTTLS, /* when the connection is first plain, + then, we want to switch to + TLS (secure connection) */ + CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain, + then, we will try to switch to TLS */ + CONNECTION_TYPE_TLS, /* the connection is over TLS */ + CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */ + CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell + command and STARTTLS will be used */ + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over + a shell command and STARTTLS will + be tried */ + CONNECTION_TYPE_COMMAND_TLS, /* the connection is over a shell + command in TLS */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstream.h b/kmicromail/libetpan/include/libetpan/mailstream.h new file mode 100644 index 0000000..a4e35cd --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_H + +#define MAILSTREAM_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count); +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); +int mailstream_close(mailstream * s); +int mailstream_flush(mailstream * s); +ssize_t mailstream_feed_read_buffer(mailstream * s); +mailstream_low * mailstream_get_low(mailstream * s); +void mailstream_set_low(mailstream * s, mailstream_low * low); + +#ifdef LIBETPAN_MAILSTREAM_DEBUG +extern int mailstream_debug; +#endif + +#define LIBETPAN_MAILSTREAM_NETWORK_DELAY +extern struct timeval mailstream_network_delay; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/include/libetpan/mailstream_helper.h b/kmicromail/libetpan/include/libetpan/mailstream_helper.h new file mode 100644 index 0000000..d030b1d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream_helper.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_HELPER_H + +#define MAILSTREAM_HELPER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_is_end_multiline(const char * line); + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstream_low.h b/kmicromail/libetpan/include/libetpan/mailstream_low.h new file mode 100644 index 0000000..fb8914c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream_low.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_LOW_H + +#define MAILSTREAM_LOW_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count); +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); +int mailstream_low_close(mailstream_low * s); +int mailstream_low_get_fd(mailstream_low * s); +void mailstream_low_free(mailstream_low * s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstream_socket.h b/kmicromail/libetpan/include/libetpan/mailstream_socket.h new file mode 100644 index 0000000..6a26e33 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream_socket.h @@ -0,0 +1,61 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_SOCKET_H + +#define MAILSTREAM_SOCKET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +extern mailstream_low_driver * mailstream_socket_driver; + +mailstream_low * mailstream_low_socket_open(int fd); +mailstream * mailstream_socket_open(int fd); + +struct mailstream_socket_data { + int fd; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstream_ssl.h b/kmicromail/libetpan/include/libetpan/mailstream_ssl.h new file mode 100644 index 0000000..a37b3d4 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream_ssl.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_SSL_H + +#define MAILSTREAM_SSL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +#ifdef USE_SSL +extern mailstream_low_driver * mailstream_ssl_driver; +#endif + +mailstream_low * mailstream_low_ssl_open(int fd); +mailstream * mailstream_ssl_open(int fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailstream_types.h b/kmicromail/libetpan/include/libetpan/mailstream_types.h new file mode 100644 index 0000000..2165149 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailstream_types.h @@ -0,0 +1,87 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_TYPES_H + +#define MAILSTREAM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBETPAN_MAILSTREAM_DEBUG + +struct _mailstream; + +typedef struct _mailstream mailstream; + +struct _mailstream_low; + +typedef struct _mailstream_low mailstream_low; + +struct _mailstream { + size_t buffer_max_size; + + char * write_buffer; + size_t write_buffer_len; + + char * read_buffer; + size_t read_buffer_len; + + mailstream_low * low; +}; + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + +typedef void progress_function(size_t current, size_t maximum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailthread.h b/kmicromail/libetpan/include/libetpan/mailthread.h new file mode 100644 index 0000000..e4e33ff --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailthread.h @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILTHREAD_H + +#define MAILTHREAD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_build_thread constructs a tree with the message using the + given style. + + @param type is the type of threading to apply, the value can be + MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT or + MAIL_THREAD_ORDEREDSUBJECT. + + @param default_from is the default charset to use whenever the + subject is not tagged with a charset. "US-ASCII" can be used + if you don't know what to use. + + @param env_list is the message list (with header fields fetched) + to use to build the message tree. + + @param result * result) will contain the resulting message tree. + + @param if comp_func is NULL, no sorting algorithm is used. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)); + +/* + mail_thread_sort sort the messages in the message tree, using the + given sort function. + + @param tree is the message tree to sort. + + @param comp_func is the sort function to use (this is the same kind of + functions than those used for qsort()). mailthread_tree_timecomp can be + used for default sort. + + @param sort_sub if this value is 0, only the children of the root message + are sorted. +*/ + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub); + +/* + mailthread_tree_timecomp is the default sort function. + + The message are compared by date, then by message numbers. + The tree are given in (* ptree1) and (* ptree2). +*/ + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mailthread_types.h b/kmicromail/libetpan/include/libetpan/mailthread_types.h new file mode 100644 index 0000000..5ef7b46 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mailthread_types.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILTHREAD_TYPES_H + +#define MAILTHREAD_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + This is the type of tree construction to apply. +*/ + +enum { + MAIL_THREAD_REFERENCES, /* this is threading using + References fields only) */ + MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References + fields, then subject */ + MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxdriver.h b/kmicromail/libetpan/include/libetpan/mboxdriver.h new file mode 100644 index 0000000..c598026 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxdriver_cached.h b/kmicromail/libetpan/include/libetpan/mboxdriver_cached.h new file mode 100644 index 0000000..b0d8dbf --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxdriver_cached.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxdriver_cached_message.h b/kmicromail/libetpan/include/libetpan/mboxdriver_cached_message.h new file mode 100644 index 0000000..a6673b3 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxdriver_message.h b/kmicromail/libetpan/include/libetpan/mboxdriver_message.h new file mode 100644 index 0000000..cdabd23 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxdriver_types.h b/kmicromail/libetpan/include/libetpan/mboxdriver_types.h new file mode 100644 index 0000000..be31ea3 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxdriver_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID, +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mboxstorage.h b/kmicromail/libetpan/include/libetpan/mboxstorage.h new file mode 100644 index 0000000..e5e83ce --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mboxstorage.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int mbox_mailstorage_init(struct mailstorage * storage, + char * mb_pathname, int mb_cached, + char * mb_cache_directory, char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhdriver.h b/kmicromail/libetpan/include/libetpan/mhdriver.h new file mode 100644 index 0000000..a82b9c1 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_H + +#define MHDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhdriver_cached.h b/kmicromail/libetpan/include/libetpan/mhdriver_cached.h new file mode 100644 index 0000000..4a07e7d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_CACHED_H + +#define MHDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhdriver_cached_message.h b/kmicromail/libetpan/include/libetpan/mhdriver_cached_message.h new file mode 100644 index 0000000..f3ed089 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_CACHED_MESSAGE_H + +#define MHDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhdriver_message.h b/kmicromail/libetpan/include/libetpan/mhdriver_message.h new file mode 100644 index 0000000..a7cb2cf --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_MESSAGE_H + +#define MHDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhdriver_types.h b/kmicromail/libetpan/include/libetpan/mhdriver_types.h new file mode 100644 index 0000000..09c6cc6 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhdriver_types.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHDRIVER_TYPES_H + +#define MHDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mh_session_state_data { + struct mailmh * mh_session; + + struct mailmh_folder * mh_cur_folder; + + clist * mh_subscribed_list; +}; + +enum { + MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct mh_cached_session_state_data { + mailsession * mh_ancestor; + char * mh_quoted_mb; + char mh_cache_directory[PATH_MAX]; + char mh_flags_directory[PATH_MAX]; + struct mail_flags_store * mh_flags_store; +}; + +/* mh storage */ + +/* + mh_mailstorage is the state data specific to the MH storage. + + - pathname is the root path of the MH storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mh_mailstorage { + char * mh_pathname; + + int mh_cached; + char * mh_cache_directory; + char * mh_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mhstorage.h b/kmicromail/libetpan/include/libetpan/mhstorage.h new file mode 100644 index 0000000..245bc81 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mhstorage.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MHSTORAGE_H + +#define MHSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mh_mailstorage_init is the constructor for a MH storage + + @param pathname is the filename the root path of the MH storage. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache. + + @param flags_directory is the location of the flags. +*/ + +int mh_mailstorage_init(struct mailstorage * storage, + char * mh_pathname, int mh_cached, + char * mh_cache_directory, char * mh_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mime_message_driver.h b/kmicromail/libetpan/include/libetpan/mime_message_driver.h new file mode 100644 index 0000000..ffcdd5c --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mime_message_driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MIME_MESSAGE_DRIVER_H + +#define MIME_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_MIME_MESSAGE + +extern mailmessage_driver * mime_message_driver; + +mailmessage * mime_message_init(struct mailmime * mime); + +void mime_message_detach_mime(mailmessage * msg); + +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir); + +#endif diff --git a/kmicromail/libetpan/include/libetpan/mmapstring.h b/kmicromail/libetpan/include/libetpan/mmapstring.h new file mode 100644 index 0000000..6d7227d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/mmapstring.h @@ -0,0 +1,136 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef __MMAP_STRING_H__ + +#define __MMAP_STRING_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +#define TMPDIR "/tmp" +*/ + +typedef struct _MMAPString MMAPString; + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; + /* + char * old_non_mmapped_str; + */ +}; + +/* configure location of mmaped files */ + +void mmap_string_set_tmpdir(char * directory); + +/* Strings + */ + +MMAPString * mmap_string_new (const char * init); + +MMAPString * mmap_string_new_len (const char * init, + size_t len); + +MMAPString * mmap_string_sized_new (size_t dfl_size); + +void mmap_string_free (MMAPString * string); + +MMAPString * mmap_string_assign (MMAPString * string, + const char * rval); + +MMAPString * mmap_string_truncate (MMAPString *string, + size_t len); + +MMAPString * mmap_string_set_size (MMAPString * string, + size_t len); + +MMAPString * mmap_string_insert_len (MMAPString * string, + size_t pos, + const char * val, + size_t len); + +MMAPString * mmap_string_append (MMAPString * string, + const char * val); + +MMAPString * mmap_string_append_len (MMAPString * string, + const char * val, + size_t len); + +MMAPString * mmap_string_append_c (MMAPString * string, + char c); + +MMAPString * mmap_string_prepend (MMAPString * string, + const char * val); + +MMAPString * mmap_string_prepend_c (MMAPString * string, + char c); + +MMAPString * mmap_string_prepend_len (MMAPString * string, + const char * val, + size_t len); + +MMAPString * mmap_string_insert (MMAPString * string, + size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c (MMAPString *string, + size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, + size_t pos, + size_t len); + +void mmap_string_set_ceil(size_t ceil); + +int mmap_string_ref(MMAPString * string); +int mmap_string_unref(char * str); + +#ifdef __cplusplus +} +#endif + + +#endif /* __MMAP_STRING_H__ */ diff --git a/kmicromail/libetpan/include/libetpan/newsnntp.h b/kmicromail/libetpan/include/libetpan/newsnntp.h new file mode 100644 index 0000000..13360d0 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/newsnntp.h @@ -0,0 +1,188 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_H + +#define NEWSNNTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +newsnntp * newsnntp_new(size_t nntp_progr_rate, + progress_function * nntp_progr_fun); +void newsnntp_free(newsnntp * f); + +int newsnntp_quit(newsnntp * f); +int newsnntp_connect(newsnntp * f, mailstream * s); + +int newsnntp_head(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_article(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_body(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); + +void newsnntp_head_free(char * str); +void newsnntp_article_free(char * str); +void newsnntp_body_free(char * str); + +int newsnntp_mode_reader(newsnntp * f); + +int newsnntp_date(newsnntp * f, struct tm * tm); + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments); + +int newsnntp_authinfo_username(newsnntp * f, const char * username); +int newsnntp_authinfo_password(newsnntp * f, const char * password); + +int newsnntp_post(newsnntp * f, const char * message, size_t size); + + + + + + +/******************* requests ******************************/ + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info); +void newsnntp_group_free(struct newsnntp_group_info * info); + +/* + elements are struct newsnntp_group_info * + */ + +int newsnntp_list(newsnntp * f, clist ** result); +void newsnntp_list_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result); +void newsnntp_list_overview_fmt_free(clist * l); + +/* + elements are struct newsnntp_group_info * +*/ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result); +void newsnntp_list_active_free(clist * l); + +/* + elements are struct newsnntp_group_time * +*/ + +int newsnntp_list_active_times(newsnntp * f, clist ** result); +void newsnntp_list_active_times_free(clist * l); + +/* + elements are struct newsnntp_distrib_value_meaning * +*/ + +int newsnntp_list_distribution(newsnntp * f, clist ** result); +void newsnntp_list_distribution_free(clist * l); + +/* + elements are struct newsnntp_distrib_default_value * +*/ + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result); +void newsnntp_list_distrib_pats_free(clist * l); + +/* + elements are struct newsnntp_group_description * +*/ + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result); +void newsnntp_list_newsgroups_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result); +void newsnntp_list_subscriptions_free(clist * l); + +/* + elements are uint32_t * +*/ + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result); +void newsnntp_listgroup_free(clist * l); + +/* + elements are struct newsnntp_xhdr_resp_item * +*/ + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result); +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void newsnntp_xhdr_free(clist * l); + +/* + elements are struct newsnntp_xover_resp_item * +*/ + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result); +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void newsnntp_xover_free(clist * l); +void xover_resp_item_free(struct newsnntp_xover_resp_item * n); +void newsnntp_xover_resp_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/newsnntp_socket.h b/kmicromail/libetpan/include/libetpan/newsnntp_socket.h new file mode 100644 index 0000000..fd44b44 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/newsnntp_socket.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_SOCKET_H + +#define NEWSNNTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/newsnntp_ssl.h b/kmicromail/libetpan/include/libetpan/newsnntp_ssl.h new file mode 100644 index 0000000..59eace5 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/newsnntp_ssl.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_SSL_H + +#define NEWSNNTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/newsnntp_types.h b/kmicromail/libetpan/include/libetpan/newsnntp_types.h new file mode 100644 index 0000000..0501088 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/newsnntp_types.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_TYPES_H + +#define NEWSNNTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include + +enum { + NEWSNNTP_NO_ERROR = 0, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, + NEWSNNTP_ERROR_STREAM, + NEWSNNTP_ERROR_UNEXPECTED, + NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, + NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, + NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, + NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, + NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, + NEWSNNTP_ERROR_INVALID_RESPONSE, + NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, + NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, + NEWSNNTP_ERROR_POSTING_FAILED, + NEWSNNTP_ERROR_PROGRAM_ERROR, + NEWSNNTP_ERROR_NO_PERMISSION, + NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, + NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, + NEWSNNTP_ERROR_CONNECTION_REFUSED, + NEWSNNTP_ERROR_MEMORY, + NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, + NEWSNNTP_ERROR_BAD_STATE, +}; + +struct newsnntp +{ + mailstream * nntp_stream; + + int nntp_readonly; + + uint32_t nntp_progr_rate; + progress_function * nntp_progr_fun; + + MMAPString * nntp_stream_buffer; + MMAPString * nntp_response_buffer; + + char * nntp_response; +}; + +typedef struct newsnntp newsnntp; + +struct newsnntp_group_info +{ + char * grp_name; + uint32_t grp_first; + uint32_t grp_last; + uint32_t grp_count; + char grp_type; +}; + +struct newsnntp_group_time { + char * grp_name; + uint32_t grp_date; + char * grp_email; +}; + +struct newsnntp_distrib_value_meaning { + char * dst_value; + char * dst_meaning; +}; + +struct newsnntp_distrib_default_value { + uint32_t dst_weight; + char * dst_group_pattern; + char * dst_value; +}; + +struct newsnntp_group_description { + char * grp_name; + char * grp_description; +}; + +struct newsnntp_xhdr_resp_item { + uint32_t hdr_article; + char * hdr_value; +}; + +struct newsnntp_xover_resp_item { + uint32_t ovr_article; + char * ovr_subject; + char * ovr_author; + char * ovr_date; + char * ovr_message_id; + char * ovr_references; + size_t ovr_size; + uint32_t ovr_line_count; + clist * ovr_others; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpdriver.h b/kmicromail/libetpan/include/libetpan/nntpdriver.h new file mode 100644 index 0000000..45bfeab --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_H + +#define NNTPDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpdriver_cached.h b/kmicromail/libetpan/include/libetpan/nntpdriver_cached.h new file mode 100644 index 0000000..feb576b --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_CACHED_H + +#define NNTPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpdriver_cached_message.h b/kmicromail/libetpan/include/libetpan/nntpdriver_cached_message.h new file mode 100644 index 0000000..c12f479 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include + +#ifndef NNTPDRIVER_CACHED_MESSAGE_H + +#define NNTPDRIVER_CACHED_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * nntp_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpdriver_message.h b/kmicromail/libetpan/include/libetpan/nntpdriver_message.h new file mode 100644 index 0000000..3b12a2d --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_MESSAGE_H + +#define NNTPDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailmessage_driver * nntp_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpdriver_types.h b/kmicromail/libetpan/include/libetpan/nntpdriver_types.h new file mode 100644 index 0000000..6492788 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpdriver_types.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPDRIVER_TYPES_H + +#define NNTPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* NNTP driver for session */ + +enum { + NNTPDRIVER_SET_MAX_ARTICLES = 1, +}; + +struct nntp_session_state_data { + newsnntp * nntp_session; + char * nntp_userid; + char * nntp_password; + + struct newsnntp_group_info * nntp_group_info; + char * nntp_group_name; + + clist * nntp_subscribed_list; + + uint32_t nntp_max_articles; + + int nntp_mode_reader; +}; + +/* cached NNTP driver for session */ + +enum { + /* the mapping of the parameters should be the same as for nntp */ + NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1, + /* cache specific */ + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct nntp_cached_session_state_data { + mailsession * nntp_ancestor; + char nntp_cache_directory[PATH_MAX]; + char nntp_flags_directory[PATH_MAX]; + struct mail_flags_store * nntp_flags_store; +}; + + +/* nntp storage */ + +/* + nntp_mailstorage is the state data specific to the IMAP4rev1 storage. + + - storage this is the storage to initialize. + + - servername this is the name of the NNTP server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache + + - flags_directory is the location of the flags +*/ + +struct nntp_mailstorage { + char * nntp_servername; + uint16_t nntp_port; + char * nntp_command; + int nntp_connection_type; + + int nntp_auth_type; + char * nntp_login; + char * nntp_password; + + int nntp_cached; + char * nntp_cache_directory; + char * nntp_flags_directory; +}; + +/* this is the type of NNTP authentication */ + +enum { + NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/nntpstorage.h b/kmicromail/libetpan/include/libetpan/nntpstorage.h new file mode 100644 index 0000000..794c717 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/nntpstorage.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NNTPSTORAGE_H + +#define NNTPSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + nntp_mailstorage_init is the constructor for a NNTP storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the NNTP server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int nntp_mailstorage_init(struct mailstorage * storage, + char * nntp_servername, uint16_t nntp_port, + char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + char * nntp_login, char * nntp_password, + int nntp_cached, char * nntp_cache_directory, + char * nntp_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3driver.h b/kmicromail/libetpan/include/libetpan/pop3driver.h new file mode 100644 index 0000000..2df94db --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_H + +#define POP3DRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * pop3_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3driver_cached.h b/kmicromail/libetpan/include/libetpan/pop3driver_cached.h new file mode 100644 index 0000000..953e699 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3driver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_CACHED_H + +#define POP3DRIVER_CACHED_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * pop3_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3driver_cached_message.h b/kmicromail/libetpan/include/libetpan/pop3driver_cached_message.h new file mode 100644 index 0000000..d03f8e5 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3driver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_CACHED_MESSAGE_H + +#define POP3DRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3driver_message.h b/kmicromail/libetpan/include/libetpan/pop3driver_message.h new file mode 100644 index 0000000..6281a39 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3driver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_MESSAGE_H + +#define POP3DRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3driver_types.h b/kmicromail/libetpan/include/libetpan/pop3driver_types.h new file mode 100644 index 0000000..73286d8 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3driver_types.h @@ -0,0 +1,153 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3DRIVER_TYPES_H + +#define POP3DRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* POP3 driver for session */ + +enum { + POP3DRIVER_SET_AUTH_TYPE = 1, +}; + +enum { + POP3DRIVER_AUTH_TYPE_PLAIN = 0, + POP3DRIVER_AUTH_TYPE_APOP, + POP3DRIVER_AUTH_TYPE_TRY_APOP, +}; + +struct pop3_session_state_data { + int pop3_auth_type; + mailpop3 * pop3_session; +}; + +/* cached POP3 driver for session */ + +enum { + /* the mapping of the parameters should be the same as for pop3 */ + POP3DRIVER_CACHED_SET_AUTH_TYPE = 1, + /* cache specific */ + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY, +}; + +struct pop3_cached_session_state_data { + mailsession * pop3_ancestor; + char pop3_cache_directory[PATH_MAX]; + char pop3_flags_directory[PATH_MAX]; + chash * pop3_flags_hash; + carray * pop3_flags_array; + struct mail_flags_store * pop3_flags_store; +}; + +/* pop3 storage */ + +/* + pop3_mailstorage is the state data specific to the POP3 storage. + + - servername this is the name of the POP3 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct pop3_mailstorage { + char * pop3_servername; + uint16_t pop3_port; + char * pop3_command; + int pop3_connection_type; + + int pop3_auth_type; + char * pop3_login; + char * pop3_password; + + int pop3_cached; + char * pop3_cache_directory; + char * pop3_flags_directory; +}; + +/* this is the type of POP3 authentication */ + +enum { + POP3_AUTH_TYPE_PLAIN, /* plain text authentication */ + POP3_AUTH_TYPE_APOP, /* APOP authentication */ + POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails, + try plain text */ + POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/include/libetpan/pop3storage.h b/kmicromail/libetpan/include/libetpan/pop3storage.h new file mode 100644 index 0000000..c2118b6 --- a/dev/null +++ b/kmicromail/libetpan/include/libetpan/pop3storage.h @@ -0,0 +1,95 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef POP3STORAGE_H + +#define POP3STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + pop3_mailstorage_init is the constructor for a POP3 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the POP3 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +int pop3_mailstorage_init(struct mailstorage * storage, + char * pop3_servername, uint16_t pop3_port, + char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + char * pop3_login, char * pop3_password, + int pop3_cached, char * pop3_cache_directory, + char * pop3_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/libetpan-config.h b/kmicromail/libetpan/libetpan-config.h new file mode 100644 index 0000000..20d1e62 --- a/dev/null +++ b/kmicromail/libetpan/libetpan-config.h @@ -0,0 +1,7 @@ +#ifndef LIBETPAN_CONFIG_H +#define LIBETPAN_CONFIG_H +#include +#include +#define MAIL_DIR_SEPARATOR '/' +#define MAIL_DIR_SEPARATOR_S "/" +#endif diff --git a/kmicromail/libetpan/libetpanE.pro b/kmicromail/libetpan/libetpanE.pro new file mode 100644 index 0000000..b7a9a16 --- a/dev/null +++ b/kmicromail/libetpan/libetpanE.pro @@ -0,0 +1,274 @@ +###################################################################### +# Automatically generated by qmake (1.07a) Thu Jul 1 00:54:03 2004 +###################################################################### + +TEMPLATE = lib +TARGET = kmicrolibetpan + +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +DESTDIR=$(QPEDIR)/lib + +DEPENDPATH += generic \ + imap \ + imf \ + maildir \ + mbox \ + mh \ + mime \ + nntp \ + pop3 \ + smtp \ + tests \ + tools \ + include/libetpan +INCLUDEPATH += . \ + generic \ + include \ + tools \ + imf \ + imap \ + mime \ + maildir \ + mbox \ + mh \ + nntp \ + pop3 \ + smtp \ + tests + +# Input +HEADERS += generic/data_message_driver.h \ + generic/generic_cache.h \ + generic/generic_cache_types.h \ + generic/imapdriver.h \ + generic/imapdriver_cached.h \ + generic/imapdriver_cached_message.h \ + generic/imapdriver_message.h \ + generic/imapdriver_tools.h \ + generic/imapdriver_types.h \ + generic/imapstorage.h \ + generic/imfcache.h \ + generic/libetpan.h \ + generic/libetpan_version.h \ + generic/maildirdriver.h \ + generic/maildirdriver_cached.h \ + generic/maildirdriver_cached_message.h \ + generic/maildirdriver_message.h \ + generic/maildirdriver_tools.h \ + generic/maildirdriver_types.h \ + generic/maildirstorage.h \ + generic/maildriver.h \ + generic/maildriver_errors.h \ + generic/maildriver_tools.h \ + generic/maildriver_types.h \ + generic/maildriver_types_helper.h \ + generic/mailfolder.h \ + generic/mailmessage.h \ + generic/mailmessage_tools.h \ + generic/mailmessage_types.h \ + generic/mailstorage.h \ + generic/mailstorage_tools.h \ + generic/mailstorage_types.h \ + generic/mailthread.h \ + generic/mailthread_types.h \ + generic/mboxdriver.h \ + generic/mboxdriver_cached.h \ + generic/mboxdriver_cached_message.h \ + generic/mboxdriver_message.h \ + generic/mboxdriver_tools.h \ + generic/mboxdriver_types.h \ + generic/mboxstorage.h \ + generic/mhdriver.h \ + generic/mhdriver_cached.h \ + generic/mhdriver_cached_message.h \ + generic/mhdriver_message.h \ + generic/mhdriver_tools.h \ + generic/mhdriver_types.h \ + generic/mhstorage.h \ + generic/mime_message_driver.h \ + generic/nntpdriver.h \ + generic/nntpdriver_cached.h \ + generic/nntpdriver_cached_message.h \ + generic/nntpdriver_message.h \ + generic/nntpdriver_tools.h \ + generic/nntpdriver_types.h \ + generic/nntpstorage.h \ + generic/pop3driver.h \ + generic/pop3driver_cached.h \ + generic/pop3driver_cached_message.h \ + generic/pop3driver_message.h \ + generic/pop3driver_tools.h \ + generic/pop3driver_types.h \ + generic/pop3storage.h \ + imap/mailimap.h \ + imap/mailimap_helper.h \ + imap/mailimap_keywords.h \ + imap/mailimap_parser.h \ + imap/mailimap_print.h \ + imap/mailimap_sender.h \ + imap/mailimap_socket.h \ + imap/mailimap_ssl.h \ + imap/mailimap_types.h \ + imap/mailimap_types_helper.h \ + imf/mailimf.h \ + imf/mailimf_types.h \ + imf/mailimf_types_helper.h \ + imf/mailimf_write.h \ + maildir/maildir.h \ + maildir/maildir_types.h \ + mbox/mailmbox.h \ + mbox/mailmbox_parse.h \ + mbox/mailmbox_types.h \ + mh/mailmh.h \ + mime/mailmime.h \ + mime/mailmime_content.h \ + mime/mailmime_decode.h \ + mime/mailmime_disposition.h \ + mime/mailmime_types.h \ + mime/mailmime_types_helper.h \ + mime/mailmime_write.h \ + nntp/newsnntp.h \ + nntp/newsnntp_socket.h \ + nntp/newsnntp_ssl.h \ + nntp/newsnntp_types.h \ + pop3/mailpop3.h \ + pop3/mailpop3_helper.h \ + pop3/mailpop3_socket.h \ + pop3/mailpop3_ssl.h \ + pop3/mailpop3_types.h \ + smtp/mailsmtp.h \ + smtp/mailsmtp_helper.h \ + smtp/mailsmtp_socket.h \ + smtp/mailsmtp_ssl.h \ + smtp/mailsmtp_types.h \ + tools/base64.h \ + tools/carray.h \ + tools/charconv.h \ + tools/chash.h \ + tools/cinthash.h \ + tools/clist.h \ + tools/connect.h \ + tools/hmac-md5.h \ + tools/mail.h \ + tools/mail_cache_db.h \ + tools/mail_cache_db_types.h \ + tools/maillock.h \ + tools/mailstream.h \ + tools/mailstream_helper.h \ + tools/mailstream_low.h \ + tools/mailstream_socket.h \ + tools/mailstream_ssl.h \ + tools/mailstream_types.h \ + tools/mapping.h \ + tools/md5.h \ + tools/md5global.h \ + tools/mmapstring.h \ + +SOURCES += generic/data_message_driver.c \ + generic/generic_cache.c \ + generic/imapdriver.c \ + generic/imapdriver_cached.c \ + generic/imapdriver_cached_message.c \ + generic/imapdriver_message.c \ + generic/imapdriver_tools.c \ + generic/imapstorage.c \ + generic/imfcache.c \ + generic/libetpan_version.c \ + generic/maildirdriver.c \ + generic/maildirdriver_cached.c \ + generic/maildirdriver_cached_message.c \ + generic/maildirdriver_message.c \ + generic/maildirdriver_tools.c \ + generic/maildirstorage.c \ + generic/maildriver.c \ + generic/maildriver_tools.c \ + generic/maildriver_types.c \ + generic/maildriver_types_helper.c \ + generic/mailfolder.c \ + generic/mailmessage.c \ + generic/mailmessage_tools.c \ + generic/mailmessage_types.c \ + generic/mailstorage.c \ + generic/mailstorage_tools.c \ + generic/mailthread.c \ + generic/mailthread_types.c \ + generic/mboxdriver.c \ + generic/mboxdriver_cached.c \ + generic/mboxdriver_cached_message.c \ + generic/mboxdriver_message.c \ + generic/mboxdriver_tools.c \ + generic/mboxstorage.c \ + generic/mhdriver.c \ + generic/mhdriver_cached.c \ + generic/mhdriver_cached_message.c \ + generic/mhdriver_message.c \ + generic/mhdriver_tools.c \ + generic/mhstorage.c \ + generic/mime_message_driver.c \ + generic/nntpdriver.c \ + generic/nntpdriver_cached.c \ + generic/nntpdriver_cached_message.c \ + generic/nntpdriver_message.c \ + generic/nntpdriver_tools.c \ + generic/nntpstorage.c \ + generic/pop3driver.c \ + generic/pop3driver_cached.c \ + generic/pop3driver_cached_message.c \ + generic/pop3driver_message.c \ + generic/pop3driver_tools.c \ + generic/pop3storage.c \ + imap/mailimap.c \ + imap/mailimap_helper.c \ + imap/mailimap_keywords.c \ + imap/mailimap_parser.c \ + imap/mailimap_print.c \ + imap/mailimap_sender.c \ + imap/mailimap_socket.c \ + imap/mailimap_ssl.c \ + imap/mailimap_types.c \ + imap/mailimap_types_helper.c \ + imf/mailimf.c \ + imf/mailimf_types.c \ + imf/mailimf_types_helper.c \ + imf/mailimf_write.c \ + maildir/maildir.c \ + mbox/mailmbox.c \ + mbox/mailmbox_parse.c \ + mbox/mailmbox_types.c \ + mh/mailmh.c \ + mime/mailmime.c \ + mime/mailmime_content.c \ + mime/mailmime_decode.c \ + mime/mailmime_disposition.c \ + mime/mailmime_types.c \ + mime/mailmime_types_helper.c \ + mime/mailmime_write.c \ + nntp/newsnntp.c \ + nntp/newsnntp_socket.c \ + nntp/newsnntp_ssl.c \ + pop3/mailpop3.c \ + pop3/mailpop3_helper.c \ + pop3/mailpop3_socket.c \ + pop3/mailpop3_ssl.c \ + smtp/mailsmtp.c \ + smtp/mailsmtp_helper.c \ + smtp/mailsmtp_socket.c \ + smtp/mailsmtp_ssl.c \ + tools/base64.c \ + tools/carray.c \ + tools/charconv.c \ + tools/chash.c \ + tools/cinthash.c \ + tools/clist.c \ + tools/connect.c \ + tools/mail_cache_db.c \ + tools/maillock.c \ + tools/mailstream.c \ + tools/mailstream_helper.c \ + tools/mailstream_low.c \ + tools/mailstream_socket.c \ + tools/mailstream_ssl.c \ + tools/mapping.c \ + tools/md5.c \ + tools/mmapstring.c diff --git a/kmicromail/libetpan/maildir/.libs/libmaildir.a b/kmicromail/libetpan/maildir/.libs/libmaildir.a new file mode 100644 index 0000000..9eaf93e --- a/dev/null +++ b/kmicromail/libetpan/maildir/.libs/libmaildir.a Binary files differ diff --git a/kmicromail/libetpan/maildir/maildir.c b/kmicromail/libetpan/maildir/maildir.c new file mode 100644 index 0000000..320ef81 --- a/dev/null +++ b/kmicromail/libetpan/maildir/maildir.c @@ -0,0 +1,710 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "maildir.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LIBETPAN_SYSTEM_BASENAME +#include +#endif + +/* + We suppose the maildir mailbox remains on one unique filesystem. +*/ + +struct maildir * maildir_new(const char * path) +{ + struct maildir * md; + + md = malloc(sizeof(* md)); + if (md == NULL) + goto err; + + md->mdir_counter = 0; + md->mdir_mtime_new = (time_t) -1; + md->mdir_mtime_cur = (time_t) -1; + + md->mdir_pid = getpid(); + gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); + strncpy(md->mdir_path, path, sizeof(md->mdir_path)); + md->mdir_path[PATH_MAX - 1] = '\0'; + + md->mdir_msg_list = carray_new(128); + if (md->mdir_msg_list == NULL) + goto free; + + md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + if (md->mdir_msg_hash == NULL) + goto free_msg_list; + + return md; + + free_msg_list: + carray_free(md->mdir_msg_list); + free: + free(md); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int msg_new); + +void maildir_free(struct maildir * md) +{ + maildir_flush(md, 0); + maildir_flush(md, 1); + chash_free(md->mdir_msg_hash); + carray_free(md->mdir_msg_list); + free(md); +} + +#define MAX_TRY_ALLOC 32 + +static char * maildir_get_new_message_filename(struct maildir * md, + char * tmpfile) +{ + char filename[PATH_MAX]; + char basename[PATH_MAX]; + int k; + time_t now; + + now = time(NULL); + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", + (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); + snprintf(filename, sizeof(filename), "%s/tmp/%s", + md->mdir_path, basename); + + if (link(tmpfile, filename) == 0) { + char * dup_filename; + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + return NULL; + } + + unlink(tmpfile); + md->mdir_counter ++; + + return dup_filename; + } + + md->mdir_counter ++; + k ++; + } + + return NULL; +} + + +static void msg_free(struct maildir_msg * msg) +{ + free(msg->msg_uid); + free(msg->msg_filename); + free(msg); +} + +/* + msg_new() + + filename is given without path +*/ + +static struct maildir_msg * msg_new(char * filename, int new_msg) +{ + struct maildir_msg * msg; + char * p; + int flags; + size_t uid_len; + char * begin_uid; + + /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + goto err; + + msg->msg_filename = strdup(filename); + if (msg->msg_filename == NULL) + goto free; + + begin_uid = filename; + + uid_len = strlen(begin_uid); + + flags = 0; + p = strstr(filename, ":2,"); + if (p != NULL) { + uid_len = p - begin_uid; + + p += 3; + + /* parse flags */ + while (* p != '\0') { + switch (* p) { + case 'S': + flags |= MAILDIR_FLAG_SEEN; + break; + case 'R': + flags |= MAILDIR_FLAG_REPLIED; + break; + case 'F': + flags |= MAILDIR_FLAG_FLAGGED; + break; + case 'T': + flags |= MAILDIR_FLAG_TRASHED; + break; + } + p ++; + } + } + + if (new_msg) + flags |= MAILDIR_FLAG_NEW; + + msg->msg_flags = flags; + + msg->msg_uid = malloc(uid_len + 1); + if (msg->msg_uid == NULL) + goto free_filename; + + strncpy(msg->msg_uid, begin_uid, uid_len); + msg->msg_uid[uid_len] = '\0'; + + return msg; + + free_filename: + free(msg->msg_filename); + free: + free(msg); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int msg_new) +{ + unsigned int i; + + i = 0; + while (i < carray_count(md->mdir_msg_list)) { + struct maildir_msg * msg; + int delete; + + msg = carray_get(md->mdir_msg_list, i); + + if (msg_new) { + delete = 0; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 1; + } + else { + delete = 1; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 0; + } + + if (delete) { + chashdatum key; + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + chash_delete(md->mdir_msg_hash, &key, NULL); + + carray_delete(md->mdir_msg_list, i); + msg_free(msg); + } + else { + i ++; + } + } +} + +static int add_message(struct maildir * md, + char * filename, int is_new) +{ + struct maildir_msg * msg; + chashdatum key; + chashdatum value; + unsigned int i; + int res; + int r; + + msg = msg_new(filename, is_new); + if (msg == NULL) { + res = MAILDIR_ERROR_MEMORY; + goto err; + } + + r = carray_add(md->mdir_msg_list, msg, &i); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto free_msg; + } + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + value.data = msg; + value.len = 0; + + r = chash_set(md->mdir_msg_hash, &key, &value, NULL); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto delete; + } + + return MAILDIR_NO_ERROR; + + delete: + carray_delete(md->mdir_msg_list, i); + free_msg: + msg_free(msg); + err: + return res; +} + +static int add_directory(struct maildir * md, char * path, int is_new) +{ + DIR * d; + struct dirent * entry; + int res; + int r; + char filename[PATH_MAX]; + + d = opendir(path); + if (d == NULL) { + res = MAILDIR_ERROR_DIRECTORY; + goto err; + } + + while ((entry = readdir(d)) != NULL) { + struct stat stat_info; + + snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); + r = stat(filename, &stat_info); + if (r < 0) + continue; + + if (S_ISDIR(stat_info.st_mode)) + continue; + + r = add_message(md, entry->d_name, is_new); + if (r != MAILDIR_NO_ERROR) { + /* ignore errors */ + } + } + + closedir(d); + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_update(struct maildir * md) +{ + struct stat stat_info; + char path_new[PATH_MAX]; + char path_cur[PATH_MAX]; + int r; + int res; + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); + + /* did new/ changed ? */ + + r = stat(path_new, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_new != stat_info.st_mtime) { + md->mdir_mtime_new = stat_info.st_mtime; + + maildir_flush(md, 1); + + /* messages in new */ + r = add_directory(md, path_new, 1); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + } + + /* did cur/ changed ? */ + + r = stat(path_cur, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_cur != stat_info.st_mtime) { + md->mdir_mtime_cur = stat_info.st_mtime; + + maildir_flush(md, 0); + + /* messages in cur */ + r = add_directory(md, path_cur, 0); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + } + + return MAILDIR_NO_ERROR; + + free: + maildir_flush(md, 0); + maildir_flush(md, 1); + md->mdir_mtime_cur = (time_t) -1; + md->mdir_mtime_new = (time_t) -1; + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +int maildir_message_add(struct maildir * md, + const char * message, size_t size) +{ + char path_new[PATH_MAX]; + char tmpname[PATH_MAX]; + int fd; + int r; + char * mapping; + char * delivery_tmp_name; + char * delivery_tmp_basename; + char delivery_new_name[PATH_MAX]; + char * delivery_new_basename; + int res; + struct stat stat_info; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* write to tmp/ with a classic temporary file */ + + snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", md->mdir_path); + fd = mkstemp(tmpname); + if (fd < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + r = ftruncate(fd, size); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapping == MAP_FAILED) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + memcpy(mapping, message, size); + + msync(mapping, size, MS_SYNC); + munmap(mapping, size); + + close(fd); + + /* write to tmp/ with maildir standard name */ + + delivery_tmp_name = maildir_get_new_message_filename(md, tmpname); + if (delivery_tmp_name == NULL) { + res = MAILDIR_ERROR_FILE; + goto unlink; + } + + /* write to new/ with maildir standard name */ + + strncpy(tmpname, delivery_tmp_name, sizeof(tmpname)); + tmpname[sizeof(tmpname) - 1] = '\0'; + + delivery_tmp_basename = libetpan_basename(tmpname); + + snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s", + md->mdir_path, delivery_tmp_basename); + + r = link(delivery_tmp_name, delivery_new_name); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + r = stat(path_new, &stat_info); + if (r < 0) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + md->mdir_mtime_new = stat_info.st_mtime; + + delivery_new_basename = libetpan_basename(delivery_new_name); + + r = add_message(md, delivery_new_basename, 1); + if (r != MAILDIR_NO_ERROR) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + unlink(delivery_tmp_name); + free(delivery_tmp_name); + + return MAILDIR_NO_ERROR; + + unlink_tmp: + unlink(delivery_tmp_name); + free(delivery_tmp_name); + goto err; + close: + close(fd); + unlink: + unlink(tmpname); + err: + return res; +} + +int maildir_message_add_file(struct maildir * md, int fd) +{ + char * message; + struct stat buf; + int r; + + if (fstat(fd, &buf) == -1) + return MAILDIR_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == MAP_FAILED) + return MAILDIR_ERROR_FILE; + + r = maildir_message_add(md, message, buf.st_size); + + munmap(message, buf.st_size); + + return r; +} + +char * maildir_message_get(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + char * dup_filename; + struct maildir_msg * msg; + char * dir; + int r; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return NULL; + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + dup_filename = strdup(filename); + if (dup_filename == NULL) + return NULL; + + return dup_filename; +} + +int maildir_message_remove(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + int res; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + r = unlink(filename); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + char new_filename[PATH_MAX]; + char flag_str[5]; + size_t i; + int res; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + if ((new_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + i = 0; + if ((new_flags & MAILDIR_FLAG_SEEN) != 0) { + flag_str[i] = 'S'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) { + flag_str[i] = 'R'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) { + flag_str[i] = 'F'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) { + flag_str[i] = 'T'; + i ++; + } + flag_str[i] = 0; + + if (flag_str[0] == '\0') + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_uid); + else + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s", + md->mdir_path, dir, msg->msg_uid, flag_str); + + if (strcmp(filename, new_filename) == 0) + return MAILDIR_NO_ERROR; + + r = link(filename, new_filename); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + unlink(filename); + + return MAILDIR_NO_ERROR; + + err: + return res; +} diff --git a/kmicromail/libetpan/maildir/maildir.h b/kmicromail/libetpan/maildir/maildir.h new file mode 100644 index 0000000..b782484 --- a/dev/null +++ b/kmicromail/libetpan/maildir/maildir.h @@ -0,0 +1,60 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIR_H + +#define MAILDIR_H + +#include + +struct maildir * maildir_new(const char * path); + +void maildir_free(struct maildir * md); + +int maildir_update(struct maildir * md); + +int maildir_message_add(struct maildir * md, + const char * message, size_t size); + +int maildir_message_add_file(struct maildir * md, int fd); + +char * maildir_message_get(struct maildir * md, const char * uid); + +int maildir_message_remove(struct maildir * md, const char * uid); + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags); + +#endif diff --git a/kmicromail/libetpan/maildir/maildir_types.h b/kmicromail/libetpan/maildir/maildir_types.h new file mode 100644 index 0000000..c7e368e --- a/dev/null +++ b/kmicromail/libetpan/maildir/maildir_types.h @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILDIR_TYPES_H + +#define MAILDIR_TYPES_H + +#include +#include +#include +#include +#include + +#include + +#define LIBETPAN_MAILDIR + +enum { + MAILDIR_NO_ERROR = 0, + MAILDIR_ERROR_CREATE, + MAILDIR_ERROR_DIRECTORY, + MAILDIR_ERROR_MEMORY, + MAILDIR_ERROR_FILE, + MAILDIR_ERROR_NOT_FOUND, +}; + +#define MAILDIR_FLAG_NEW (1 << 0) +#define MAILDIR_FLAG_SEEN (1 << 1) +#define MAILDIR_FLAG_REPLIED (1 << 2) +#define MAILDIR_FLAG_FLAGGED (1 << 3) +#define MAILDIR_FLAG_TRASHED (1 << 4) + +struct maildir_msg { + char * msg_uid; + char * msg_filename; + int msg_flags; +}; + +/* + work around for missing #define HOST_NAME_MAX in Linux +*/ + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +struct maildir { + pid_t mdir_pid; + char mdir_hostname[HOST_NAME_MAX]; + char mdir_path[PATH_MAX]; + uint32_t mdir_counter; + time_t mdir_mtime_new; + time_t mdir_mtime_cur; + carray * mdir_msg_list; + chash * mdir_msg_hash; +}; + +#endif diff --git a/kmicromail/libetpan/mbox/.libs/libmailmbox.a b/kmicromail/libetpan/mbox/.libs/libmailmbox.a new file mode 100644 index 0000000..7b92e2d --- a/dev/null +++ b/kmicromail/libetpan/mbox/.libs/libmailmbox.a Binary files differ diff --git a/kmicromail/libetpan/mbox/TODO b/kmicromail/libetpan/mbox/TODO new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/kmicromail/libetpan/mbox/TODO diff --git a/kmicromail/libetpan/mbox/mailmbox.c b/kmicromail/libetpan/mbox/mailmbox.c new file mode 100644 index 0000000..280c313 --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox.c @@ -0,0 +1,1424 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmbox.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "libetpan-config.h" + +#include "mmapstring.h" +#include "mailmbox_parse.h" +#include "maillock.h" + +/* + http://www.qmail.org/qmail-manual-html/man5/mbox.html + RFC 2076 +*/ + +#define TMPDIR "/tmp" + +/* mbox is a file with a corresponding filename */ + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +int mailmbox_write_lock(struct mailmbox_folder * folder) +{ + int r; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + r = maillock_write_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_write_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_write_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_lock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + + +/* + map the file into memory. + the file must be locked. +*/ + +int mailmbox_map(struct mailmbox_folder * folder) +{ + char * str; + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + if (folder->mb_read_only) + str = (char *) mmap(0, buf.st_size, PROT_READ, + MAP_PRIVATE, folder->mb_fd, 0); + else + str = (char *) mmap(0, buf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, folder->mb_fd, 0); + if (str == MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + folder->mb_mapping = str; + folder->mb_mapping_size = buf.st_size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +/* + unmap the file +*/ + +void mailmbox_unmap(struct mailmbox_folder * folder) +{ + munmap(folder->mb_mapping, folder->mb_mapping_size); + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; +} + +void mailmbox_sync(struct mailmbox_folder * folder) +{ + msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC); +} + +void mailmbox_timestamp(struct mailmbox_folder * folder) +{ + int r; + struct stat buf; + + r = stat(folder->mb_filename, &buf); + if (r < 0) + folder->mb_mtime = (time_t) -1; + else + folder->mb_mtime = buf.st_mtime; +} + +/* + open the file +*/ + +int mailmbox_open(struct mailmbox_folder * folder) +{ + int fd; + int read_only; + + if (!folder->mb_read_only) { + read_only = FALSE; + fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + } + + if (folder->mb_read_only || (fd < 0)) { + read_only = TRUE; + fd = open(folder->mb_filename, O_RDONLY); + if (fd < 0) + return MAILMBOX_ERROR_FILE_NOT_FOUND; + } + + folder->mb_fd = fd; + folder->mb_read_only = read_only; + + return MAILMBOX_NO_ERROR; +} + +/* + close the file +*/ + +void mailmbox_close(struct mailmbox_folder * folder) +{ + close(folder->mb_fd); + folder->mb_fd = -1; +} + + +static int mailmbox_validate_lock(struct mailmbox_folder * folder, + int (* custom_lock)(struct mailmbox_folder *), + int (* custom_unlock)(struct mailmbox_folder *)) +{ + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + buf.st_mtime = (time_t) -1; + } + + if ((buf.st_mtime != folder->mb_mtime) || + ((size_t) buf.st_size != folder->mb_mapping_size)) { + int r; + + mailmbox_unmap(folder); + mailmbox_close(folder); + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + folder->mb_mtime = buf.st_mtime; + + return MAILMBOX_NO_ERROR; + } + else { + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + return MAILMBOX_NO_ERROR; + + err_unlock: + custom_unlock(folder); + err: + return res; +} + + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_write_lock, + mailmbox_write_unlock); +} + + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_read_lock, + mailmbox_read_unlock); +} + + +/* ********************************************************************** */ +/* append messages */ + +#define MAX_FROM_LINE_SIZE 256 + +static inline size_t get_line(const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length > 0) { + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + line ++; + length --; + count ++; + } + } + + * pnext_line = line; + * pcount = count; + + return count; +} + +/* + TODO : should strip \r\n if any + see also in write_fixed_line +*/ + +static inline size_t get_fixed_line_size(const char * line, size_t length, + const char ** pnext_line, size_t * pcount, + size_t * pfixed_count) +{ + size_t count; + const char * next_line; + size_t fixed_count; + + if (!get_line(line, length, &next_line, &count)) + return 0; + + fixed_count = count; + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) + fixed_count ++; + } + } + + * pnext_line = next_line; + * pcount = count; + * pfixed_count = fixed_count; + + return count; +} + +static size_t get_fixed_message_size(const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t fixed_size; + size_t cur_token; + size_t left; + const char * next; + const char * cur; + int end; + int r; + uint32_t tmp_uid; + + cur_token = 0; + + fixed_size = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) + fixed_size += cur_token - begin; + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + + fixed_size += strlen(UID_HEADER " \r\n"); + + tmp_uid = uid; + while (tmp_uid >= 10) { + tmp_uid /= 10; + fixed_size ++; + } + fixed_size ++; + } + + /* body */ + + left = size - cur_token; + next = message + cur_token; + while (left > 0) { + size_t count; + size_t fixed_count; + + cur = next; + + if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count)) + break; + + fixed_size += fixed_count; + left -= count; + } + + return fixed_size; +} + +static inline char * write_fixed_line(char * str, + const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + const char * next_line; + + if (!get_line(line, length, &next_line, &count)) + return str; + + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) { + * str = '>'; + str ++; + } + } + } + + memcpy(str, line, count); + + * pnext_line = next_line; + * pcount = count; + str += count; + + return str; +} + +static char * write_fixed_message(char * str, + const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t fixed_size; + size_t cur_token; + size_t left; + int end; + int r; + const char * cur_src; + size_t numlen; + + cur_token = 0; + + fixed_size = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) { + memcpy(str, message + begin, cur_token - begin); + str += cur_token - begin; + } + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + + memcpy(str, UID_HEADER " ", strlen(UID_HEADER " ")); + str += strlen(UID_HEADER " "); + numlen = snprintf(str, 20, "%i\r\n", uid); + str += numlen; + } + + /* body */ + + cur_src = message + cur_token; + left = size - cur_token; + while (left > 0) { + size_t count; + const char * next; + + str = write_fixed_line(str, cur_src, left, &next, &count); + + cur_src = next; + left -= count; + } + + return str; +} + +#define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n" + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab) +{ + size_t extra_size; + int r; + char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE; + struct tm time_info; + time_t date; + int res; + size_t old_size; + char * str; + unsigned int i; + size_t from_size; + size_t maxuid; + size_t left; + size_t crlf_count; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + date = time(NULL); + from_size = strlen(DEFAULT_FROM_LINE); + if (localtime_r(&date, &time_info) != NULL) + from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info); + + maxuid = /* */ folder->mb_max_uid; + + extra_size = 0; + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + extra_size += from_size; + extra_size += get_fixed_message_size(info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); + extra_size += 2; /* CR LF */ + } + + left = folder->mb_mapping_size; + crlf_count = 0; + while (left >= 1) { + if (folder->mb_mapping[left - 1] == '\n') { + crlf_count ++; + left --; + } + else if (folder->mb_mapping[left - 1] == '\r') { + left --; + } + else + break; + + if (crlf_count == 2) + break; + } + + old_size = folder->mb_mapping_size; + mailmbox_unmap(folder); + + if (old_size != 0) { + if (crlf_count != 2) + extra_size += (2 - crlf_count) * 2; + } + + r = ftruncate(folder->mb_fd, extra_size + old_size); + if (r < 0) { + mailmbox_map(folder); + res = MAILMBOX_ERROR_FILE; + goto err; + } + + r = mailmbox_map(folder); + if (r < 0) { + ftruncate(folder->mb_fd, old_size); + return MAILMBOX_ERROR_FILE; + } + + str = folder->mb_mapping + old_size; + + if (old_size != 0) { + for(i = 0 ; i < 2 - crlf_count ; i ++) { + * str = '\r'; + str ++; + * str = '\n'; + str ++; + } + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + + memcpy(str, from_line, from_size); + + str += strlen(from_line); + + str = write_fixed_message(str, info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); + + * str = '\r'; + str ++; + * str = '\n'; + str ++; + } + + folder->mb_max_uid += carray_count(append_tab); + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab) +{ + int r; + int res; + size_t cur_token; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cur_token = folder->mb_mapping_size; + + r = mailmbox_append_message_list_no_lock(folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_sync(folder); + + r = mailmbox_parse_additionnal(folder, &cur_token); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_timestamp(folder); + + mailmbox_write_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len) +{ + carray * tab; + struct mailmbox_append_info * append_info; + int res; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, append_info, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto free_append_info; + } + + r = mailmbox_append_message_list(folder, tab); + + mailmbox_append_info_free(append_info); + carray_free(tab); + + return r; + + free_append_info: + mailmbox_append_info_free(append_info); + free_list: + carray_free(tab); + err: + return res; +} + +/* ********************************************************************** */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_size - info->msg_start_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_headers_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + +#if 0 + mmapstr = mmap_string_new_len(data, fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + +#if 0 + mmapstr = mmap_string_new_len(data, len); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +void mailmbox_fetch_result_free(char * msg) +{ + mmap_string_unref(msg); +} + + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab) +{ + int r; + int res; + carray * append_tab; + unsigned int i; + + r = mailmbox_validate_read_lock(src_folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + append_tab = carray_new(carray_count(tab)); + if (append_tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(tab) ; i ++) { + struct mailmbox_append_info * append_info; + char * data; + size_t len; + uint32_t uid; + + uid = * ((uint32_t *) carray_get(tab, i)); + + r = mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free_list; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(append_tab, append_info, NULL); + if (r < 0) { + mailmbox_append_info_free(append_info); + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + } + + r = mailmbox_append_message_list(dest_folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + + mailmbox_read_unlock(src_folder); + + return MAILMBOX_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + src_unlock: + mailmbox_read_unlock(src_folder); + err: + return res; +} + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid) +{ + carray * tab; + int res; + uint32_t * puid; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + puid = malloc(sizeof(* puid)); + if (puid == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_array; + } + * puid = uid; + + r = mailmbox_copy_msg_list(dest_folder, src_folder, tab); + res = r; + + free(puid); + free_array: + carray_free(tab); + err: + return res; +} + +static int mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd, + struct mailmbox_folder * folder, + size_t * result_size) +{ + int r; + int res; + unsigned long i; + size_t cur_offset; + char * dest; + size_t size; + + size = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + size += info->msg_size + info->msg_padding; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + uint32_t uid; + + size += strlen(UID_HEADER " \r\n"); + + uid = info->msg_uid; + while (uid >= 10) { + uid /= 10; + size ++; + } + size ++; + } + } + } + } + + r = ftruncate(dest_fd, size); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0); + if (dest == MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + cur_offset = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start, + info->msg_headers_len + info->msg_start_len); + cur_offset += info->msg_headers_len + info->msg_start_len; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + size_t numlen; + + memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " ")); + cur_offset += strlen(UID_HEADER " "); + numlen = snprintf(dest + cur_offset, size - cur_offset, + "%i\r\n", info->msg_uid); + cur_offset += numlen; + } + } + + memcpy(dest + cur_offset, + folder->mb_mapping + info->msg_headers + info->msg_headers_len, + info->msg_size - (info->msg_start_len + info->msg_headers_len) + + info->msg_padding); + + cur_offset += info->msg_size - + (info->msg_start_len + info->msg_headers_len) + + info->msg_padding; + } + } + fflush(stdout); + + msync(dest, size, MS_SYNC); + munmap(dest, size); + + * result_size = size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder) +{ + char tmpfile[PATH_MAX]; + int r; + int res; + int dest_fd; + size_t size; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) && + (!folder->mb_changed)) { + /* no need to expunge */ + return MAILMBOX_NO_ERROR; + } + + snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename); + dest_fd = mkstemp(tmpfile); + + if (dest_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto unlink; + } + + r = mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd, + folder, &size); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlink; + } + + close(dest_fd); + + r = rename(tmpfile, folder->mb_filename); + if (r < 0) { + res = r; + goto err; + } + + mailmbox_unmap(folder); + mailmbox_close(folder); + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + mailmbox_timestamp(folder); + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + return MAILMBOX_NO_ERROR; + + unlink: + close(dest_fd); + unlink(tmpfile); + err: + return res; +} + +int mailmbox_expunge(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + res = r; + + mailmbox_write_unlock(folder); + err: + return res; +} + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info->msg_deleted = TRUE; + folder->mb_changed = TRUE; + folder->mb_deleted_count ++; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +/* + INIT of MBOX + + - open file + - map the file + + - lock the file + + - parse memory + + - unlock the file +*/ + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder) +{ + struct mailmbox_folder * folder; + int r; + int res; + + folder = mailmbox_folder_new(filename); + if (folder == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + folder->mb_no_uid = force_no_uid; + folder->mb_read_only = force_readonly; + folder->mb_written_uid = default_written_uid; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto close; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unmap; + } + + mailmbox_read_unlock(folder); + + * result_folder = folder; + + return MAILMBOX_NO_ERROR; + + unmap: + mailmbox_unmap(folder); + close: + mailmbox_close(folder); + free: + mailmbox_folder_free(folder); + err: + return res; +} + + +/* + when MBOX is DONE + + - check for changes + + - unmap the file + - close file +*/ + +void mailmbox_done(struct mailmbox_folder * folder) +{ + if (!folder->mb_read_only) + mailmbox_expunge(folder); + + mailmbox_unmap(folder); + mailmbox_close(folder); + + mailmbox_folder_free(folder); +} diff --git a/kmicromail/libetpan/mbox/mailmbox.h b/kmicromail/libetpan/mbox/mailmbox.h new file mode 100644 index 0000000..8be086c --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox.h @@ -0,0 +1,140 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMBOX_H + +#define MAILMBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab); + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len); + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +void mailmbox_fetch_result_free(char * msg); + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab); + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid); + +int mailmbox_expunge(struct mailmbox_folder * folder); + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid); + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder); + +void mailmbox_done(struct mailmbox_folder * folder); + +/* low-level access primitives */ + +int mailmbox_write_lock(struct mailmbox_folder * folder); + +int mailmbox_write_unlock(struct mailmbox_folder * folder); + +int mailmbox_read_lock(struct mailmbox_folder * folder); + +int mailmbox_read_unlock(struct mailmbox_folder * folder); + + +/* memory map */ + +int mailmbox_map(struct mailmbox_folder * folder); + +void mailmbox_unmap(struct mailmbox_folder * folder); + +void mailmbox_sync(struct mailmbox_folder * folder); + + +/* open & close file */ + +int mailmbox_open(struct mailmbox_folder * folder); + +void mailmbox_close(struct mailmbox_folder * folder); + + +/* validate cache */ + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder); + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder); + + +/* fetch message */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +/* append message */ + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab); + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mbox/mailmbox_parse.c b/kmicromail/libetpan/mbox/mailmbox_parse.c new file mode 100644 index 0000000..927159c --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox_parse.c @@ -0,0 +1,620 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmbox_parse.h" + +#include "mailmbox.h" + +#include +#include +#include +#include + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static inline int +mailmbox_fields_parse(char * str, size_t length, + size_t * index, + uint32_t * puid, + size_t * phlen) +{ + size_t cur_token; + int r; + size_t hlen; + size_t uid; + int end; + + cur_token = * index; + + end = FALSE; + uid = 0; + while (!end) { + size_t begin; + + begin = cur_token; + + r = mailimf_ignore_field_parse(str, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (str[begin] == 'X') { + + if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) { + begin += strlen(UID_HEADER); + + while (str[begin] == ' ') + begin ++; + + uid = strtoul(str + begin, NULL, 10); + } + } + + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + hlen = cur_token - * index; + + * phlen = hlen; + * puid = uid; + * index = cur_token; + + return MAILMBOX_NO_ERROR; +} + +enum { + IN_MAIL, + FIRST_CR, + FIRST_LF, + SECOND_CR, + SECOND_LF, + PARSING_F, + PARSING_R, + PARSING_O, + PARSING_M, + OUT_MAIL +}; + + + + +static inline int +mailmbox_single_parse(char * str, size_t length, + size_t * index, + size_t * pstart, + size_t * pstart_len, + size_t * pheaders, + size_t * pheaders_len, + size_t * pbody, + size_t * pbody_len, + size_t * psize, + size_t * ppadding, + uint32_t * puid) +{ + size_t cur_token; + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t end; + size_t next; + size_t message_length; + uint32_t uid; + int r; +#if 0 + int in_mail_data; +#endif +#if 0 + size_t begin; +#endif + + int state; + + cur_token = * index; + + if (cur_token >= length) + return MAILMBOX_ERROR_PARSE; + + start = cur_token; + start_len = 0; + headers = cur_token; + + if (cur_token + 5 < length) { + if (strncmp(str + cur_token, "From ", 5) == 0) { + cur_token += 5; + while (str[cur_token] != '\n') { + cur_token ++; + if (cur_token >= length) + break; + } + if (cur_token < length) { + cur_token ++; + headers = cur_token; + start_len = headers - start; + } + } + } + + next = length; + + r = mailmbox_fields_parse(str, length, &cur_token, + &uid, &headers_len); + if (r != MAILMBOX_NO_ERROR) + return r; + + /* save position */ +#if 0 + begin = cur_token; +#endif + + mailimf_crlf_parse(str, length, &cur_token); + +#if 0 + if (str[cur_token] == 'F') { + printf("start !\n"); + printf("%50.50s\n", str + cur_token); + getchar(); + } +#endif + + body = cur_token; + + /* restore position */ + /* cur_token = begin; */ + + state = FIRST_LF; + + end = length; + +#if 0 + in_mail_data = 0; +#endif + while (state != OUT_MAIL) { + + if (cur_token >= length) { + if (state == IN_MAIL) + end = length; + next = length; + break; + } + + switch(state) { + case IN_MAIL: + switch(str[cur_token]) { + case '\r': + state = FIRST_CR; + break; + case '\n': + state = FIRST_LF; + break; + case 'F': + if (cur_token == body) { + end = cur_token; + next = cur_token; + state = PARSING_F; + } + break; +#if 0 + default: + in_mail_data = 1; + break; +#endif + } + break; + + case FIRST_CR: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = FIRST_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case FIRST_LF: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = SECOND_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_CR: + switch(str[cur_token]) { + case '\r': + end = cur_token; + break; + case '\n': + state = SECOND_LF; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_LF: + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + end = cur_token; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_F: + switch(str[cur_token]) { + case 'r': + state = PARSING_R; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_R: + switch(str[cur_token]) { + case 'o': + state = PARSING_O; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_O: + switch(str[cur_token]) { + case 'm': + state = PARSING_M; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_M: + switch(str[cur_token]) { + case ' ': + state = OUT_MAIL; + break; + default: + state = IN_MAIL; + break; + } + break; + } + + cur_token ++; + } + + message_length = end - start; + + * pstart = start; + * pstart_len = start_len; + * pheaders = headers; + * pheaders_len = headers_len; + * pbody = body; + * pbody_len = end - body; + * psize = message_length; + * ppadding = next - end; + * puid = uid; + + * index = next; + + return MAILMBOX_NO_ERROR; +} + + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * index) +{ + size_t cur_token; + + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t body_len; + size_t size; + size_t padding; + uint32_t uid; + int r; + int res; + + uint32_t max_uid; + uint32_t first_index; + unsigned int i; + unsigned int j; + + cur_token = * index; + + /* remove temporary UID that we will parse */ + + first_index = carray_count(folder->mb_tab); + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_start < cur_token) { + continue; + } + + if (!info->msg_written_uid) { + chashdatum key; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + + chash_delete(folder->mb_hash, &key, NULL); + carray_delete_fast(folder->mb_tab, i); + mailmbox_msg_info_free(info); + if (i < first_index) + first_index = i; + } + } + + /* make a sequence in the table */ + + max_uid = folder->mb_written_uid; + + i = 0; + j = 0; + while (i < carray_count(folder->mb_tab)) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) { + carray_set(folder->mb_tab, j, info); + + if (info->msg_uid > max_uid) + max_uid = info->msg_uid; + + info->msg_index = j; + j ++; + } + i ++; + } + carray_set_size(folder->mb_tab, j); + + /* parse content */ + + first_index = j; + + while (1) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + r = mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size, + &cur_token, + &start, &start_len, + &headers, &headers_len, + &body, &body_len, + &size, &padding, &uid); + if (r == MAILMBOX_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILMBOX_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + info = data.data; + + if (!info->msg_written_uid) { + /* some new mail has been written and override an + existing temporary UID */ + + chash_delete(folder->mb_hash, &key, NULL); + info->msg_uid = 0; + + if (info->msg_index < first_index) + first_index = info->msg_index; + } + else + uid = 0; + } + + if (uid > max_uid) + max_uid = uid; + + r = mailmbox_msg_info_update(folder, + start, start_len, headers, headers_len, + body, body_len, size, padding, uid); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + * index = cur_token; + + folder->mb_written_uid = max_uid; + + /* attribute uid */ + + for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_uid != 0) { + continue; + } + + max_uid ++; + info->msg_uid = max_uid; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + folder->mb_max_uid = max_uid; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +static void flush_uid(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + chash_clear(folder->mb_hash); + carray_set_size(folder->mb_tab, 0); +} + +int mailmbox_parse(struct mailmbox_folder * folder) +{ + int r; + int res; + size_t cur_token; + + flush_uid(folder); + + cur_token = 0; + + r = mailmbox_parse_additionnal(folder, &cur_token); + + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} diff --git a/kmicromail/libetpan/mbox/mailmbox_parse.h b/kmicromail/libetpan/mbox/mailmbox_parse.h new file mode 100644 index 0000000..8d3d1d8 --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox_parse.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMBOX_PARSE_H + +#define MAILMBOX_PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmbox_types.h" + +int mailmbox_parse(struct mailmbox_folder * folder); + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mbox/mailmbox_types.c b/kmicromail/libetpan/mbox/mailmbox_types.c new file mode 100644 index 0000000..1986182 --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox_types.c @@ -0,0 +1,250 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmbox_types.h" + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* *********************************************************************** */ + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = &msg_uid; + key.len = sizeof(msg_uid); + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + unsigned int index; + + info = mailmbox_msg_info_new(msg_start, msg_start_len, + msg_headers, msg_headers_len, + msg_body, msg_body_len, msg_size, msg_padding, msg_uid); + if (info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->mb_tab, info, &index); + if (r < 0) { + mailmbox_msg_info_free(info); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + if (msg_uid != 0) { + chashdatum key; + chashdatum data; + + key.data = &msg_uid; + key.len = sizeof(msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + mailmbox_msg_info_free(info); + carray_delete(folder->mb_tab, index); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + info->msg_index = index; + } + else { + info = data.data; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + info->msg_size = msg_size; + info->msg_padding = msg_padding; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->msg_index = 0; + info->msg_uid = msg_uid; + if (msg_uid != 0) + info->msg_written_uid = TRUE; + else + info->msg_written_uid = FALSE; + info->msg_deleted = FALSE; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + + info->msg_size = msg_size; + + info->msg_padding = msg_padding; + + return info; +} + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info) +{ + free(info); +} + + +/* append info */ + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size) +{ + struct mailmbox_append_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->ai_message = ai_message; + info->ai_size = ai_size; + + return info; +} + +void mailmbox_append_info_free(struct mailmbox_append_info * info) +{ + free(info); +} + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename) +{ + struct mailmbox_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + strncpy(folder->mb_filename, mb_filename, PATH_MAX); + + folder->mb_mtime = (time_t) -1; + + folder->mb_fd = -1; + folder->mb_read_only = TRUE; + folder->mb_no_uid = TRUE; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; + + folder->mb_written_uid = 0; + folder->mb_max_uid = 0; + + folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->mb_hash == NULL) + goto free; + + folder->mb_tab = carray_new(128); + if (folder->mb_tab == NULL) + goto free_hash; + + return folder; + + free_hash: + chash_free(folder->mb_hash); + free: + free(folder); + err: + return NULL; +} + +void mailmbox_folder_free(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + carray_free(folder->mb_tab); + + chash_free(folder->mb_hash); + + free(folder); +} diff --git a/kmicromail/libetpan/mbox/mailmbox_types.h b/kmicromail/libetpan/mbox/mailmbox_types.h new file mode 100644 index 0000000..dd6758c --- a/dev/null +++ b/kmicromail/libetpan/mbox/mailmbox_types.h @@ -0,0 +1,142 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMBOX_TYPES_H + +#define MAILMBOX_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include +#include + +enum { + MAILMBOX_NO_ERROR = 0, + MAILMBOX_ERROR_PARSE, + MAILMBOX_ERROR_INVAL, + MAILMBOX_ERROR_FILE_NOT_FOUND, + MAILMBOX_ERROR_MEMORY, + MAILMBOX_ERROR_TEMPORARY_FILE, + MAILMBOX_ERROR_FILE, + MAILMBOX_ERROR_MSG_NOT_FOUND, + MAILMBOX_ERROR_READONLY, +}; + + +struct mailmbox_folder { + char mb_filename[PATH_MAX]; + + time_t mb_mtime; + + int mb_fd; + int mb_read_only; + int mb_no_uid; + + int mb_changed; + unsigned int mb_deleted_count; + + char * mb_mapping; + size_t mb_mapping_size; + + uint32_t mb_written_uid; + uint32_t mb_max_uid; + + chash * mb_hash; + carray * mb_tab; +}; + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename); +void mailmbox_folder_free(struct mailmbox_folder * folder); + + +struct mailmbox_msg_info { + unsigned int msg_index; + uint32_t msg_uid; + int msg_written_uid; + int msg_deleted; + + size_t msg_start; + size_t msg_start_len; + + size_t msg_headers; + size_t msg_headers_len; + + size_t msg_body; + size_t msg_body_len; + + size_t msg_size; + + size_t msg_padding; +}; + + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info); + +struct mailmbox_append_info { + const char * ai_message; + size_t ai_size; +}; + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size); + +void mailmbox_append_info_free(struct mailmbox_append_info * info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mh/.libs/libmailmh.a b/kmicromail/libetpan/mh/.libs/libmailmh.a new file mode 100644 index 0000000..9e9574f --- a/dev/null +++ b/kmicromail/libetpan/mh/.libs/libmailmh.a Binary files differ diff --git a/kmicromail/libetpan/mh/mailmh.c b/kmicromail/libetpan/mh/mailmh.c new file mode 100644 index 0000000..d6ff950 --- a/dev/null +++ b/kmicromail/libetpan/mh/mailmh.c @@ -0,0 +1,965 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmh.h" + +/* +perfs : + +/net/home/dinh/Mail/inbox/sylpheed 686 + +2724 /net/home/dinh/Mail/inbox/sylpheed + +bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null + +real 0m0.385s +user 0m0.270s +sys 0m0.110s + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libetpan-config.h" + +struct mailmh * mailmh_new(const char * foldername) +{ + struct mailmh * f; + + f = malloc(sizeof(*f)); + if (f == NULL) + return NULL; + + f->mh_main = mailmh_folder_new(NULL, foldername); + if (f->mh_main == NULL) { + free(f); + return NULL; + } + + return f; +} + +void mailmh_free(struct mailmh * f) +{ + mailmh_folder_free(f->mh_main); + free(f); +} + + + +struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size, + time_t mtime) +{ + struct mailmh_msg_info * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + return NULL; + msg_info->msg_index = index; + msg_info->msg_size = size; + msg_info->msg_mtime = mtime; + + msg_info->msg_array_index = 0; + + return msg_info; +} + +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info) +{ + free(msg_info); +} + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name) +{ + char * filename; + char * parent_filename; + + struct mailmh_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + if (parent == NULL) { + filename = strdup(name); + if (filename == NULL) + goto free_folder; + } + else { + parent_filename = parent->fl_filename; + filename = malloc(strlen(parent_filename) + strlen(name) + 2); + if (filename == NULL) + goto free_folder; + + strcpy(filename, parent_filename); + strcat(filename, MAIL_DIR_SEPARATOR_S); + strcat(filename, name); + } + + folder->fl_filename = filename; + + folder->fl_name = strdup(name); + if (folder->fl_name == NULL) + goto free_filename; + + folder->fl_msgs_tab = carray_new(128); + if (folder->fl_msgs_tab == NULL) + goto free_name; + +#if 0 + folder->fl_msgs_hash = cinthash_new(128); + if (folder->fl_msgs_hash == NULL) + goto free_msgs_tab; +#endif + folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->fl_msgs_hash == NULL) + goto free_msgs_tab; + + folder->fl_subfolders_tab = carray_new(128); + if (folder->fl_subfolders_tab == NULL) + goto free_msgs_hash; + + folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); + if (folder->fl_subfolders_hash == NULL) + goto free_subfolders_tab; + + folder->fl_mtime = 0; + folder->fl_parent = parent; + folder->fl_max_index = 0; + + return folder; + + free_subfolders_tab: + carray_free(folder->fl_subfolders_tab); + free_msgs_hash: +#if 0 + cinthash_free(folder->fl_msgs_hash); +#endif + chash_free(folder->fl_msgs_hash); + free_msgs_tab: + carray_free(folder->fl_msgs_tab); + free_name: + free(folder->fl_name); + free_filename: + free(folder->fl_filename); + free_folder: + free(folder); + err: + return NULL; +} + +void mailmh_folder_free(struct mailmh_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + if (subfolder != NULL) + mailmh_folder_free(subfolder); + } + carray_free(folder->fl_subfolders_tab); + chash_free(folder->fl_subfolders_hash); + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + mailmh_msg_info_free(msg_info); + } + carray_free(folder->fl_msgs_tab); + chash_free(folder->fl_msgs_hash); +#if 0 + cinthash_free(folder->fl_msgs_hash); +#endif + + free(folder->fl_filename); + free(folder->fl_name); + + free(folder); +} + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename) +{ + int r; + char pathname[PATH_MAX]; + char * p; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + char * start; + + if (strcmp(root->fl_filename, filename) == 0) + return root; + +#if 0 + r = mailmh_folder_update(root); + if (r != MAILMH_NO_ERROR) + return NULL; +#endif + +#if 0 + for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(root->fl_subfolders_tab, i); + if (subfolder != NULL) + if (strncmp(subfolder->fl_filename, filename, + strlen(subfolder->fl_filename)) == 0) + return mailmh_folder_find(subfolder, filename); + } +#endif + strncpy(pathname, filename, PATH_MAX); + pathname[PATH_MAX - 1] = 0; + start = pathname + strlen(root->fl_filename) + 1; + + p = strchr(start, MAIL_DIR_SEPARATOR); + if (p != NULL) { + * p = 0; + + root = mailmh_folder_find(root, pathname); + if (root != NULL) { + folder = mailmh_folder_find(root, filename); + if (folder == NULL) + return NULL; + return folder; + } + + return NULL; + } + else { + key.data = pathname; + key.len = strlen(pathname); + r = chash_get(root->fl_subfolders_hash, &key, &data); + if (r < 0) + return NULL; + + return data.data; + } +} + +int mailmh_folder_update(struct mailmh_folder * folder) +{ + DIR * d; + struct dirent * ent; + struct stat buf; + char * mh_seq; + char filename[PATH_MAX]; + int res; + int r; + uint32_t max_index; +#if 0 + int add_folder; +#endif + unsigned int i; + + if (stat(folder->fl_filename, &buf) == -1) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + if (folder->fl_mtime == buf.st_mtime) { + res = MAILMH_NO_ERROR; + goto err; + } + + folder->fl_mtime = buf.st_mtime; + + d = opendir(folder->fl_filename); + if (d == NULL) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + max_index = 0; + +#if 0 + if (folder->fl_subfolders_tab->len == 0) + add_folder = 1; + else + add_folder = 0; +#endif + + /* clear the message list */ + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + chashdatum key; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info == NULL) + continue; + +#if 0 + cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); +#endif + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + chash_delete(folder->fl_msgs_hash, &key, NULL); + + mailmh_msg_info_free(msg_info); + } + + carray_set_size(folder->fl_msgs_tab, 0); + + do { + uint32_t index; + + ent = readdir(d); + + if (ent != NULL) { + + snprintf(filename, PATH_MAX, + "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); + + if (stat(filename, &buf) == -1) + continue; + + if (S_ISREG(buf.st_mode)) { + index = strtoul(ent->d_name, NULL, 10); + if (index != 0) { + struct mailmh_msg_info * msg_info; + unsigned int array_index; + chashdatum key; + chashdatum data; + + msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); + if (msg_info == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + msg_info->msg_array_index = array_index; + + if (index > max_index) + max_index = index; + +#if 0 + r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); +#endif + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + data.data = msg_info; + data.len = 0; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + else if (S_ISDIR(buf.st_mode)) { + struct mailmh_folder * subfolder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + if (ent->d_name[0] == '.') { + if (ent->d_name[1] == 0) + continue; + if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) + continue; + } + + key.data = ent->d_name; + key.len = strlen(ent->d_name); + r = chash_get(folder->fl_subfolders_hash, &key, &data); + if (r < 0) { + subfolder = mailmh_folder_new(folder, ent->d_name); + if (subfolder == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); + if (r < 0) { + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + subfolder->fl_array_index = array_index; + + key.data = subfolder->fl_filename; + key.len = strlen(subfolder->fl_filename); + data.data = subfolder; + data.len = 0; + r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + } + } + while (ent != NULL); + + folder->fl_max_index = max_index; + + mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); + if (mh_seq == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + strcpy(mh_seq, folder->fl_filename); + strcat(mh_seq, MAIL_DIR_SEPARATOR_S); + strcat(mh_seq, ".mh_sequences"); + + if (stat(mh_seq, &buf) == -1) { + int fd; + + fd = creat(mh_seq, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + free(mh_seq); + + closedir(d); + + return MAILMH_NO_ERROR; + + closedir: + closedir(d); + err: + return res; +} + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name) +{ + char * foldername; + int r; + struct mailmh_folder * folder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); + if (foldername == NULL) + return MAILMH_ERROR_MEMORY; + strcpy(foldername, parent->fl_filename); + strcat(foldername, MAIL_DIR_SEPARATOR_S); + strcat(foldername, name); + + r = mkdir(foldername, 0700); + free(foldername); + + if (r < 0) + return MAILMH_ERROR_FOLDER; + + folder = mailmh_folder_new(parent, name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, &array_index); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + folder->fl_array_index = array_index; + + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); + data.data = folder; + data.len = 0; + + r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) +{ + struct mailmh_folder * parent; + chashdatum key; + chashdatum data; + int r; + + parent = folder->fl_parent; + + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); + + r = chash_get(parent->fl_subfolders_hash, &key, &data); + if (r < 0) + return MAILMH_ERROR_FOLDER; + + chash_delete(parent->fl_subfolders_hash, &key, NULL); + carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); + + mailmh_folder_free(folder); + + return MAILMH_NO_ERROR; + +} + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_folder * parent; + char * new_foldername; + + parent = src_folder->fl_parent; + if (parent == NULL) + return MAILMH_ERROR_RENAME; + + new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); + if (new_foldername == NULL) + return MAILMH_ERROR_MEMORY; + + strcpy(new_foldername, dst_folder->fl_filename); + strcat(new_foldername, MAIL_DIR_SEPARATOR_S); + strcat(new_foldername, new_name); + + r = rename(src_folder->fl_filename, new_foldername); + free(new_foldername); + if (r < 0) + return MAILMH_ERROR_RENAME; + + r = mailmh_folder_remove_subfolder(src_folder); + if (r != MAILMH_NO_ERROR) + return r; + + folder = mailmh_folder_new(dst_folder, new_name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, NULL); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +#define MAX_TRY_ALLOC 32 + +/* initial file MUST be in the same directory */ + +static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, + char * filename, uint32_t * result) +{ + uint32_t max; + uint32_t k; + char * new_filename; + size_t len; + + len = strlen(folder->fl_filename) + 20; + new_filename = malloc(len); + if (new_filename == NULL) + return MAILMH_ERROR_MEMORY; + + max = folder->fl_max_index + 1; + + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, + MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); + + if (link(filename, new_filename) == 0) { + int r; + + free(new_filename); + unlink(filename); + + if (k > MAX_TRY_ALLOC / 2) { + r = mailmh_folder_update(folder); + /* ignore errors */ + } + + * result = max + k; + + folder->fl_max_index = max + k; + + return MAILMH_NO_ERROR; + } + else if (errno == EXDEV) { + free(filename); + return MAILMH_ERROR_FOLDER; + } + k ++; + } + + free(new_filename); + + return MAILMH_ERROR_FOLDER; +} + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t index, char ** result) +{ + char * filename; + int len; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + len = strlen(folder->fl_filename) + 20; + filename = malloc(len); + if (filename == NULL) + return MAILMH_ERROR_MEMORY; + + snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, + (unsigned long) index); + + * result = filename; + + return MAILMH_NO_ERROR;; +} + + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t index, int flags, int * result) +{ + char * filename; + int fd; + int r; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + fd = open(filename, flags); + free(filename); + if (fd == -1) + return MAILMH_ERROR_MSG_NOT_FOUND; + + * result = fd; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t index, size_t * result) +{ + int r; + char * filename; + struct stat buf; + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = stat(filename, &buf); + free(filename); + if (r < 0) + return MAILMH_ERROR_FILE; + + * result = buf.st_size; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size) +{ + char * tmpname; + int fd; + size_t namesize; + size_t left; + ssize_t res; + struct mailmh_msg_info * msg_info; + uint32_t index; + int error; + int r; + unsigned int array_index; + struct stat buf; + chashdatum key; + chashdatum data; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) { + error = r; + goto err; + } +#endif + + namesize = strlen(folder->fl_filename) + 20; + tmpname = malloc(namesize); + snprintf(tmpname, namesize, "%s%ctmpXXXXXX", + folder->fl_filename, MAIL_DIR_SEPARATOR); + fd = mkstemp(tmpname); + if (fd < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + left = size; + while (left > 0) { + res = write(fd, message, left); + if (res == -1) { + close(fd); + error = MAILMH_ERROR_FILE; + goto free; + } + + left -= res; + } + close(fd); + + r = stat(tmpname, &buf); + if (r < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + r = mailmh_folder_alloc_msg(folder, tmpname, &index); + if (r != MAILMH_NO_ERROR) { + unlink(tmpname); + error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; + goto free; + } + free(tmpname); + + msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); + if (msg_info == NULL) { + mailmh_folder_remove_message(folder, index); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_folder_remove_message(folder, index); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + msg_info->msg_array_index = array_index; + +#if 0 + r = cinthash_add(folder->fl_msgs_hash, index, msg_info); +#endif + key.data = &index; + key.len = sizeof(index); + data.data = msg_info; + data.len = 0; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + return MAILMH_NO_ERROR; + + free: + free(tmpname); + err: + return error; +} + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd) +{ + char * message; + struct stat buf; + int r; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + if (fstat(fd, &buf) == -1) + return MAILMH_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == MAP_FAILED) + return MAILMH_ERROR_FILE; + + r = mailmh_folder_add_message(folder, message, buf.st_size); + + munmap(message, buf.st_size); + + return r; +} + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t index) +{ + char * filename; + struct mailmh_msg_info * msg_info; + int res; + int r; + chashdatum key; + chashdatum data; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) { + res = r; + goto err; + } +#endif + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (filename == NULL) { + res = r; + goto err; + } + + if (unlink(filename) == -1) { + res = MAILMH_ERROR_FILE; + goto free; + } + + key.data = &index; + key.len = sizeof(index); + r = chash_get(folder->fl_msgs_hash, &key, &data); +#if 0 + msg_info = cinthash_find(folder->fl_msgs_hash, index); +#endif + if (r == 0) { + msg_info = data.data; + + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); +#if 0 + cinthash_remove(folder->fl_msgs_hash, index); +#endif + chash_delete(folder->fl_msgs_hash, &key, NULL); + } + + return MAILMH_NO_ERROR; + + free: + free(filename); + err: + return res; +} + + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t index) +{ + int fd; + char * filename; + int r; + +#if 0 + r = mailmh_folder_update(dest_folder); + if (r != MAILMH_NO_ERROR) + return r; + r = mailmh_folder_update(src_folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + /* move on the same filesystem */ + r = mailmh_folder_get_message_filename(src_folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_alloc_msg(dest_folder, filename, &index); + free(filename); + if (r == MAILMH_NO_ERROR) + return MAILMH_NO_ERROR; + + /* move on the different filesystems */ + r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_add_message_file(dest_folder, fd); + if (r != MAILMH_NO_ERROR) { + close(fd); + return r; + } + + close(fd); + + r = mailmh_folder_remove_message(src_folder, index); + + return MAILMH_NO_ERROR; +} + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) +{ + unsigned int i; + unsigned int count; + + count = 0; + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) + if (carray_get(folder->fl_msgs_tab, i) != NULL) + count ++; + + return count; +} diff --git a/kmicromail/libetpan/mh/mailmh.h b/kmicromail/libetpan/mh/mailmh.h new file mode 100644 index 0000000..40432cb --- a/dev/null +++ b/kmicromail/libetpan/mh/mailmh.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMH_H + +#define MAILMH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +enum { + MAILMH_NO_ERROR = 0, + MAILMH_ERROR_FOLDER, + MAILMH_ERROR_MEMORY, + MAILMH_ERROR_FILE, + MAILMH_ERROR_COULD_NOT_ALLOC_MSG, + MAILMH_ERROR_RENAME, + MAILMH_ERROR_MSG_NOT_FOUND, +}; + +struct mailmh { + struct mailmh_folder * mh_main; +}; + +struct mailmh_msg_info { + unsigned int msg_array_index; + uint32_t msg_index; + size_t msg_size; + time_t msg_mtime; +}; + +struct mailmh_folder { + char * fl_filename; + unsigned int fl_array_index; + + char * fl_name; + time_t fl_mtime; + struct mailmh_folder * fl_parent; + uint32_t fl_max_index; + + carray * fl_msgs_tab; +#if 0 + cinthash_t * fl_msgs_hash; +#endif + chash * fl_msgs_hash; + + carray * fl_subfolders_tab; + chash * fl_subfolders_hash; +}; + +struct mailmh * mailmh_new(const char * foldername); +void mailmh_free(struct mailmh * f); + +struct mailmh_msg_info * +mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime); +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info); + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name); +void mailmh_folder_free(struct mailmh_folder * folder); + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name); + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename); + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder); + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name); + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t index, char ** result); + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t index, int flags, int * result); + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t index, size_t * result); + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size); + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd); + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t index); + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t index); + +int mailmh_folder_update(struct mailmh_folder * folder); + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/.libs/libmailmime.a b/kmicromail/libetpan/mime/.libs/libmailmime.a new file mode 100644 index 0000000..902b9d9 --- a/dev/null +++ b/kmicromail/libetpan/mime/.libs/libmailmime.a Binary files differ diff --git a/kmicromail/libetpan/mime/TODO b/kmicromail/libetpan/mime/TODO new file mode 100644 index 0000000..df02810 --- a/dev/null +++ b/kmicromail/libetpan/mime/TODO @@ -0,0 +1,10 @@ +- see about the RFC2047, beginning in mailmime_decode.[ch] +- content-langage +- single mime_field +- RFC 2048 +- RFC 2049 +- RFC 2231 +- RFC 2387 +- RFC 2424 +- RFC 2557 + diff --git a/kmicromail/libetpan/mime/mailmime.c b/kmicromail/libetpan/mime/mailmime.c new file mode 100644 index 0000000..e920722 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.c @@ -0,0 +1,1408 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime.h" + +/* + RFC 2045 + RFC 2046 + RFC 2047 + RFC 2048 + RFC 2049 + RFC 2231 + RFC 2387 + RFC 2424 + RFC 2557 + + RFC 2183 Content-Disposition + + RFC 1766 Language + */ + +#include +#include +#include + +#include "mailmime_types.h" +#include "mailmime_disposition.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result); +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result); + +static int is_text(char ch); + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result); + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int is_token(char ch); + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token); + +static int is_tspecials(char ch); + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result); + +/* +int mailmime_version_parse(const char * message, guint32 length, + guint32 * index, + guint32 * result); +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result); +*/ + +/* ********************************************************************** */ + +/* +x attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. +*/ + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* +x composite-type := "message" / "multipart" / extension-token +*/ + +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result) +{ + char * extension_token; + int type; + struct mailmime_composite_type * ct; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension_token = NULL; + + type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "message"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "multipart"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MULTIPART; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + ct = mailmime_composite_type_new(type, extension_token); + if (ct == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_extension; + } + + * result = ct; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_extension: + if (extension_token != NULL) + mailmime_extension_token_free(extension_token); + err: + return res; +} + +/* +x content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. +*/ + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result) +{ + size_t cur_token; + struct mailmime_type * type; + char * subtype; + clist * parameters_list; + struct mailmime_content * content; + int r; + int res; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailmime_type_parse(message, length, &cur_token, &type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '/'); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_subtype_parse(message, length, &cur_token, &subtype); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_type; + } + break; + + case MAILIMF_ERROR_PARSE: + subtype = strdup("unknown"); + break; + + default: + res = r; + goto free_type; + } + + parameters_list = clist_new(); + if (parameters_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + size_t final_token; + struct mailmime_parameter * parameter; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r != MAILIMF_NO_ERROR) { + cur_token = final_token; + break; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_parameter_parse(message, length, &cur_token, ¶meter); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto err; + } + + r = clist_append(parameters_list, parameter); + if (r < 0) { + mailmime_parameter_free(parameter); + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + } + + content = mailmime_content_new(type, subtype, parameters_list); + if (content == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_parameters: + clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters_list); + + mailmime_subtype_free(subtype); + free_type: + mailmime_type_free(type); + err: + return res; +} + +/* +x description := "Content-Description" ":" *text +*/ + +static int is_text(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 1) + return FALSE; + + if ((uch == 10) || (uch == 13)) + return FALSE; + + return TRUE; +} + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_text); +} + +/* +x discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token +*/ + +/* currently porting */ + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result) +{ + char * extension; + int type; + struct mailmime_discrete_type * discrete_type; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension = NULL; + + type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "text"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_TEXT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "image"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_IMAGE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "audio"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_AUDIO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "video"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_VIDEO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "application"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_APPLICATION; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, + &cur_token, &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + discrete_type = mailmime_discrete_type_new(type, extension); + if (discrete_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = discrete_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mailmime_extension_token_free(extension); + err: + return res; +} + +/* +x encoding := "Content-Transfer-Encoding" ":" mechanism +*/ + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + return mailmime_mechanism_parse(message, length, index, result); +} + +/* +x entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + */ + +enum { + FIELD_STATE_START, + FIELD_STATE_T, + FIELD_STATE_D +}; + +static int guess_field_type(char * name) +{ + int state; + + if (* name == 'M') + return MAILMIME_FIELD_VERSION; + + if (strncasecmp(name, "Content-", 8) != 0) + return MAILMIME_FIELD_NONE; + + name += 8; + + state = FIELD_STATE_START; + + while (1) { + + switch (state) { + + case FIELD_STATE_START: + switch ((char) toupper((unsigned char) * name)) { + case 'T': + state = FIELD_STATE_T; + break; + case 'I': + return MAILMIME_FIELD_ID; + case 'D': + state = FIELD_STATE_D; + break; + case 'L': + return MAILMIME_FIELD_LANGUAGE; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_T: + switch ((char) toupper((unsigned char) * name)) { + case 'Y': + return MAILMIME_FIELD_TYPE; + case 'R': + return MAILMIME_FIELD_TRANSFER_ENCODING; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_D: + switch ((char) toupper((unsigned char) * name)) { + case 'E': + return MAILMIME_FIELD_DESCRIPTION; + case 'I': + return MAILMIME_FIELD_DISPOSITION; + default: + return MAILMIME_FIELD_NONE; + } + break; + } + name ++; + } +} + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result) +{ + char * name; + char * value; + int guessed_type; + size_t cur_token; + struct mailmime_content * content; + struct mailmime_mechanism * encoding; + char * id; + char * description; + uint32_t version; + struct mailmime_field * mime_field; + struct mailmime_language * language; + struct mailmime_disposition * disposition; + int res; + int r; + + name = field->fld_name; + value = field->fld_value; + cur_token = 0; + + content = NULL; + encoding = NULL; + id = NULL; + description = NULL; + version = 0; + disposition = NULL; + language = NULL; + + guessed_type = guess_field_type(name); + + switch (guessed_type) { + case MAILMIME_FIELD_TYPE: + if (strcasecmp(name, "Content-Type") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_content_parse(value, strlen(value), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (strcasecmp(name, "Content-Transfer-Encoding") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_ID: + if (strcasecmp(name, "Content-ID") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_id_parse(value, strlen(value), &cur_token, &id); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DESCRIPTION: + if (strcasecmp(name, "Content-Description") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_description_parse(value, strlen(value), + &cur_token, &description); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_VERSION: + if (strcasecmp(name, "MIME-Version") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_version_parse(value, strlen(value), &cur_token, &version); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DISPOSITION: + if (strcasecmp(name, "Content-Disposition") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_disposition_parse(value, strlen(value), + &cur_token, &disposition); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_LANGUAGE: + if (strcasecmp(name, "Content-Language") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_language_parse(value, strlen(value), &cur_token, &language); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + return MAILIMF_ERROR_PARSE; + } + + mime_field = mailmime_field_new(guessed_type, content, encoding, + id, description, version, disposition, + language); + if (mime_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime_field; + + return MAILIMF_NO_ERROR; + + free: + if (content != NULL) + mailmime_content_free(content); + if (encoding != NULL) + mailmime_encoding_free(encoding); + if (id != NULL) + mailmime_id_free(id); + if (description != NULL) + mailmime_description_free(description); + return res; +} + +/* +x extension-token := ietf-token / x-token +*/ + +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". +*/ + +/* +x iana-token := +*/ + +/* +x ietf-token := +*/ + +/* +x id := "Content-ID" ":" msg-id +*/ + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_msg_id_parse(message, length, index, result); +} + +/* +x mechanism := "7bit" / "8bit" / "binary" / + "quoted-printable" / "base64" / + ietf-token / x-token +*/ + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + char * token; + int type; + struct mailmime_mechanism * mechanism; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */ + + token = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "7bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_7BIT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "8bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_8BIT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "binary"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BINARY; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "quoted-printable"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "base64"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BASE64; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_token_parse(message, length, &cur_token, &token); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_TOKEN; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mechanism = mailmime_mechanism_new(type, token); + if (mechanism == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mechanism; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (token != NULL) + mailmime_token_free(token); + err: + return res; +} + +/* +x MIME-extension-field := +*/ + +/* +in headers + +x MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +/* +in message + +x MIME-part-headers := entity-headers + [fields] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +#if 0 +int +mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + if (fields->list == NULL) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_optional_field * field = cur->data; + struct mailmime_field * mime_field; + + r = mailmime_field_parse(field, &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + struct mailmime_field * mime_field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} + +/* +x parameter := attribute "=" value +*/ + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result) +{ + char * attribute; + char * value; + struct mailmime_parameter * parameter; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailmime_attribute_parse(message, length, &cur_token, &attribute); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_attr; + } + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + parameter = mailmime_parameter_new(attribute, value); + if (parameter == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = parameter; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailmime_value_free(value); + free_attr: + mailmime_attribute_free(attribute); + err: + return res; +} + +/* + ptext := hex-octet / safe-char +*/ + +/* + qp-line := *(qp-segment transport-padding CRLF) + qp-part transport-padding +*/ + +/* + qp-part := qp-section + ; Maximum length of 76 characters +*/ + +/* + qp-section := [*(ptext / SPACE / TAB) ptext] +*/ + +/* + qp-segment := qp-section *(SPACE / TAB) "=" + ; Maximum length of 76 characters +*/ + +/* + quoted-printable := qp-line *(CRLF qp-line) +*/ + +/* + safe-char := + ; Characters not listed as "mail-safe" in + ; RFC 2049 are also not recommended. +*/ + +/* +x subtype := extension-token / iana-token +*/ + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_extension_token_parse(message, length, index, result); +} + +/* +x token := 1* +*/ + +static int is_token(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch > 0x7F) + return FALSE; + + if (uch == ' ') + return FALSE; + + if (is_tspecials(ch)) + return FALSE; + + return TRUE; +} + + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token) +{ + return mailimf_custom_string_parse(message, length, + index, token, + is_token); +} + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + +/* +enum { + LWSP_1, + LWSP_2, + LWSP_3, + LWSP_4, + LWSP_OK +}; + +gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length, + guint32 * index) +{ + guint32 cur_token; + gint state; + guint32 last_valid_pos; + + cur_token = * index; + + if (cur_token >= length) + return FALSE; + + state = LWSP_1; + + while (state != LWSP_OUT) { + + if (cur_token >= length) + return FALSE; + + switch (state) { + case LWSP_1: + last_valid_pos = cur_token; + + switch (message[cur_token]) { + case '\r': + state = LWSP_2; + break; + case '\n': + state = LWSP_3; + break; + case ' ': + case '\t': + state = LWSP_4; + break; + default: + state = LWSP_OK; + break; + } + case LWSP_2: + switch (message[cur_token]) { + case '\n': + state = LWSP_3; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + case LWSP_3: + switch (message[cur_token]) { + case ' ': + case '\t': + state = LWSP_1; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + + cur_token ++; + } + } + + * index = cur_token; + + return TRUE; +} +*/ + +/* +x tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + +static int is_tspecials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '\"': + case '/': + case '[': + case ']': + case '?': + case '=': + return TRUE; + default: + return FALSE; + } +} + +/* +x type := discrete-type / composite-type +*/ + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result) +{ + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + size_t cur_token; + struct mailmime_type * mime_type; + int type; + int res; + int r; + + cur_token = * index; + + discrete_type = NULL; + composite_type = NULL; + + type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailmime_composite_type_parse(message, length, &cur_token, + &composite_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_COMPOSITE_TYPE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_discrete_type_parse(message, length, &cur_token, + &discrete_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_DISCRETE_TYPE; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mime_type = mailmime_type_new(type, discrete_type, composite_type); + if (mime_type == NULL) { + res = r; + goto free; + } + + * result = mime_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +/* +x value := token / quoted-string +*/ + +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailmime_token_parse(message, length, index, result); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, index, result); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +/* +x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT +*/ + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t hi; + uint32_t low; + uint32_t version; + int r; + + cur_token = * index; + + r = mailimf_number_parse(message, length, &cur_token, &hi); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '.'); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &low); + if (r != MAILIMF_NO_ERROR) + return r; + + version = (hi << 16) + low; + + * result = version; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +x x-token := +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result) +{ + guint32 cur_token; + gchar * token; + gchar * x_token; + gboolean min_x; + + cur_token = * index; + + if (!mailimf_char_parse(message, length, &cur_token, 'x')) { + if (!mailimf_char_parse(message, length, &cur_token, 'X')) + return FALSE; + min_x = FALSE; + } + else + min_x = TRUE; + + if (!mailimf_char_parse(message, length, &cur_token, '-')) + return FALSE; + + if (!mailmime_token_parse(message, length, &cur_token, &token)) + return FALSE; + + if (min_x) + x_token = g_strconcat("x-", token, NULL); + else + x_token = g_strconcat("X-", token, NULL); + mailmime_token_free(token); + + if (x_token == NULL) + return FALSE; + + * result = x_token; + * index = cur_token; + + return TRUE; +} +*/ + + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result) +{ + size_t cur_token; + int r; + int res; + clist * list; + int first; + struct mailmime_language * language; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + char * atom; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, ','); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = mailimf_atom_parse(message, length, &cur_token, &atom); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = clist_append(list, atom); + if (r < 0) { + mailimf_atom_free(atom); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + language = mailmime_language_new(list); + if (language == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = language; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimf_atom_free, NULL); + clist_free(list); + err: + return res; +} diff --git a/kmicromail/libetpan/mime/mailmime.h b/kmicromail/libetpan/mime/mailmime.h new file mode 100644 index 0000000..c834967 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_content.c b/kmicromail/libetpan/mime/mailmime_content.c new file mode 100644 index 0000000..c73812d --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.c @@ -0,0 +1,2164 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailimf.h" + +#include +#include + +#include "mailmime.h" +#include "mailmime_types.h" +#include "mmapstring.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* + RFC 2045 + RFC 2046 + RFC 2047 + + RFC 2231 +*/ + + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + + + +char * mailmime_content_charset_get(struct mailmime_content * content) +{ + char * charset; + + charset = mailmime_content_param_get(content, "charset"); + if (charset == NULL) + return "us-ascii"; + else + return charset; +} + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name) +{ + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, name) == 0) + return param->pa_value; + } + + return NULL; +} + + +/* + boundary := 0*69 bcharsnospace +*/ + +/* + bchars := bcharsnospace / " " +*/ + +/* + bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / + "+" / "_" / "," / "-" / "." / + "/" / ":" / "=" / "?" +*/ + +/* + body-part := <"message" as defined in RFC 822, with all + header fields optional, not starting with the + specified dash-boundary, and with the + delimiter not occurring anywhere in the + body part. Note that the semantics of a + part differ from the semantics of a message, + as described in the text.> +*/ + +/* + close-delimiter := delimiter "--" +*/ + +/* + dash-boundary := "--" boundary + ; boundary taken from the value of + ; boundary parameter of the + ; Content-Type field. +*/ + +/* + delimiter := CRLF dash-boundary +*/ + +/* + discard-text := *(*text CRLF) + ; May be ignored or discarded. +*/ + +/* + encapsulation := delimiter transport-padding + CRLF body-part +*/ + +/* + epilogue := discard-text +*/ + +/* + multipart-body := [preamble CRLF] + dash-boundary transport-padding CRLF + body-part *encapsulation + close-delimiter transport-padding + [CRLF epilogue] +*/ + +/* + preamble := discard-text +*/ + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + + +/* + ACCESS-TYPE + EXPIRATION + SIZE + PERMISSION +*/ + +/* + 5.2.3.2. The 'ftp' and 'tftp' Access-Types + NAME + SITE + + (3) Before any data are retrieved, using FTP, the user will + generally need to be asked to provide a login id and a + password for the machine named by the site parameter. + For security reasons, such an id and password are not + specified as content-type parameters, but must be + obtained from the user. + + optional : + DIRECTORY + MODE +*/ + +/* +5.2.3.3. The 'anon-ftp' Access-Type +*/ + +/* +5.2.3.4. The 'local-file' Access-Type +NAME +SITE +*/ + +/* +5.2.3.5. The 'mail-server' Access-Type +SERVER +SUBJECT +*/ + + +enum { + PREAMBLE_STATE_A0, + PREAMBLE_STATE_A, + PREAMBLE_STATE_A1, + PREAMBLE_STATE_B, + PREAMBLE_STATE_C, + PREAMBLE_STATE_D, + PREAMBLE_STATE_E +}; + +static int mailmime_preamble_parse(const char * message, size_t length, + size_t * index, int beol) +{ + int state; + size_t cur_token; + + cur_token = * index; + if (beol) + state = PREAMBLE_STATE_A0; + else + state = PREAMBLE_STATE_A; + + while (state != PREAMBLE_STATE_E) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (state) { + case PREAMBLE_STATE_A0: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_A1; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A1: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_B: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + case '-': + state = PREAMBLE_STATE_D; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_C: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_D; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_D: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_boundary_parse(const char * message, size_t length, + size_t * index, char * boundary) +{ + size_t cur_token; + size_t len; + + cur_token = * index; + + len = strlen(boundary); + + if (cur_token + len >= length) + return MAILIMF_ERROR_PARSE; + + if (strncmp(message + cur_token, boundary, len) != 0) + return MAILIMF_ERROR_PARSE; + + cur_token += len; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int is_wsp(char ch) +{ + if ((ch == ' ') || (ch == '\t')) + return TRUE; + + return FALSE; +} + +static int mailmime_lwsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + while (is_wsp(message[cur_token])) { + cur_token ++; + if (cur_token >= length) + break; + } + + if (cur_token == * index) + return MAILIMF_ERROR_PARSE; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index) +*/ + +enum { + BODY_PART_DASH2_STATE_0, + BODY_PART_DASH2_STATE_1, + BODY_PART_DASH2_STATE_2, + BODY_PART_DASH2_STATE_3, + BODY_PART_DASH2_STATE_4, + BODY_PART_DASH2_STATE_5, + BODY_PART_DASH2_STATE_6 +}; + +static int +mailmime_body_part_dash2_parse(const char * message, size_t length, + size_t * index, char * boundary, + const char ** result, size_t * result_size) +{ + int state; + size_t cur_token; + size_t size; + size_t begin_text; + size_t end_text; + int r; + + cur_token = * index; + state = BODY_PART_DASH2_STATE_0; + + begin_text = cur_token; + end_text = length; + + while (state != BODY_PART_DASH2_STATE_5) { + + if (cur_token >= length) + break; + + switch(state) { + + case BODY_PART_DASH2_STATE_0: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_1: + switch (message[cur_token]) { + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_2: + switch (message[cur_token]) { + case '-': + end_text = cur_token; + state = BODY_PART_DASH2_STATE_3; + break; + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_3: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + case '-': + state = BODY_PART_DASH2_STATE_4; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_4: + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) + state = BODY_PART_DASH2_STATE_5; + else + state = BODY_PART_DASH2_STATE_6; + + break; + } + + if ((state != BODY_PART_DASH2_STATE_5) && + (state != BODY_PART_DASH2_STATE_6)) + cur_token ++; + + if (state == BODY_PART_DASH2_STATE_6) + state = BODY_PART_DASH2_STATE_0; + } + + end_text --; + if (end_text >= 1) + if (message[end_text - 1] == '\r') + end_text --; + + size = end_text - begin_text; + +#if 0 + body_part = mailimf_body_new(message + begin_text, size); + if (body_part == NULL) + goto err; +#endif + + * result = message + begin_text; + * result_size = size; + * index = cur_token; + + return MAILIMF_NO_ERROR; +#if 0 + err: + return MAILIMF_ERROR_PARSE; +#endif +} + +enum { + MULTIPART_CLOSE_STATE_0, + MULTIPART_CLOSE_STATE_1, + MULTIPART_CLOSE_STATE_2, + MULTIPART_CLOSE_STATE_3, + MULTIPART_CLOSE_STATE_4 +}; + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_CLOSE_STATE_0; + + while (state != MULTIPART_CLOSE_STATE_4) { + + switch(state) { + + case MULTIPART_CLOSE_STATE_0: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_1; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_1: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_2: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case ' ': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\t': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\r': + state = MULTIPART_CLOSE_STATE_3; + break; + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + + case MULTIPART_CLOSE_STATE_3: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_NEXT_STATE_0, + MULTIPART_NEXT_STATE_1, + MULTIPART_NEXT_STATE_2 +}; + +int mailmime_multipart_next_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_NEXT_STATE_0; + + while (state != MULTIPART_NEXT_STATE_2) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(state) { + + case MULTIPART_NEXT_STATE_0: + switch (message[cur_token]) { + case ' ': + state = MULTIPART_NEXT_STATE_0; + break; + case '\t': + state = MULTIPART_NEXT_STATE_0; + break; + case '\r': + state = MULTIPART_NEXT_STATE_1; + break; + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_NEXT_STATE_1: + switch (message[cur_token]) { + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_multipart_body_parse(const char * message, size_t length, + size_t * index, char * boundary, + int default_subtype, + clist ** result, + struct mailmime_data ** p_preamble, + struct mailmime_data ** p_epilogue) +{ + size_t cur_token; + clist * list; + int r; + int res; +#if 0 + size_t begin; +#endif + size_t preamble_begin; + size_t preamble_length; + size_t preamble_end; +#if 0 + int no_preamble; + size_t before_crlf; +#endif + size_t epilogue_begin; + size_t epilogue_length; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + size_t part_begin; + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + preamble_begin = cur_token; + +#if 0 + no_preamble = FALSE; +#endif + preamble_end = preamble_begin; + +#if 0 + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + no_preamble = TRUE; + } + else { + res = r; + goto err; + } + + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + no_preamble = TRUE; + break; + } + else { + res = r; + goto err; + } + } + + if (no_preamble) { +#if 0 + preamble_end = cur_token; +#endif + } + else { + + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + before_crlf = cur_token; + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = before_crlf; +#endif + /* remove the CR LF at the end of preamble if any */ + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + } + preamble_length = preamble_end - begin; +#endif + + r = mailmime_preamble_parse(message, length, &cur_token, 1); + if (r == MAILIMF_NO_ERROR) { + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token, 0); + if (r == MAILIMF_NO_ERROR) { + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + } + } + + preamble_end -= 2; + if (preamble_end != preamble_begin) { + /* try to find the real end of the preamble (strip CR LF) */ + if (message[preamble_end - 1] == '\n') { + preamble_end --; + if (preamble_end - 1 >= preamble_begin) { + if (message[preamble_end - 1] == '\r') + preamble_end --; + } + } + else if (message[preamble_end - 1] == '\r') { + preamble_end --; + } + } + preamble_length = preamble_end - preamble_begin; + + part_begin = cur_token; + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + part_begin = cur_token; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto err; + } + } + + cur_token = part_begin; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + size_t bp_token; + struct mailmime * mime_bp; + const char * data_str; + size_t data_size; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + + r = mailmime_body_part_dash2_parse(message, length, &cur_token, + boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + + bp_token = 0; + + + r = mailimf_optional_fields_parse(data_str, data_size, + &bp_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(data_str, data_size, &bp_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free; + } + + mime_fields = NULL; + r = mailmime_fields_parse(fields, &mime_fields); + mailimf_fields_free(fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, default_subtype, NULL, + mime_fields, &mime_bp); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_bp); + if (r < 0) { + mailmime_free(mime_bp); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + break; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + r = mailmime_multipart_next_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_multipart_close_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + break; + } + else { + res = r; + goto free; + } + } + + epilogue_begin = length; + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + +#if 0 + before_crlf = cur_token; +#endif + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + epilogue_begin = cur_token; + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto free; + } + } + + /* add preamble and epilogue */ + + epilogue_length = length - epilogue_begin; + + if (preamble_length != 0) { + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + preamble_begin, preamble_length, + NULL); + if (preamble == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + if (epilogue_length != 0) { + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + epilogue_begin, epilogue_length, + NULL); + if (epilogue == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + /* end of preamble and epilogue */ + + cur_token = length; + + * result = list; + * p_preamble = preamble; + * p_epilogue = epilogue; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + err: + return res; +} + +enum { + MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + MAILMIME_DEFAULT_TYPE_MESSAGE +}; + + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result) +{ + struct mailmime * mime; + int r; + int res; + struct mailmime_content * content_message; + size_t cur_token; + struct mailmime_fields * mime_fields; + const char * data_str; + size_t data_size; + size_t bp_token; + + cur_token = * index; + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + mime_fields = mailmime_fields_new_with_data(content_message, + NULL, + NULL, + NULL, + NULL, + NULL); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } +#endif + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + data_str = message + cur_token; + data_size = length - cur_token; + + bp_token = 0; + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + content_message, mime_fields, &mime); + cur_token += bp_token; + if (r != MAILIMF_NO_ERROR) { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + * index = cur_token; + * result = mime; + + return MAILIMF_NO_ERROR; + + free: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +char * mailmime_extract_boundary(struct mailmime_content * content_type) +{ + char * boundary; + + boundary = mailmime_content_param_get(content_type, "boundary"); + + if (boundary != NULL) { + int len; + char * new_boundary; + + len = strlen(boundary); + new_boundary = malloc(len + 1); + if (new_boundary == NULL) + return NULL; + + if (boundary[0] == '"') { + strncpy(new_boundary, boundary + 1, len - 2); + new_boundary[len - 2] = 0; + } + else + strcpy(new_boundary, boundary); + + boundary = new_boundary; + } + + return boundary; +} + +static void remove_unparsed_mime_headers(struct mailimf_fields * fields) +{ + clistiter * cur; + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + int delete; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_OPTIONAL_FIELD: + delete = 0; + if (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-", 8) == 0) { + char * name; + + name = field->fld_data.fld_optional_field->fld_name + 8; + if ((strcasecmp(name, "Type") == 0) + || (strcasecmp(name, "Transfer-Encoding") == 0) + || (strcasecmp(name, "ID") == 0) + || (strcasecmp(name, "Description") == 0) + || (strcasecmp(name, "Disposition") == 0) + || (strcasecmp(name, "Language") == 0)) { + delete = 1; + } + } + else if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + delete = 1; + } + + if (delete) { + cur = clist_delete(fields->fld_list, cur); + mailimf_field_free(field); + } + else { + cur = clist_next(cur); + } + break; + + default: + cur = clist_next(cur); + } + } +} + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + size_t cur_token; + + int body_type; + + int encoding; + struct mailmime_data * body; + char * boundary; + struct mailimf_fields * fields; + clist * list; + struct mailmime * msg_mime; + + struct mailmime * mime; + + int r; + int res; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + + /* + note that when this function is called, content type is always detached, + even if the function fails + */ + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + + /* get content type */ + + if (content_type == NULL) { + if (mime_fields != NULL) { + clistiter * cur; + + for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TYPE) { + content_type = field->fld_data.fld_content; + + /* detach content type from list */ + field->fld_data.fld_content = NULL; + clist_delete(mime_fields->fld_list, cur); + mailmime_field_free(field); + /* + there may be a leak due to the detached content type + in case the function fails + */ + break; + } + } + } + } + + /* set default type if no content type */ + + if (content_type == NULL) { + /* content_type is detached, in any case, we will have to free it */ + if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { + content_type = mailmime_get_content_text(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else /* message */ { + body_type = MAILMIME_MESSAGE; + + content_type = mailmime_get_content_message(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + } + + /* get the body type */ + + boundary = NULL; /* XXX - removes a gcc warning */ + + switch (content_type->ct_type->tp_type) { + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + boundary = mailmime_extract_boundary(content_type); + + if (boundary == NULL) + body_type = MAILMIME_SINGLE; + else + body_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + + if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) + body_type = MAILMIME_MESSAGE; + else + body_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free_content; + } + break; + + default: /* MAILMIME_TYPE_DISCRETE_TYPE */ + body_type = MAILMIME_SINGLE; + break; + } + + /* set body */ + + if (mime_fields != NULL) + encoding = mailmime_transfer_encoding_get(mime_fields); + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = * index; + body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, + message + cur_token, length - cur_token, + NULL); + if (body == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + + /* in case of composite, parse the sub-part(s) */ + + list = NULL; + msg_mime = NULL; + fields = NULL; + + switch (body_type) { + case MAILMIME_MESSAGE: + { + struct mailmime_fields * submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, + &cur_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_content; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + submime_fields = NULL; + r = mailmime_fields_parse(fields, &submime_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + remove_unparsed_mime_headers(fields); + + r = mailmime_parse_with_default(message, length, + &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + NULL, submime_fields, &msg_mime); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + msg_mime = NULL; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free_content; + } + } + + break; + + case MAILMIME_MULTIPLE: + { + int default_subtype; + + default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; + if (content_type != NULL) + if (strcasecmp(content_type->ct_subtype, "digest") == 0) + default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; + + cur_token = * index; + r = mailmime_multipart_body_parse(message, length, + &cur_token, boundary, + default_subtype, + &list, &preamble, &epilogue); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + } + else { + res = r; + goto free_content; + } + + free(boundary); + } + break; + + default: /* MAILMIME_SINGLE */ + /* do nothing */ + break; + } + + mime = mailmime_new(body_type, message, length, + mime_fields, content_type, + body, preamble, /* preamble */ + epilogue, /* epilogue */ + list, fields, msg_mime); + if (mime == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime; + * index = length; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + if (msg_mime != NULL) + mailmime_free(msg_mime); + if (list != NULL) { + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + } + free_content: + mailmime_content_free(content_type); + err: + return res; +} + +static int mailmime_get_section_list(struct mailmime * mime, + clistiter * list, struct mailmime ** result) +{ + uint32_t id; + struct mailmime * data; + struct mailmime * submime; + + if (list == NULL) { + * result = mime; + return MAILIMF_NO_ERROR; + } + + id = * ((uint32_t *) clist_content(list)); + + data = NULL; + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAILIMF_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + if (clist_next(list) != NULL) + return mailmime_get_section_list(data, clist_next(list), result); + else { + * result = data; + return MAILIMF_NO_ERROR; + } + + case MAILMIME_MESSAGE: + submime = mime->mm_data.mm_message.mm_msg_mime; + switch (submime->mm_type) { + case MAILMIME_MULTIPLE: + data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + return mailmime_get_section_list(data, clist_next(list), result); + + default: + if (id != 1) + return MAILIMF_ERROR_INVAL; + + data = submime; + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + return mailmime_get_section_list(data, clist_next(list), result); + } + break; + + default: + return MAILIMF_ERROR_INVAL; + } +} + +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result) +{ + return mailmime_get_section_list(mime, + clist_begin(section->sec_list), result); +} + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* MIME part decoding */ + +static inline signed char get_base64_value(char ch) +{ + if ((ch >= 'A') && (ch <= 'Z')) + return ch - 'A'; + if ((ch >= 'a') && (ch <= 'z')) + return ch - 'a' + 26; + if ((ch >= '0') && (ch <= '9')) + return ch - '0' + 52; + switch (ch) { + case '+': + return 62; + case '/': + return 63; + case '=': /* base64 padding */ + return -1; + default: + return -1; + } +} + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + size_t cur_token; + size_t i; + char chunk[4]; + int chunk_index; + char out[3]; + MMAPString * mmapstr; + int res; + int r; + size_t written; + + cur_token = * index; + chunk_index = 0; + written = 0; + + mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + i = 0; + while (1) { + signed char value; + + value = -1; + while (value == -1) { + + if (cur_token >= length) + break; + + value = get_base64_value(message[cur_token]); + cur_token ++; + } + + if (value == -1) + break; + + chunk[chunk_index] = value; + chunk_index ++; + + if (chunk_index == 4) { + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + out[2] = (chunk[2] << 6) | (chunk[3]); + + chunk[0] = 0; + chunk[1] = 0; + chunk[2] = 0; + chunk[3] = 0; + + chunk_index = 0; + + if (mmap_string_append_len(mmapstr, out, 3) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += 3; + } + } + + if (chunk_index != 0) { + size_t len; + + len = 0; + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + len ++; + + if (chunk_index >= 3) { + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + len ++; + } + + if (mmap_string_append_len(mmapstr, out, len) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += len; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + + +static inline int hexa_to_char(char hexdigit) +{ + if ((hexdigit >= '0') && (hexdigit <= '9')) + return hexdigit - '0'; + if ((hexdigit >= 'a') && (hexdigit <= 'f')) + return hexdigit - 'a' + 10; + if ((hexdigit >= 'A') && (hexdigit <= 'F')) + return hexdigit - 'A' + 10; + return 0; +} + +static inline char to_char(const char * hexa) +{ + return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]); +} + +enum { + STATE_NORMAL, + STATE_CODED, + STATE_OUT, + STATE_CR, +}; + + +static int write_decoded_qp(MMAPString * mmapstr, + const char * start, size_t count) +{ + if (mmap_string_append_len(mmapstr, start, count) == NULL) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + + +#define WRITE_MAX_QP 512 + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header) +{ + size_t cur_token; + int state; + int r; + char ch; + size_t count; + const char * start; + MMAPString * mmapstr; + int res; + size_t written; + + state = STATE_NORMAL; + cur_token = * index; + + count = 0; + start = message + cur_token; + written = 0; + + mmapstr = mmap_string_sized_new(length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') { + length --; + } + } + } +#endif + + while (state != STATE_OUT) { + + if (cur_token >= length) { + state = STATE_OUT; + break; + } + + switch (state) { + + case STATE_CODED: + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + switch (message[cur_token]) { + case '=': + if (cur_token + 1 >= length) { + /* error but ignore it */ + state = STATE_NORMAL; + start = message + cur_token; + cur_token ++; + count ++; + break; + } + + switch (message[cur_token + 1]) { + + case '\n': + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + + case '\r': + if (cur_token + 2 >= length) { + state = STATE_OUT; + break; + } + + if (message[cur_token + 2] == '\n') + cur_token += 3; + else + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + + break; + + default: + if (cur_token + 2 >= length) { + /* error but ignore it */ + cur_token ++; + + start = message + cur_token; + + count ++; + state = STATE_NORMAL; + break; + } + +#if 0 + /* flush before writing additionnal information */ + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; +#endif + + ch = to_char(message + cur_token + 1); + + if (mmap_string_append_c(mmapstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + cur_token += 3; + written ++; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + } + break; + } + break; /* end of STATE_ENCODED */ + + case STATE_NORMAL: + + switch (message[cur_token]) { + + case '=': + state = STATE_CODED; + break; + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + break; + + case '\r': + state = STATE_CR; + cur_token ++; + break; + + case '_': + if (in_header) { + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + if (mmap_string_append_c(mmapstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + written ++; + cur_token ++; + start = message + cur_token; + + break; + } + /* WARINING : must be followed by switch default action */ + + default: + if (count >= WRITE_MAX_QP) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + start = message + cur_token; + } + + count ++; + cur_token ++; + break; + } + break; /* end of STATE_NORMAL */ + + case STATE_CR: + switch (message[cur_token]) { + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + state = STATE_NORMAL; + break; + + default: + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + start = message + cur_token; + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + state = STATE_NORMAL; + } + break; /* end of STATE_CR */ + } + } + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') + length --; + } + } + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = length; + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len) +{ + switch (encoding) { + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_body_parse(message, length, index, + result, result_len); + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_body_parse(message, length, index, + result, result_len, FALSE); + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailmime_binary_body_parse(message, length, index, + result, result_len); + } +} + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result) +{ + clist * list; + int res; + struct mailmime_section * section_id; + int r; + + if (mime->mm_parent == NULL) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + section_id = mailmime_section_new(list); + if (section_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else { + uint32_t id; + uint32_t * p_id; + clistiter * cur; + struct mailmime * parent; + + r = mailmime_get_section_id(mime->mm_parent, §ion_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + parent = mime->mm_parent; + switch (parent->mm_type) { + case MAILMIME_MULTIPLE: + id = 1; + for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + if (clist_content(cur) == mime) + break; + id ++; + } + + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = id; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + break; + + case MAILMIME_MESSAGE: + if ((mime->mm_type == MAILMIME_SINGLE) || + (mime->mm_type == MAILMIME_MESSAGE)) { + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = 1; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + } + + * result = section_id; + + return MAILIMF_NO_ERROR; + + free: + mailmime_section_free(section_id); + err: + return res; +} diff --git a/kmicromail/libetpan/mime/mailmime_content.h b/kmicromail/libetpan/mime/mailmime_content.h new file mode 100644 index 0000000..df4b232 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.h @@ -0,0 +1,89 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_decode.c b/kmicromail/libetpan/mime/mailmime_decode.c new file mode 100644 index 0000000..3025dcb --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.c @@ -0,0 +1,533 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* + RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: + Message Header Extensions for Non-ASCII Text +*/ + +#include "mailmime_decode.h" + +#include +#include +#include +#include +#include + +#include "mailmime_content.h" + +#include "charconv.h" +#include "mmapstring.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset); + +enum { + MAILMIME_ENCODING_B, + MAILMIME_ENCODING_Q +}; + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int +mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result); + + +enum { + TYPE_ERROR, + TYPE_WORD, + TYPE_ENCODED_WORD, +}; + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result) +{ + MMAPString * gphrase; + struct mailmime_encoded_word * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + char * wordutf8; + int type; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + type = TYPE_ERROR; /* XXX - removes a gcc warning */ + + while (1) { + + r = mailmime_encoded_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (type != TYPE_ENCODED_WORD) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + type = TYPE_ENCODED_WORD; + wordutf8 = NULL; + r = charconv(tocode, word->wd_charset, word->wd_text, + strlen(word->wd_text), &wordutf8); + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + case MAIL_CHARCONV_ERROR_CONV: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + mailmime_encoded_word_free(word); + free(wordutf8); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + free(wordutf8); + } + mailmime_encoded_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) { + char * raw_word; + + r = mailmime_non_encoded_word_parse(message, length, + &cur_token, &raw_word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + type = TYPE_WORD; + + wordutf8 = NULL; + r = charconv(tocode, default_fromcode, raw_word, + strlen(raw_word), &wordutf8); + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + free(wordutf8); + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + free(wordutf8); + } + free(raw_word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int end; + size_t cur_token; + int res; + char * text; + int r; + size_t begin; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + begin = cur_token; + + end = FALSE; + while (1) { + if (cur_token >= length) + break; + + switch (message[cur_token]) { + case ' ': + case '\t': + case '\r': + case '\n': + end = TRUE; + break; + } + + if (end) + break; + + cur_token ++; + } + + if (cur_token - begin == 0) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + text = malloc(cur_token - begin + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + memcpy(text, message + begin, cur_token - begin); + text[cur_token - begin] = '\0'; + + * index = cur_token; + * result = text; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +static int mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result) +{ + size_t cur_token; + char * charset; + int encoding; + char * text; + size_t end_encoding; + char * decoded; + size_t decoded_len; + struct mailmime_encoded_word * ew; + int r; + int res; + int opening_quote; + int end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + opening_quote = FALSE; + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if (r == MAILIMF_NO_ERROR) { + opening_quote = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailmime_charset_parse(message, length, &cur_token, &charset); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailmime_encoding_parse(message, length, &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + end = FALSE; + end_encoding = cur_token; + while (1) { + if (end_encoding >= length) + break; + + switch (message[end_encoding]) { + case '?': +#if 0 + case ' ': +#endif + end = TRUE; + break; + } + + if (end) + break; + + end_encoding ++; + } + + decoded_len = 0; + decoded = NULL; + switch (encoding) { + case MAILMIME_ENCODING_B: + r = mailmime_base64_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + break; + case MAILMIME_ENCODING_Q: + r = mailmime_quoted_printable_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len, TRUE); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + break; + } + + text = malloc(decoded_len + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_charset; + } + + if (decoded_len > 0) + memcpy(text, decoded, decoded_len); + text[decoded_len] = '\0'; + + mailmime_decoded_part_free(decoded); + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?="); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_encoded_text; + } + + if (opening_quote) { + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_encoded_text; + } + } + + ew = mailmime_encoded_word_new(charset, text); + if (ew == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_encoded_text; + } + + * result = ew; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_encoded_text: + mailmime_encoded_text_free(text); + free_charset: + mailmime_charset_free(charset); + err: + return res; +} + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset) +{ + return mailmime_etoken_parse(message, length, index, charset); +} + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int encoding; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch ((char) toupper((unsigned char) message[cur_token])) { + case 'Q': + encoding = MAILMIME_ENCODING_Q; + break; + case 'B': + encoding = MAILMIME_ENCODING_B; + break; + default: + return MAILIMF_ERROR_INVAL; + } + + cur_token ++; + + * result = encoding; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int is_etoken_char(char ch) +{ + unsigned char uch = ch; + + if (uch < 31) + return FALSE; + + switch (uch) { + case ' ': + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '"': + case '/': + case '[': + case ']': + case '?': + case '.': + case '=': + return FALSE; + } + + return TRUE; +} + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_etoken_char); +} diff --git a/kmicromail/libetpan/mime/mailmime_decode.h b/kmicromail/libetpan/mime/mailmime_decode.h new file mode 100644 index 0000000..034db6f --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_disposition.c b/kmicromail/libetpan/mime/mailmime_disposition.c new file mode 100644 index 0000000..9d8dfec --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.c @@ -0,0 +1,595 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime_disposition.h" +#include "mailmime.h" + +#include +#include + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result); + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result); + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* + disposition := "Content-Disposition" ":" + disposition-type + *(";" disposition-parm) + +*/ + + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result) +{ + size_t final_token; + size_t cur_token; + struct mailmime_disposition_type * dsp_type; + clist * list; + struct mailmime_disposition * dsp; + int r; + int res; + + cur_token = * index; + + r = mailmime_disposition_type_parse(message, length, &cur_token, + &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + struct mailmime_disposition_parm * param; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free_list; + } + + r = mailmime_disposition_parm_parse(message, length, &cur_token, ¶m); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto free_list; + } + + r = clist_append(list, param); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + if (dsp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +/* + disposition-type := "inline" + / "attachment" + / extension-token + ; values are not case-sensitive + +*/ + + + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result) +{ + size_t cur_token; + int type; + char * extension; + struct mailmime_disposition_type * dsp_type; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */ + + extension = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "inline"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_INLINE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "attachment"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, &cur_token, + &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + dsp_type = mailmime_disposition_type_new(type, extension); + if (dsp_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (extension != NULL) + free(extension); + err: + return res; +} + +/* + disposition-parm := filename-parm + / creation-date-parm + / modification-date-parm + / read-date-parm + / size-parm + / parameter +*/ + + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index) +{ + if (index >= length) + return MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch ((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILMIME_DISPOSITION_PARM_FILENAME; + case 'C': + return MAILMIME_DISPOSITION_PARM_CREATION_DATE; + case 'M': + return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE; + case 'R': + return MAILMIME_DISPOSITION_PARM_READ_DATE; + case 'S': + return MAILMIME_DISPOSITION_PARM_SIZE; + default: + return MAILMIME_DISPOSITION_PARM_PARAMETER; + } +} + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result) +{ + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + struct mailmime_parameter * parameter; + size_t cur_token; + struct mailmime_disposition_parm * dsp_parm; + int type; + int guessed_type; + int r; + int res; + + cur_token = * index; + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + parameter = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + guessed_type = mailmime_disposition_guess_type(message, length, cur_token); + + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch (guessed_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailmime_filename_parm_parse(message, length, &cur_token, + &filename); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailmime_creation_date_parm_parse(message, length, &cur_token, + &creation_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailmime_modification_date_parm_parse(message, length, &cur_token, + &modification_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailmime_read_date_parm_parse(message, length, &cur_token, + &read_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailmime_size_parm_parse(message, length, &cur_token, + &size); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + r = mailmime_parameter_parse(message, length, &cur_token, + ¶meter); + if (r != MAILIMF_NO_ERROR) { + type = guessed_type; + res = r; + goto err; + } + } + + dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date, + modification_date, read_date, + size, parameter); + + if (dsp_parm == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_parm; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (filename != NULL) + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + if (creation_date != NULL) + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + if (modification_date != NULL) + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + if (read_date != NULL) + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + if (parameter != NULL) + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + err: + return res; +} + +/* + filename-parm := "filename" "=" value +*/ + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "filename"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + creation-date-parm := "creation-date" "=" quoted-date-time +*/ + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "creation-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + modification-date-parm := "modification-date" "=" quoted-date-time +*/ + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "modification-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + read-date-parm := "read-date" "=" quoted-date-time +*/ + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "read-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + size-parm := "size" "=" 1*DIGIT +*/ + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result) +{ + uint32_t value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "size"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + quoted-date-time := quoted-string + ; contents MUST be an RFC 822 `date-time' + ; numeric timezones (+HHMM or -HHMM) MUST be used +*/ + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_quoted_string_parse(message, length, index, result); +} diff --git a/kmicromail/libetpan/mime/mailmime_disposition.h b/kmicromail/libetpan/mime/mailmime_disposition.h new file mode 100644 index 0000000..e3bba15 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_types.c b/kmicromail/libetpan/mime/mailmime_types.c new file mode 100644 index 0000000..a81c87a --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.c @@ -0,0 +1,750 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime_types.h" +#include "mmapstring.h" + +#include +#include + +void mailmime_attribute_free(char * attribute) +{ + mailmime_token_free(attribute); +} + + + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token) +{ + struct mailmime_composite_type * ct; + + ct = malloc(sizeof(* ct)); + if (ct == NULL) + return NULL; + + ct->ct_type = ct_type; + ct->ct_token = ct_token; + + return ct; +} + +void mailmime_composite_type_free(struct mailmime_composite_type * ct) +{ + if (ct->ct_token != NULL) + mailmime_extension_token_free(ct->ct_token); + free(ct); +} + + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters) +{ + struct mailmime_content * content; + + content = malloc(sizeof(* content)); + if (content == NULL) + return NULL; + + content->ct_type = ct_type; + content->ct_subtype = ct_subtype; + content->ct_parameters = ct_parameters; + + return content; +} + +void mailmime_content_free(struct mailmime_content * content) +{ + mailmime_type_free(content->ct_type); + mailmime_subtype_free(content->ct_subtype); + if (content->ct_parameters != NULL) { + clist_foreach(content->ct_parameters, + (clist_func) mailmime_parameter_free, NULL); + clist_free(content->ct_parameters); + } + + free(content); +} + + +void mailmime_description_free(char * description) +{ + free(description); +} + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = malloc(sizeof(* discrete_type)); + if (discrete_type == NULL) + return NULL; + + discrete_type->dt_type = dt_type; + discrete_type->dt_extension = dt_extension; + + return discrete_type; +} + +void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type) +{ + if (discrete_type->dt_extension != NULL) + mailmime_extension_token_free(discrete_type->dt_extension); + free(discrete_type); +} + +void mailmime_encoding_free(struct mailmime_mechanism * encoding) +{ + mailmime_mechanism_free(encoding); +} + +void mailmime_extension_token_free(char * extension) +{ + mailmime_token_free(extension); +} + +void mailmime_id_free(char * id) +{ + mailimf_msg_id_free(id); +} + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token) +{ + struct mailmime_mechanism * mechanism; + + mechanism = malloc(sizeof(* mechanism)); + if (mechanism == NULL) + return NULL; + + mechanism->enc_type = enc_type; + mechanism->enc_token = enc_token; + + return mechanism; +} + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism) +{ + if (mechanism->enc_token != NULL) + mailmime_token_free(mechanism->enc_token); + free(mechanism); +} + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value) +{ + struct mailmime_parameter * parameter; + + parameter = malloc(sizeof(* parameter)); + if (parameter == NULL) + return NULL; + + parameter->pa_name = pa_name; + parameter->pa_value = pa_value; + + return parameter; +} + +void mailmime_parameter_free(struct mailmime_parameter * parameter) +{ + mailmime_attribute_free(parameter->pa_name); + mailmime_value_free(parameter->pa_value); + free(parameter); +} + + +void mailmime_subtype_free(char * subtype) +{ + mailmime_extension_token_free(subtype); +} + + +void mailmime_token_free(char * token) +{ + free(token); +} + + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type) +{ + struct mailmime_type * mime_type; + + mime_type = malloc(sizeof(* mime_type)); + if (mime_type == NULL) + return NULL; + + mime_type->tp_type = tp_type; + switch (tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type->tp_data.tp_discrete_type = tp_discrete_type; + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mime_type->tp_data.tp_composite_type = tp_composite_type; + break; + } + + return mime_type; +} + +void mailmime_type_free(struct mailmime_type * type) +{ + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mailmime_discrete_type_free(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mailmime_composite_type_free(type->tp_data.tp_composite_type); + break; + } + free(type); +} + +void mailmime_value_free(char * value) +{ + free(value); +} + + +/* +void mailmime_x_token_free(gchar * x_token) +{ + g_free(x_token); +} +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language) +{ + struct mailmime_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + field->fld_type = fld_type; + + switch (fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = fld_content; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = fld_encoding; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = fld_id; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = fld_description; + break; + case MAILMIME_FIELD_VERSION: + field->fld_data.fld_version = fld_version; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = fld_disposition; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = fld_language; + break; + } + return field; +} + +void mailmime_field_free(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + if (field->fld_data.fld_content != NULL) + mailmime_content_free(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (field->fld_data.fld_encoding != NULL) + mailmime_encoding_free(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + if (field->fld_data.fld_id != NULL) + mailmime_id_free(field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + if (field->fld_data.fld_description != NULL) + mailmime_description_free(field->fld_data.fld_description); + break; + case MAILMIME_FIELD_DISPOSITION: + if (field->fld_data.fld_disposition != NULL) + mailmime_disposition_free(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + if (field->fld_data.fld_language != NULL) + mailmime_language_free(field->fld_data.fld_language); + break; + } + + free(field); +} + +struct mailmime_fields * mailmime_fields_new(clist * fld_list) +{ + struct mailmime_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailmime_fields_free(struct mailmime_fields * fields) +{ + clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL); + clist_free(fields->fld_list); + free(fields); +} + + +/* +struct mailmime_body_part * +mailmime_body_part_new(gchar * text, guint32 size) +{ + struct mailmime_body_part * body_part; + + body_part = g_new(struct mailmime_body_part, 1); + if (body_part == NULL) + return NULL; + + body_part->text = text; + body_part->size = size; + + return body_part; +} + +void mailmime_body_part_free(struct mailmime_body_part * body_part) +{ + g_free(body_part); +} +*/ + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list) +{ + struct mailmime_multipart_body * mp_body; + + mp_body = malloc(sizeof(* mp_body)); + if (mp_body == NULL) + return NULL; + + mp_body->bd_list = bd_list; + + return mp_body; +} + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body) +{ + clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL); + clist_free(mp_body->bd_list); + free(mp_body); +} + + + + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime) +{ + struct mailmime * mime; + clistiter * cur; + + mime = malloc(sizeof(* mime)); + if (mime == NULL) + return NULL; + + mime->mm_parent = NULL; + mime->mm_parent_type = MAILMIME_NONE; + mime->mm_multipart_pos = NULL; + + mime->mm_type = mm_type; + mime->mm_mime_start = mm_mime_start; + mime->mm_length = mm_length; + mime->mm_mime_fields = mm_mime_fields; + mime->mm_content_type = mm_content_type; + + mime->mm_body = mm_body; + + switch (mm_type) { + case MAILMIME_SINGLE: + mime->mm_data.mm_single = mm_body; + break; + + case MAILMIME_MULTIPLE: + mime->mm_data.mm_multipart.mm_preamble = mm_preamble; + mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue; + mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list; + + for(cur = clist_begin(mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + submime->mm_parent = mime; + submime->mm_parent_type = MAILMIME_MULTIPLE; + submime->mm_multipart_pos = cur; + } + break; + + case MAILMIME_MESSAGE: + mime->mm_data.mm_message.mm_fields = mm_fields; + mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime; + if (mm_msg_mime != NULL) { + mm_msg_mime->mm_parent = mime; + mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE; + } + break; + + } + + return mime; +} + +void mailmime_free(struct mailmime * mime) +{ + if (mime->mm_body != NULL) + mailmime_data_free(mime->mm_body); + switch (mime->mm_type) { + case MAILMIME_SINGLE: + /* do nothing */ + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble); + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue); + clist_foreach(mime->mm_data.mm_multipart.mm_mp_list, + (clist_func) mailmime_free, NULL); + clist_free(mime->mm_data.mm_multipart.mm_mp_list); + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields != NULL) + mailimf_fields_free(mime->mm_data.mm_message.mm_fields); + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + mailmime_free(mime->mm_data.mm_message.mm_msg_mime); + break; + + } + if (mime->mm_mime_fields != NULL) + mailmime_fields_free(mime->mm_mime_fields); + if (mime->mm_content_type != NULL) + mailmime_content_free(mime->mm_content_type); + free(mime); +} + + + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text) +{ + struct mailmime_encoded_word * ew; + + ew = malloc(sizeof(* ew)); + if (ew == NULL) + return NULL; + ew->wd_charset = wd_charset; + ew->wd_text = wd_text; + + return ew; +} + +void mailmime_charset_free(char * charset) +{ + free(charset); +} + +void mailmime_encoded_text_free(char * text) +{ + free(text); +} + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew) +{ + mailmime_charset_free(ew->wd_charset); + mailmime_encoded_text_free(ew->wd_text); + free(ew); +} + + + +/* mailmime_disposition */ + + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms) +{ + struct mailmime_disposition * dsp; + + dsp = malloc(sizeof(* dsp)); + if (dsp == NULL) + return NULL; + dsp->dsp_type = dsp_type; + dsp->dsp_parms = dsp_parms; + + return dsp; +} + +void mailmime_disposition_free(struct mailmime_disposition * dsp) +{ + mailmime_disposition_type_free(dsp->dsp_type); + clist_foreach(dsp->dsp_parms, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(dsp->dsp_parms); + free(dsp); +} + + + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dsp_type, char * dsp_extension) +{ + struct mailmime_disposition_type * m_dsp_type; + + m_dsp_type = malloc(sizeof(* m_dsp_type)); + if (m_dsp_type == NULL) + return NULL; + + m_dsp_type->dsp_type = dsp_type; + m_dsp_type->dsp_extension = dsp_extension; + + return m_dsp_type; +} + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type) +{ + if (dsp_type->dsp_extension != NULL) + free(dsp_type->dsp_extension); + free(dsp_type); +} + + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter) +{ + struct mailmime_disposition_parm * dsp_parm; + + dsp_parm = malloc(sizeof(* dsp_parm)); + if (dsp_parm == NULL) + return NULL; + + dsp_parm->pa_type = pa_type; + switch (pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + dsp_parm->pa_data.pa_filename = pa_filename; + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + dsp_parm->pa_data.pa_creation_date = pa_creation_date; + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + dsp_parm->pa_data.pa_modification_date = pa_modification_date; + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + dsp_parm->pa_data.pa_read_date = pa_read_date; + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + dsp_parm->pa_data.pa_size = pa_size; + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + dsp_parm->pa_data.pa_parameter = pa_parameter; + break; + } + + return dsp_parm; +} + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm) +{ + switch (dsp_parm->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + break; + } + + free(dsp_parm); +} + + +void mailmime_filename_parm_free(char * filename) +{ + mailmime_value_free(filename); +} + +void mailmime_creation_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_modification_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_read_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_quoted_date_time_free(char * date) +{ + mailimf_quoted_string_free(date); +} + +struct mailmime_section * mailmime_section_new(clist * sec_list) +{ + struct mailmime_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_list = sec_list; + + return section; +} + +void mailmime_section_free(struct mailmime_section * section) +{ + clist_foreach(section->sec_list, (clist_func) free, NULL); + clist_free(section->sec_list); + free(section); +} + + + +struct mailmime_language * mailmime_language_new(clist * lg_list) +{ + struct mailmime_language * lang; + + lang = malloc(sizeof(* lang)); + if (lang == NULL) + return NULL; + + lang->lg_list = lg_list; + + return lang; +} + +void mailmime_language_free(struct mailmime_language * lang) +{ + clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL); + clist_free(lang->lg_list); + free(lang); +} + +void mailmime_decoded_part_free(char * part) +{ + mmap_string_unref(part); +} + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename) +{ + struct mailmime_data * mime_data; + + mime_data = malloc(sizeof(* mime_data)); + if (mime_data == NULL) + return NULL; + + mime_data->dt_type = dt_type; + mime_data->dt_encoding = dt_encoding; + mime_data->dt_encoded = dt_encoded; + switch (dt_type) { + case MAILMIME_DATA_TEXT: + mime_data->dt_data.dt_text.dt_data = dt_data; + mime_data->dt_data.dt_text.dt_length = dt_length; + break; + case MAILMIME_DATA_FILE: + mime_data->dt_data.dt_filename = dt_filename; + break; + } + + return mime_data; +} + +void mailmime_data_free(struct mailmime_data * mime_data) +{ + switch (mime_data->dt_type) { + case MAILMIME_DATA_FILE: + free(mime_data->dt_data.dt_filename); + break; + } + free(mime_data); +} diff --git a/kmicromail/libetpan/mime/mailmime_types.h b/kmicromail/libetpan/mime/mailmime_types.h new file mode 100644 index 0000000..3bb3b10 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.h @@ -0,0 +1,440 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +void mailmime_attribute_free(char * attribute); + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + +void mailmime_description_free(char * description); + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +void mailmime_extension_token_free(char * extension); + +void mailmime_id_free(char * id); + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +void mailmime_subtype_free(char * subtype); + +void mailmime_token_free(char * token); + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +void mailmime_charset_free(char * charset); + +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +void mailmime_filename_parm_free(char * filename); + +void mailmime_creation_date_parm_free(char * date); + +void mailmime_modification_date_parm_free(char * date); + +void mailmime_read_date_parm_free(char * date); + +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +struct mailmime_section * mailmime_section_new(clist * list); + +void mailmime_section_free(struct mailmime_section * section); + + +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.c b/kmicromail/libetpan/mime/mailmime_types_helper.c new file mode 100644 index 0000000..83fa1d4 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.c @@ -0,0 +1,1385 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime_types_helper.h" +#include "clist.h" + +#include "mailmime.h" + +#include +#include +#include +#include +#include + +#define MIME_VERSION (1 << 16) + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) + return field->fld_data.fld_encoding->enc_type; + } + + return MAILMIME_MECHANISM_8BIT; +} + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename) +{ + return mailmime_disposition_new_with_data(type, filename, + NULL, NULL, NULL, (size_t) -1); + +} + +struct mailmime_fields * mailmime_fields_new_empty(void) +{ + clist * list; + struct mailmime_fields * fields; + + list = clist_new(); + if (list == NULL) + goto err; + + fields = mailmime_fields_new(list); + if (fields == NULL) + goto free; + + return fields; + + free: + clist_free(list); + err: + return NULL; +} + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void mailmime_field_detach(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = NULL; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = NULL; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = NULL; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = NULL; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = NULL; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = NULL; + break; + } +} + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_empty(); + if (fields == NULL) + goto err; + +#if 0 + if (content != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TYPE, + content, NULL, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } +#endif + + if (encoding != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (id != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_ID, + NULL, NULL, id, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (description != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION, + NULL, NULL, NULL, description, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (disposition != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (language != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, NULL, language); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_with_data(encoding, id, description, + disposition, language); + if (fields == NULL) + goto err; + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + + +struct mailmime_content * mailmime_get_content_message(void) +{ + clist * list; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) + goto free_composite; + composite_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_mime_type; + + subtype = strdup("rfc822"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_mime_type: + mailmime_type_free(mime_type); + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return NULL; +} + +struct mailmime_content * mailmime_get_content_text(void) +{ + clist * list; + struct mailmime_discrete_type * discrete_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) + goto free_discrete; + discrete_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_type; + + subtype = strdup("plain"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_type: + mailmime_type_free(mime_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + + + + + + + + +/* mailmime build */ + + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 1, NULL, 0, filename); + if (msg_content == NULL) + goto free_fields; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_fields; + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 1, data_str, length, NULL); + if (msg_content == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, + NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, NULL, + NULL, msg_mime); + if (build_info == NULL) + goto free_fields; + + return build_info; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +#define MAX_MESSAGE_ID 512 + +static char * generate_boundary() +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "%lx_%lx_%x", now, value, getpid()); + + return strdup(id); +} + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields) +{ + struct mailmime * build_info; + clist * list; + int r; + int mime_type; + + list = NULL; + + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + goto err; + } + break; + + default: + goto err; + } + + if (mime_type == MAILMIME_MULTIPLE) { + char * attr_name; + char * attr_value; + struct mailmime_parameter * param; + clist * parameters; + char * boundary; + + list = clist_new(); + if (list == NULL) + goto err; + + attr_name = strdup("boundary"); + if (attr_name == NULL) + goto free_list; + + boundary = generate_boundary(); + attr_value = boundary; + if (attr_name == NULL) { + free(attr_name); + goto free_list; + } + + param = mailmime_parameter_new(attr_name, attr_value); + if (param == NULL) { + free(attr_value); + free(attr_name); + goto free_list; + } + + if (content->ct_parameters == NULL) { + parameters = clist_new(); + if (parameters == NULL) { + mailmime_parameter_free(param); + goto free_list; + } + } + else + parameters = content->ct_parameters; + + r = clist_append(parameters, param); + if (r != 0) { + clist_free(parameters); + mailmime_parameter_free(param); + goto free_list; + } + + if (content->ct_parameters == NULL) + content->ct_parameters = parameters; + } + + build_info = mailmime_new(mime_type, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, list, + NULL, NULL); + if (build_info == NULL) { + clist_free(list); + return NULL; + } + + return build_info; + + free_list: + clist_free(list); + err: + return NULL; +} + + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + struct mailmime * build_info; +#if 0 + int mime_type; +#endif + int res; + + cur_token = 0; + r = mailmime_content_parse(content_type, strlen(content_type), + &cur_token, + &content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + +#if 0 + switch (content->type->type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->type->composite_type->type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } +#endif + + build_info = mailmime_new_empty(content, mime_fields); + if (build_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = build_info; + + return MAILIMF_NO_ERROR; + + free: + mailmime_content_free(content); + err: + return res; +} + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_FILE, encoding, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + + +/* add a part as subpart of a mime part */ + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part) +{ + int r; + + if (build_info->mm_type == MAILMIME_MESSAGE) { + build_info->mm_data.mm_message.mm_msg_mime = part; + part->mm_parent_type = MAILMIME_MESSAGE; + part->mm_parent = build_info; + } + else if (build_info->mm_type == MAILMIME_MULTIPLE) { + r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part); + if (r != 0) + return MAILIMF_ERROR_MEMORY; + + part->mm_parent_type = MAILMIME_MULTIPLE; + part->mm_parent = build_info; + part->mm_multipart_pos = + clist_end(build_info->mm_data.mm_multipart.mm_mp_list); + } + else { + return MAILIMF_ERROR_INVAL; + } + return MAILIMF_NO_ERROR; +} + +/* detach part from parent */ + +void mailmime_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + + parent = mime->mm_parent; + if (parent == NULL) + return; + + switch (mime->mm_parent_type) { + case MAILMIME_MESSAGE: + mime->mm_parent = NULL; + parent->mm_data.mm_message.mm_msg_mime = NULL; + break; + + case MAILMIME_MULTIPLE: + mime->mm_parent = NULL; + clist_delete(parent->mm_data.mm_multipart.mm_mp_list, + mime->mm_multipart_pos); + break; + } +} + + +/* + attach a part to a mime part and create multipart/mixed + when needed, when the parent part has already some part + attached to it. +*/ + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub) +{ + struct mailmime * saved_sub; + struct mailmime * mp; + int res; + int r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + res = MAILIMF_ERROR_INVAL; + goto err; + + case MAILMIME_MULTIPLE: + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + /* MAILMIME_MESSAGE */ + + if (mime->mm_data.mm_message.mm_msg_mime == NULL) { + /* there is no subpart, we can simply attach it */ + + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) { + /* in case the subpart is multipart, simply attach it to the subpart */ + + return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); + } + + /* we save the current subpart, ... */ + + saved_sub = mime->mm_data.mm_message.mm_msg_mime; + + /* create a multipart */ + + mp = mailmime_multiple_new("multipart/mixed"); + if (mp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + /* detach the saved subpart from the parent */ + + mailmime_remove_part(saved_sub); + + /* the created multipart is the new child of the parent */ + + r = mailmime_add_part(mime, mp); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_mp; + } + + /* then, attach the saved subpart and ... */ + + r = mailmime_add_part(mp, saved_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + /* the given part to the parent */ + + r = mailmime_add_part(mp, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + return MAILIMF_NO_ERROR; + + free_mp: + mailmime_free(mp); + free_saved_sub: + mailmime_free(saved_sub); + err: + return res; +} + + + +/* detach part from parent and free it only if the part has no child */ + +int mailmime_smart_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + int res; + + parent = mime->mm_parent; + if (parent == NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + switch (mime->mm_type) { + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_MULTIPLE: + if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_SINGLE: + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + default: + return MAILIMF_ERROR_INVAL; + } + + err: + return res; +} + + +/* create a mailmime_content structure (Content-Type field) */ + +struct mailmime_content * mailmime_content_new_with_str(const char * str) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + + cur_token = 0; + r = mailmime_content_parse(str, strlen(str), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} + +/* create MIME fields with only the field Content-Transfer-Encoding */ + +struct mailmime_fields * mailmime_fields_new_encoding(int type) +{ + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + encoding = mailmime_mechanism_new(type, NULL); + if (encoding == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) + goto free; + + return mime_fields; + + free: + mailmime_mechanism_free(encoding); + err: + return NULL; +} + + +/* create a multipart MIME part */ + +struct mailmime * mailmime_multiple_new(const char * type) +{ + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + struct mailmime * mp; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) + goto err; + + content = mailmime_content_new_with_str(type); + if (content == NULL) + goto free_fields; + + mp = mailmime_new_empty(content, mime_fields); + if (mp == NULL) + goto free_content; + + return mp; + + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * mm_fields) +{ + build_info->mm_data.mm_message.mm_fields = mm_fields; +} + +#if 0 +struct mailmime_content * mailmime_get_content(char * mime_type) +{ + struct mailmime_content *content; + int r; + size_t cur_token; + + cur_token = 0; + r = mailmime_content_parse(mime_type, strlen(mime_type), + &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} +#endif + + + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size) +{ + struct mailmime_disposition_type * dsp_type; + clist * list; + int r; + struct mailmime_disposition_parm * parm; + struct mailmime_disposition * dsp; + + dsp_type = mailmime_disposition_type_new(type, NULL); + if (dsp_type == NULL) + goto err; + + list = clist_new(); + if (list == NULL) + goto free_dsp_type; + + if (filename != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + filename, NULL, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (creation_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE, + NULL, creation_date, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (modification_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + NULL, NULL, modification_date, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (read_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE, + NULL, NULL, NULL, read_date, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (size != (size_t) -1) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE, + NULL, NULL, NULL, NULL, size, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + + return dsp; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return NULL; +} + + +static void mailmime_disposition_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_disposition * fld_disposition) +{ + clistiter * cur; + + single_fields->fld_disposition = fld_disposition; + + for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = clist_content(cur); + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + single_fields->fld_disposition_filename = param->pa_data.pa_filename; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + single_fields->fld_disposition_creation_date = + param->pa_data.pa_creation_date; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + single_fields->fld_disposition_modification_date = + param->pa_data.pa_modification_date; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + single_fields->fld_disposition_read_date = + param->pa_data.pa_read_date; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + single_fields->fld_disposition_size = param->pa_data.pa_size; + break; + } + } +} + +static void mailmime_content_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + single_fields->fld_content = fld_content; + + for(cur = clist_begin(fld_content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, "boundary") == 0) + single_fields->fld_content_boundary = param->pa_value; + + if (strcasecmp(param->pa_name, "charset") == 0) + single_fields->fld_content_charset = param->pa_value; + + if (strcasecmp(param->pa_name, "name") == 0) + single_fields->fld_content_name = param->pa_value; + } +} + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailmime_single_fields)); + + if (fld_content != NULL) + mailmime_content_single_fields_init(single_fields, fld_content); + + if (fld_fields == NULL) + return; + + for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + mailmime_content_single_fields_init(single_fields, + field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + single_fields->fld_encoding = field->fld_data.fld_encoding; + break; + + case MAILMIME_FIELD_ID: + single_fields->fld_id = field->fld_data.fld_id; + break; + + case MAILMIME_FIELD_DESCRIPTION: + single_fields->fld_description = field->fld_data.fld_description; + break; + + case MAILMIME_FIELD_VERSION: + single_fields->fld_version = field->fld_data.fld_version; + break; + + case MAILMIME_FIELD_DISPOSITION: + mailmime_disposition_single_fields_init(single_fields, + field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + single_fields->fld_language = field->fld_data.fld_language; + break; + } + } +} + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + struct mailmime_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailmime_single_fields)); + if (single_fields == NULL) + goto err; + + mailmime_single_fields_init(single_fields, fld_fields, fld_content); + + return single_fields; + + err: + return NULL; +} + + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type) +{ + struct mailmime_disposition * dsp; + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + dsp = mailmime_disposition_new_with_data(dsp_type, + filename, NULL, NULL, NULL, (size_t) -1); + if (dsp == NULL) + goto err; + + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) + goto free_dsp; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, dsp, NULL); + if (mime_fields == NULL) + goto free_encoding; + + return mime_fields; + + free_encoding: + mailmime_encoding_free(encoding); + free_dsp: + mailmime_disposition_free(dsp); + err: + return NULL; +} + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length) +{ + return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL); +} + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename) +{ + return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename); +} + diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.h b/kmicromail/libetpan/mime/mailmime_types_helper.h new file mode 100644 index 0000000..608acca --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_content * mailmime_get_content_message(void); +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +struct mailmime * mailmime_multiple_new(const char * type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_write.c b/kmicromail/libetpan/mime/mailmime_write.c new file mode 100644 index 0000000..5c3b1f7 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.c @@ -0,0 +1,1416 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime_write.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mailimf_write.h" +#include "mailmime_content.h" +#include "mailmime_types_helper.h" + +#define MAX_MAIL_COL 78 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field); + +static int mailmime_id_write(FILE * f, int * col, char * id); + +static int mailmime_description_write(FILE * f, int * col, char * descr); + +static int mailmime_version_write(FILE * f, int * col, uint32_t version); + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding); + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language); + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition); + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param); + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param); + +/* +static int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); +*/ + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type); + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type); + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type); + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info); + + +/* ***** */ + +int mailmime_fields_write(FILE * f, int * col, struct mailmime_fields * fields) +{ + int r; + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + r = mailmime_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + r = mailmime_content_write(f, col, field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + r = mailmime_encoding_write(f, col, field->fld_data.fld_encoding); + break; + + case MAILMIME_FIELD_ID: + r = mailmime_id_write(f, col, field->fld_data.fld_id); + break; + + case MAILMIME_FIELD_DESCRIPTION: + r = mailmime_description_write(f, col, field->fld_data.fld_description); + break; + + case MAILMIME_FIELD_VERSION: + r = mailmime_version_write(f, col, field->fld_data.fld_version); + break; + + case MAILMIME_FIELD_DISPOSITION: + r = mailmime_disposition_write(f, col, field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + r = mailmime_language_write(f, col, field->fld_data.fld_language); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_id_write(FILE * f, int * col, char * id) +{ + int r; + + r = mailimf_string_write(f, col, "Content-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, id, strlen(id)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_description_write(FILE * f, int * col, char * descr) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Description: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, descr, strlen(descr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_version_write(FILE * f, int * col, uint32_t version) +{ + int r; + char versionstr[40]; + + r = mailimf_string_write(f, col, "MIME-Version: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); + + r = mailimf_string_write(f, col, versionstr, strlen(versionstr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Transfer-Encoding: ", 27); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + r = mailimf_string_write(f, col, "7bit", 4); + break; + + case MAILMIME_MECHANISM_8BIT: + r = mailimf_string_write(f, col, "8bit", 4); + break; + + case MAILMIME_MECHANISM_BINARY: + r = mailimf_string_write(f, col, "binary", 6); + break; + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + r = mailimf_string_write(f, col, "quoted-printable", 16); + break; + + case MAILMIME_MECHANISM_BASE64: + r = mailimf_string_write(f, col, "base64", 6); + break; + + case MAILMIME_MECHANISM_TOKEN: + r = mailimf_string_write(f, col, encoding->enc_token, + strlen(encoding->enc_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Content-Language: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * lang; + size_t len; + + lang = clist_content(cur); + len = strlen(lang); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailimf_string_write(f, col, lang, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition) +{ + struct mailmime_disposition_type * dsp_type; + int r; + clistiter * cur; + + dsp_type = disposition->dsp_type; + + r = mailimf_string_write(f, col, "Content-Disposition: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (dsp_type->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + r = mailimf_string_write(f, col, "inline", 6); + break; + + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + r = mailimf_string_write(f, col, "attachment", 10); + break; + + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + r = mailimf_string_write(f, col, dsp_type->dsp_extension, + strlen(dsp_type->dsp_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_disposition_param_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param) +{ + size_t len; + char sizestr[20]; + int r; + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + len = strlen("filename=") + strlen(param->pa_data.pa_filename); + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + len = strlen("modification-date=") + + strlen(param->pa_data.pa_modification_date); + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + snprintf(sizestr, 20, "%u", param->pa_data.pa_size); + len = strlen("size=") + strlen(sizestr); + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + + strlen(param->pa_data.pa_parameter->pa_value); + break; + + default: + return MAILIMF_ERROR_INVAL; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailimf_string_write(f, col, "filename=", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailimf_string_write(f, col, "creation-date=", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_creation_date, + strlen(param->pa_data.pa_creation_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailimf_string_write(f, col, "modification-date=", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_modification_date, + strlen(param->pa_data.pa_modification_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailimf_string_write(f, col, "read-date=", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_read_date, + strlen(param->pa_data.pa_read_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailimf_string_write(f, col, "size=", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, sizestr, strlen(sizestr)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + r = mailmime_parameter_write(f, col, param->pa_data.pa_parameter); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param) +{ + int r; + + r = mailimf_string_write(f, col, param->pa_name, + strlen(param->pa_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "=", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_value, + strlen(param->pa_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content) +{ + clistiter * cur; + size_t len; + int r; + + r = mailmime_type_write(f, col, content->ct_type); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "/", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, content->ct_subtype, + strlen(content->ct_subtype)); + if (r != MAILIMF_NO_ERROR) + return r; + + if (content->ct_parameters != NULL) { + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + len = strlen(param->pa_name) + 1 + strlen(param->pa_value); + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailmime_parameter_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Type: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_content_type_write(f, col, content); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type) +{ + int r; + + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + r = mailmime_discrete_type_write(f, col, type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + r = mailmime_composite_type_write(f, col, type->tp_data.tp_composite_type); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type) +{ + int r; + + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + r = mailimf_string_write(f, col, "text", 4); + break; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + r = mailimf_string_write(f, col, "image", 5); + break; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + r = mailimf_string_write(f, col, "audio", 5); + break; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + r = mailimf_string_write(f, col, "video", 5); + break; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + r = mailimf_string_write(f, col, "application", 11); + break; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, discrete_type->dt_extension, + strlen(discrete_type->dt_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type) +{ + int r; + + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + r = mailimf_string_write(f, col, "message", 7); + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + r = mailimf_string_write(f, col, "multipart", 9); + break; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, composite_type->ct_token, + strlen(composite_type->ct_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + + + +/* ****************************************************************** */ +/* message */ + +/* +static int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int is_text); +*/ + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size); + +/* +static int mailmime_base64_write(FILE * f, int * col, + char * text, size_t size); + +static int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + char * text, size_t size); +*/ + +static int mailmime_part_write(FILE * f, int * col, + struct mailmime * build_info) +{ + clistiter * cur; + int first; + int r; + char * boundary; + int istext; + + istext = TRUE; + boundary = NULL; + + if (build_info->mm_content_type != NULL) { + if (build_info->mm_type == MAILMIME_MULTIPLE) { + boundary = mailmime_extract_boundary(build_info->mm_content_type); + if (boundary == NULL) + return MAILIMF_ERROR_INVAL; + } + + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != + MAILMIME_DISCRETE_TYPE_TEXT) + istext = FALSE; + } + } + + switch (build_info->mm_type) { + case MAILMIME_SINGLE: + + /* 1-part body */ + + if (build_info->mm_data.mm_single != NULL) { + r = mailmime_data_write(f, col, build_info->mm_data.mm_single, istext); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MULTIPLE: + + /* multi-part */ + + + /* preamble */ + + if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_preamble, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + /* sub-parts */ + + first = TRUE; + + for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * subpart; + + subpart = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailmime_sub_write(f, col, subpart); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + + /* epilogue */ + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_epilogue, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MESSAGE: + + if (build_info->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write(f, col, + build_info->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* encapsuled message */ + + if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { + r = mailmime_sub_write(f, col, + build_info->mm_data.mm_message.mm_msg_mime); + if (r != MAILIMF_NO_ERROR) + return r; + } + break; + + } + + return MAILIMF_NO_ERROR; +} + + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info) +{ + int r; + +#if 0 + * col = 0; +#endif + /* MIME field - Content-Type */ + + if (build_info->mm_content_type != NULL) { + r = mailmime_content_write(f, col, build_info->mm_content_type); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* other MIME fields */ + + if (build_info->mm_type != MAILMIME_MESSAGE) { + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return mailmime_part_write(f, col, build_info); +} + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info) +{ + if (build_info->mm_parent != NULL) + return mailmime_sub_write(f, col, build_info); + else + return mailmime_part_write(f, col, build_info); +} + + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = MAILIMF_ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (text == NULL) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + + munmap(text, buf.st_size); + } + close(fd); + + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size) +{ + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_write(f, col, istext, text, size); + break; + + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_write(f, col, text, size); + break; + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailimf_string_write(f, col, text, size); + } +} + + +static const char base64_encoding[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_MAX_COL 76 + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size) +{ + int a; + int b; + int c; + size_t remains; + const char * p; + size_t count; + char ogroup[4]; + int r; + + remains = size; + p = text; + + while (remains > 0) { + switch (remains) { + case 1: + a = (unsigned char) p[0]; + b = 0; + c = 0; + count = 1; + break; + case 2: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = 0; + count = 2; + break; + default: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = (unsigned char) p[2]; + count = 3; + break; + } + + ogroup[0]= base64_encoding[a >> 2]; + ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; + ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; + ogroup[3]= base64_encoding[c & 0x3F]; + + switch (count) { + case 1: + ogroup[2]= '='; + ogroup[3]= '='; + break; + case 2: + ogroup[3]= '='; + break; + } + + if (* col + 4 > BASE64_MAX_COL) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + r = mailimf_string_write(f, col, ogroup, 4); + if (r != MAILIMF_NO_ERROR) + return r; + + remains -= count; + p += count; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + + return MAILIMF_NO_ERROR; +} + +#if 0 +#define MAX_WRITE_SIZE 512 +#endif + +enum { + STATE_INIT, + STATE_CR, + STATE_SPACE, + STATE_SPACE_CR, +}; + +#if 0 +static inline int write_try_buf(FILE * f, int * col, + char ** pstart, size_t * plen) +{ + int r; + + if (* plen >= MAX_WRITE_SIZE) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static inline int write_remaining(FILE * f, int * col, + const char ** pstart, size_t * plen) +{ + int r; + + if (* plen > 0) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} + + + +#define QP_MAX_COL 72 + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + size_t i; + const char * start; + size_t len; + char hexstr[6]; + int r; + int state; + + start = text; + len = 0; + state = STATE_INIT; + + i = 0; + while (i < size) { + unsigned char ch; + + if (* col + len > QP_MAX_COL) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + + r = mailimf_string_write(f, col, "=\r\n", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + ch = text[i]; + + switch (state) { + + case STATE_INIT: + switch (ch) { + case ' ': + case '\t': + state = STATE_SPACE; + break; + + case '\r': + state = STATE_CR; + break; + + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + case 'F': /* there is no more 'From' at the beginning of a line */ + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + if (istext && (ch == '\n')) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + else { + if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { + len ++; + } + else { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + break; + } + + i ++; + break; + + case STATE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + state = STATE_INIT; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + snprintf(hexstr, 6, "=%02X", '\r'); + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + break; + + case STATE_SPACE: + switch (ch) { + case '\r': + state = STATE_SPACE_CR; + i ++; + break; + + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + case ' ': + case '\t': + len ++; + i ++; + break; + + default: +#if 0 + len += 2; + state = STATE_INIT; + i ++; +#endif + len ++; + state = STATE_INIT; + break; + } + + break; + + case STATE_SPACE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + + break; + } + } + + return MAILIMF_NO_ERROR; +} diff --git a/kmicromail/libetpan/mime/mailmime_write.h b/kmicromail/libetpan/mime/mailmime_write.h new file mode 100644 index 0000000..96f8777 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/nntp/.libs/libnewsnntp.a b/kmicromail/libetpan/nntp/.libs/libnewsnntp.a new file mode 100644 index 0000000..7c524b7 --- a/dev/null +++ b/kmicromail/libetpan/nntp/.libs/libnewsnntp.a Binary files differ diff --git a/kmicromail/libetpan/nntp/newsnntp.c b/kmicromail/libetpan/nntp/newsnntp.c new file mode 100644 index 0000000..0806290 --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp.c @@ -0,0 +1,2486 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "newsnntp.h" + + +#include +#include +#include +#include +#include +#include +#include + +#include "connect.h" +#include "mail.h" +#include "clist.h" + +/* + NNTP Protocol + + RFC 977 + RFC 2980 + + TODO : + + XPAT header range| pat [pat...] + + + */ + + + + +#define NNTP_STRING_SIZE 513 + + + +static char * read_line(newsnntp * f); +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer); +static int parse_response(newsnntp * f, char * response); + +static int send_command(newsnntp * f, char * command); + +newsnntp * newsnntp_new(size_t progr_rate, progress_function * progr_fun) +{ + newsnntp * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->nntp_stream = NULL; + f->nntp_readonly = FALSE; + + f->nntp_progr_rate = progr_rate; + f->nntp_progr_fun = progr_fun; + + f->nntp_stream_buffer = mmap_string_new(""); + if (f->nntp_stream_buffer == NULL) + goto free_f; + + f->nntp_response_buffer = mmap_string_new(""); + if (f->nntp_response_buffer == NULL) + goto free_stream_buffer; + + return f; + + free_stream_buffer: + mmap_string_free(f->nntp_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +void newsnntp_free(newsnntp * f) +{ + if (f->nntp_stream) + newsnntp_quit(f); + + mmap_string_free(f->nntp_response_buffer); + mmap_string_free(f->nntp_stream_buffer); + + free(f); +} + + + + + + + + + + + + + + + + +int newsnntp_quit(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + int res; + + if (f->nntp_stream == NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + snprintf(command, NNTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + parse_response(f, response); + + res = NEWSNNTP_NO_ERROR; + + close: + + mailstream_close(f->nntp_stream); + + f->nntp_stream = NULL; + + return res; +} + +int newsnntp_connect(newsnntp * f, mailstream * s) +{ + char * response; + int r; + + if (f->nntp_stream != NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + f->nntp_stream = s; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 200: + f->nntp_readonly = FALSE; + return NEWSNNTP_NO_ERROR; + + case 201: + f->nntp_readonly = TRUE; + return NEWSNNTP_NO_ERROR; + + default: + f->nntp_stream = NULL; + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + + +/* +static struct newsnntp_xover_resp_item * get_xover_info(newsnntp * f, + guint32 article); +*/ + +static void newsnntp_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void newsnntp_head_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_article_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_body_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +/* ******************** HEADER ******************************** */ + +/* + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int newsnntp_get_content(newsnntp * f, char ** result, + size_t * result_len) +{ + int r; + char * response; + MMAPString * buffer; + char * result_multiline; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 220: + case 221: + case 222: + case 223: + buffer = mmap_string_new(""); + if (buffer == NULL) + return NEWSNNTP_ERROR_MEMORY; + + result_multiline = read_multiline(f, 0, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return NEWSNNTP_NO_ERROR; + } + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 423: + return NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_head(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "HEAD %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** ARTICLE ******************************** */ + +int newsnntp_article(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "ARTICLE %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** BODY ******************************** */ + +int newsnntp_body(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "BODY %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** GROUP ******************************** */ + +static struct newsnntp_group_info * +group_info_init(char * name, uint32_t first, uint32_t last, uint32_t count, + char type) +{ + struct newsnntp_group_info * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_first = first; + n->grp_last = last; + n->grp_count = count; + n->grp_type = type; + + return n; +} + +static void group_info_free(struct newsnntp_group_info * n) +{ + if (n->grp_name) + free(n->grp_name); + free(n); +} + +static void group_info_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_info_free, NULL); + clist_free(l); +} + +static int parse_group_info(char * response, + struct newsnntp_group_info ** info); + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "GROUP %s\r\n", groupname); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + if (!parse_group_info(f->nntp_response, info)) + return NEWSNNTP_ERROR_INVALID_RESPONSE; + return NEWSNNTP_NO_ERROR; + + case 411: + return NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_group_free(struct newsnntp_group_info * info) +{ + group_info_free(info); +} + +/* ******************** LIST ******************************** */ + +static clist * read_groups_list(newsnntp * f); + +int newsnntp_list(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_free(clist * l) +{ + group_info_list_free(l); +} + +/* ******************** POST ******************************** */ + +static void send_data(newsnntp * f, const char * message, uint32_t size) +{ + mailstream_send_data(f->nntp_stream, message, size, + f->nntp_progr_rate, f->nntp_progr_fun); +} + + +int newsnntp_post(newsnntp * f, const char * message, size_t size) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "POST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 340: + break; + + case 440: + return NEWSNNTP_ERROR_POSTING_NOT_ALLOWED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } + + send_data(f, message, size); + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 240: + return NEWSNNTP_NO_ERROR; + return 1; + + case 441: + return NEWSNNTP_ERROR_POSTING_FAILED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +/* ******************** AUTHINFO ******************************** */ + +int newsnntp_authinfo_username(newsnntp * f, const char * username) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO USER %s\r\n", username); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_authinfo_password(newsnntp * f, const char * password) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO PASS %s\r\n", password); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ******************** LIST OVERVIEW.FMT ******************************** */ + +static clist * read_headers_list(newsnntp * f); + +static void headers_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST OVERVIEW.FMT\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_headers_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_overview_fmt_free(clist * l) +{ + headers_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE ******************************** */ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (wildcard != NULL) + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE %s\r\n", wildcard); + else + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_free(clist * l) +{ + group_info_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE.TIMES ******************************** */ + +static struct newsnntp_group_time * +group_time_new(char * group_name, time_t date, char * email) +{ + struct newsnntp_group_time * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_email = strdup(email); + if (n->grp_email == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + n->grp_date = date; + + return n; +} + +static void group_time_free(struct newsnntp_group_time * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_email) + free(n->grp_email); + free(n); +} + +static void group_time_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_time_free, NULL); + clist_free(l); +} + + + + + + + +static clist * read_group_time_list(newsnntp * f); + + +int newsnntp_list_active_times(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE.TIMES\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_time_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_times_free(clist * l) +{ + group_time_list_free(l); +} + + + + + + + + +/* ********************** LIST DISTRIBUTION ***************************** */ + +static struct newsnntp_distrib_value_meaning * +distrib_value_meaning_new(char * value, char * meaning) +{ + struct newsnntp_distrib_value_meaning * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n); + return NULL; + } + + n->dst_meaning = strdup(meaning); + if (n->dst_meaning == NULL) { + free(n->dst_value); + free(n); + return NULL; + } + + return n; +} + + +static void +distrib_value_meaning_free(struct newsnntp_distrib_value_meaning * n) +{ + if (n->dst_value) + free(n->dst_value); + if (n->dst_meaning) + free(n->dst_meaning); + free(n); +} + +static void distrib_value_meaning_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_value_meaning_free, NULL); + clist_free(l); +} + +static clist * read_distrib_value_meaning_list(newsnntp * f); + + +int newsnntp_list_distribution(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIBUTION\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_value_meaning_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +void newsnntp_list_distribution_free(clist * l) +{ + distrib_value_meaning_list_free(l); +} + + + + + + + + + + + +/* ********************** LIST DISTRIB.PATS ***************************** */ + +static struct newsnntp_distrib_default_value * +distrib_default_value_new(uint32_t weight, char * group_pattern, char * value) +{ + struct newsnntp_distrib_default_value * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->dst_group_pattern = strdup(group_pattern); + if (n->dst_group_pattern == NULL) { + free(n); + return NULL; + } + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n->dst_group_pattern); + free(n); + return NULL; + } + + n->dst_weight = weight; + + return n; +} + +static void +distrib_default_value_free(struct newsnntp_distrib_default_value * n) +{ + if (n->dst_group_pattern) + free(n->dst_group_pattern); + if (n->dst_value) + free(n->dst_value); + free(n); +} + +static void distrib_default_value_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_default_value_free, NULL); + clist_free(l); +} + +static clist * read_distrib_default_value_list(newsnntp * f); + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIB.PATS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_default_value_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_distrib_pats_free(clist * l) +{ + distrib_default_value_list_free(l); +} + + + + + + + + + + + + +/* ********************** LIST NEWSGROUPS ***************************** */ + +static struct newsnntp_group_description * +group_description_new(char * group_name, char * description) +{ + struct newsnntp_group_description * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_description = strdup(description); + if (n->grp_description == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + return n; +} + +static void group_description_free(struct newsnntp_group_description * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_description) + free(n->grp_description); + free(n); +} + +static void group_description_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_description_free, NULL); + clist_free(l); +} + +static clist * read_group_description_list(newsnntp * f); + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (pattern) + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS %s\r\n", pattern); + else + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_description_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_newsgroups_free(clist * l) +{ + group_description_list_free(l); +} + + + + + + + + + + + + +/* ******************** LIST SUBSCRIPTIONS ******************************** */ + +static void subscriptions_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_subscriptions_list(newsnntp * f); + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST SUBSCRIPTIONS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_subscriptions_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_subscriptions_free(clist * l) +{ + subscriptions_list_free(l); +} + + + + + + + + + + + + +/* ******************** LISTGROUP ******************************** */ + +static void articles_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_articles_list(newsnntp * f); + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (group_name) + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP %s\r\n", group_name); + else + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + * result = read_articles_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_listgroup_free(clist * l) +{ + articles_list_free(l); +} + + + + + + + +/* ********************** MODE READER ***************************** */ + +int newsnntp_mode_reader(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + + snprintf(command, NNTP_STRING_SIZE, "MODE READER\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 200: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ********************** DATE ***************************** */ + +#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}} + +int newsnntp_date(newsnntp * f, struct tm * tm) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + char year[5]; + char month[3]; + char day[3]; + char hour[3]; + char minute[3]; + char second[3]; + + snprintf(command, NNTP_STRING_SIZE, "DATE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 111: + strfcpy(year, f->nntp_response, 4); + strfcpy(month, f->nntp_response + 4, 2); + strfcpy(day, f->nntp_response + 6, 2); + strfcpy(hour, f->nntp_response + 8, 2); + strfcpy(minute, f->nntp_response + 10, 2); + strfcpy(second, f->nntp_response + 12, 2); + + tm->tm_year = atoi(year); + tm->tm_mon = atoi(month); + tm->tm_mday = atoi(day); + tm->tm_hour = atoi(hour); + tm->tm_min = atoi(minute); + tm->tm_sec = atoi(second); + + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + +/* ********************** XHDR ***************************** */ + +static struct newsnntp_xhdr_resp_item * xhdr_resp_item_new(uint32_t article, + char * value) +{ + struct newsnntp_xhdr_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->hdr_value = strdup(value); + if (n->hdr_value == NULL) { + free(n); + return NULL; + } + + n->hdr_article = article; + + return n; +} + +static void xhdr_resp_item_free(struct newsnntp_xhdr_resp_item * n) +{ + if (n->hdr_value) + free(n->hdr_value); + free(n); +} + +static void xhdr_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xhdr_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xhdr_resp_list(newsnntp * f); + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result); + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i\r\n", header, article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i-%i\r\n", header, + rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +void newsnntp_xhdr_free(clist * l) +{ + xhdr_resp_list_free(l); +} + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 221: + * result = read_xhdr_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + +/* ********************** XOVER ***************************** */ + +static struct newsnntp_xover_resp_item * +xover_resp_item_new(uint32_t article, + char * subject, + char * author, + char * date, + char * message_id, + char * references, + size_t size, + uint32_t line_count, + clist * others) +{ + struct newsnntp_xover_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->ovr_subject = strdup(subject); + if (n->ovr_subject == NULL) { + free(n); + return NULL; + } + + n->ovr_author = strdup(author); + if (n->ovr_author == NULL) { + free(n->ovr_subject); + free(n); + return NULL; + } + + n->ovr_date = strdup(date); + if (n->ovr_date == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n); + return NULL; + } + + n->ovr_message_id = strdup(message_id); + if (n->ovr_message_id == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n); + return NULL; + } + + n->ovr_references = strdup(references); + if (n->ovr_references == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n->ovr_message_id); + free(n); + return NULL; + } + + n->ovr_article = article; + n->ovr_size = size; + n->ovr_line_count = line_count; + n->ovr_others = others; + + return n; +} + +void xover_resp_item_free(struct newsnntp_xover_resp_item * n) +{ + if (n->ovr_subject) + free(n->ovr_subject); + if (n->ovr_author) + free(n->ovr_author); + if (n->ovr_date) + free(n->ovr_date); + if (n->ovr_message_id) + free(n->ovr_message_id); + if (n->ovr_references) + free(n->ovr_references); + clist_foreach(n->ovr_others, (clist_func) free, NULL); + clist_free(n->ovr_others); + + free(n); +} + +void newsnntp_xover_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xover_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xover_resp_list(newsnntp * f); + + +static int newsnntp_xover_resp(newsnntp * f, clist ** result); + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + clist * list; + clistiter * cur; + struct newsnntp_xover_resp_item * item; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i\r\n", article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + r = newsnntp_xover_resp(f, &list); + if (r != NEWSNNTP_NO_ERROR) + return r; + + cur = clist_begin(list); + item = clist_content(cur); + clist_free(list); + + * result = item; + + return r; +} + +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + int r; + char command[NNTP_STRING_SIZE]; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i-%i\r\n", rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xover_resp(f, result); +} + +static int newsnntp_xover_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 224: + * result = read_xover_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + +/* ********************** AUTHINFO GENERIC ***************************** */ + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO GENERIC %s %s\r\n", + authentificator, arguments); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + case 500: + return NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD; + + case 501: + return NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + +static int parse_response(newsnntp * f, char * response) +{ + int code; + + code = strtol(response, &response, 10); + + if (response == NULL) { + f->nntp_response = NULL; + return code; + } + + parse_space(&response); + + if (mmap_string_assign(f->nntp_response_buffer, response) != NULL) + f->nntp_response = f->nntp_response_buffer->str; + else + f->nntp_response = NULL; + + return code; +} + + +static char * read_line(newsnntp * f) +{ + return mailstream_read_line_remove_eol(f->nntp_stream, f->nntp_stream_buffer); +} + +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->nntp_stream, size, + f->nntp_stream_buffer, multiline_buffer, + f->nntp_progr_rate, f->nntp_progr_fun); +} + + + + + + + +static int parse_group_info(char * response, + struct newsnntp_group_info ** result) +{ + char * line; + uint32_t first; + uint32_t last; + uint32_t count; + char * name; + struct newsnntp_group_info * info; + + line = response; + + count = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + first = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + last = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + name = line; + + info = group_info_init(name, first, last, count, FALSE); + if (info == NULL) + return FALSE; + + * result = info; + + return TRUE; +} + + +static clist * read_groups_list(newsnntp * f) +{ + char * line; + char * group_name; + uint32_t first; + uint32_t last; + uint32_t count; + int type; + clist * groups_list; + struct newsnntp_group_info * n; + int r; + + groups_list = clist_new(); + if (groups_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + group_name = line; + line = p; + + last = strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + first = strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + count = last - first + 1; + + type = * line; + + n = group_info_init(group_name, first, last, count, type); + if (n == NULL) + goto free_list; + + r = clist_append(groups_list, n); + if (r < 0) { + group_info_free(n); + goto free_list; + } + } + + return groups_list; + + free_list: + group_info_list_free(groups_list); + err: + return NULL; +} + + +static clist * read_headers_list(newsnntp * f) +{ + char * line; + clist * headers_list; + char * header; + int r; + + headers_list = clist_new(); + if (headers_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + header = strdup(line); + if (header == NULL) + goto free_list; + + r = clist_append(headers_list, header); + if (r < 0) { + free(header); + goto free_list; + } + } + + return headers_list; + + free_list: + headers_list_free(headers_list); + err: + return NULL; +} + + + + +static clist * read_group_time_list(newsnntp * f) +{ + char * line; + char * group_name; + time_t date; + char * email; + clist * group_time_list; + struct newsnntp_group_time * n; + int r; + + group_time_list = clist_new(); + if (group_time_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + date = strtoul(p, &remaining, 10); + + p = remaining; + parse_space(&p); + + email = p; + + group_name = line; + + n = group_time_new(group_name, date, email); + if (n == NULL) + goto free_list; + + r = clist_append(group_time_list, n); + if (r < 0) { + group_time_free(n); + goto free_list; + } + } + + return group_time_list; + + free_list: + group_time_list_free(group_time_list); + err: + return NULL; +} + + + + +static clist * read_distrib_value_meaning_list(newsnntp * f) +{ + char * line; + char * value; + char * meaning; + clist * distrib_value_meaning_list; + struct newsnntp_distrib_value_meaning * n; + int r; + + distrib_value_meaning_list = clist_new(); + if (distrib_value_meaning_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + + value = line; + + n = distrib_value_meaning_new(value, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_value_meaning_list, n); + if (r < 0) { + distrib_value_meaning_free(n); + goto free_list; + } + } + + return distrib_value_meaning_list; + + free_list: + distrib_value_meaning_list_free(distrib_value_meaning_list); + err: + return NULL; +} + + + + +static clist * read_distrib_default_value_list(newsnntp * f) +{ + char * line; + uint32_t weight; + char * group_pattern; + char * meaning; + clist * distrib_default_value_list; + struct newsnntp_distrib_default_value * n; + int r; + + distrib_default_value_list = clist_new(); + if (distrib_default_value_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = line; + + weight = strtoul(p, &remaining, 10); + p = remaining; + parse_space(&p); + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + group_pattern = line; + + n = distrib_default_value_new(weight, group_pattern, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_default_value_list, n); + if (r < 0) { + distrib_default_value_free(n); + goto free_list; + } + } + + return distrib_default_value_list; + + free_list: + distrib_default_value_list_free(distrib_default_value_list); + err: + return NULL; +} + + + +static clist * read_group_description_list(newsnntp * f) +{ + char * line; + char * group_name; + char * description; + clist * group_description_list; + struct newsnntp_group_description * n; + int r; + + group_description_list = clist_new(); + if (group_description_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + description = p; + + group_name = line; + + n = group_description_new(group_name, description); + if (n == NULL) + goto free_list; + + r = clist_append(group_description_list, n); + if (r < 0) { + group_description_free(n); + goto free_list; + } + } + + return group_description_list; + + free_list: + group_description_list_free(group_description_list); + err: + return NULL; +} + + + +static clist * read_subscriptions_list(newsnntp * f) +{ + char * line; + clist * subscriptions_list; + char * group_name; + int r; + + subscriptions_list = clist_new(); + if (subscriptions_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + group_name = strdup(line); + if (group_name == NULL) + goto free_list; + + r = clist_append(subscriptions_list, group_name); + if (r < 0) { + free(group_name); + goto free_list; + } + } + + return subscriptions_list; + + free_list: + subscriptions_list_free(subscriptions_list); + err: + return NULL; +} + + + +static clist * read_articles_list(newsnntp * f) +{ + char * line; + clist * articles_list; + uint32_t * article_num; + int r; + + articles_list = clist_new(); + if (articles_list == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article_num = malloc(sizeof(* article_num)); + if (article_num == NULL) + goto free_list; + * article_num = atoi(line); + + r = clist_append(articles_list, article_num); + if (r < 0) { + free(article_num); + goto free_list; + } + } + + return articles_list; + + free_list: + articles_list_free(articles_list); + err: + return NULL; +} + +static clist * read_xhdr_resp_list(newsnntp * f) +{ + char * line; + uint32_t article; + char * value; + clist * xhdr_resp_list; + struct newsnntp_xhdr_resp_item * n; + int r; + + xhdr_resp_list = clist_new(); + if (xhdr_resp_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article = strtoul(line, &line, 10); + if (!parse_space(&line)) + continue; + + value = line; + + n = xhdr_resp_item_new(article, value); + if (n == NULL) + goto free_list; + + r = clist_append(xhdr_resp_list, n); + if (r < 0) { + xhdr_resp_item_free(n); + goto free_list; + } + } + + return xhdr_resp_list; + + free_list: + xhdr_resp_list_free(xhdr_resp_list); + err: + return NULL; +} + + +static clist * read_xover_resp_list(newsnntp * f) +{ + char * line; + clist * xover_resp_list; + struct newsnntp_xover_resp_item * n; + clist * values_list; + clistiter * current; + uint32_t article; + char * subject; + char * author; + char * date; + char * message_id; + char * references; + size_t size; + uint32_t line_count; + clist * others; + int r; + + xover_resp_list = clist_new(); + if (xover_resp_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + /* parse the data separated with \t */ + + values_list = clist_new(); + if (values_list == NULL) + goto free_list; + + while ((p = strchr(line, '\t')) != NULL) { + * p = 0; + p ++; + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + line = p; + } + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + + /* set the known data */ + current = clist_begin(values_list); + article = atoi((char *) clist_content(current)); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + subject = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + author = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + date = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + message_id = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + references = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + size = atoi((char *) clist_content(current)); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + line_count = atoi((char *) clist_content(current)); + + current = clist_next(current); + + /* make a copy of the other data */ + others = clist_new(); + if (others == NULL) { + goto free_values_list; + } + + while (current) { + char * val; + + val = strdup(clist_content(current)); + if (val == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(others, val); + if (r < 0) { + goto free_list; + } + + current = clist_next(current); + } + + clist_free(values_list); + + n = xover_resp_item_new(article, subject, author, date, message_id, + references, size, line_count, others); + if (n == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(xover_resp_list, n); + if (r < 0) { + xover_resp_item_free(n); + goto free_list; + } + } + + return xover_resp_list; + + free_list: + newsnntp_xover_resp_list_free(xover_resp_list); + err: + return NULL; + + free_values_list: + clist_foreach(values_list, (clist_func) free, NULL); + clist_free(values_list); + return NULL; +} + +static int send_command(newsnntp * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->nntp_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->nntp_stream); + if (r == -1) + return -1; + + return 0; +} diff --git a/kmicromail/libetpan/nntp/newsnntp.h b/kmicromail/libetpan/nntp/newsnntp.h new file mode 100644 index 0000000..13360d0 --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp.h @@ -0,0 +1,188 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_H + +#define NEWSNNTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +newsnntp * newsnntp_new(size_t nntp_progr_rate, + progress_function * nntp_progr_fun); +void newsnntp_free(newsnntp * f); + +int newsnntp_quit(newsnntp * f); +int newsnntp_connect(newsnntp * f, mailstream * s); + +int newsnntp_head(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_article(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_body(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); + +void newsnntp_head_free(char * str); +void newsnntp_article_free(char * str); +void newsnntp_body_free(char * str); + +int newsnntp_mode_reader(newsnntp * f); + +int newsnntp_date(newsnntp * f, struct tm * tm); + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments); + +int newsnntp_authinfo_username(newsnntp * f, const char * username); +int newsnntp_authinfo_password(newsnntp * f, const char * password); + +int newsnntp_post(newsnntp * f, const char * message, size_t size); + + + + + + +/******************* requests ******************************/ + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info); +void newsnntp_group_free(struct newsnntp_group_info * info); + +/* + elements are struct newsnntp_group_info * + */ + +int newsnntp_list(newsnntp * f, clist ** result); +void newsnntp_list_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result); +void newsnntp_list_overview_fmt_free(clist * l); + +/* + elements are struct newsnntp_group_info * +*/ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result); +void newsnntp_list_active_free(clist * l); + +/* + elements are struct newsnntp_group_time * +*/ + +int newsnntp_list_active_times(newsnntp * f, clist ** result); +void newsnntp_list_active_times_free(clist * l); + +/* + elements are struct newsnntp_distrib_value_meaning * +*/ + +int newsnntp_list_distribution(newsnntp * f, clist ** result); +void newsnntp_list_distribution_free(clist * l); + +/* + elements are struct newsnntp_distrib_default_value * +*/ + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result); +void newsnntp_list_distrib_pats_free(clist * l); + +/* + elements are struct newsnntp_group_description * +*/ + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result); +void newsnntp_list_newsgroups_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result); +void newsnntp_list_subscriptions_free(clist * l); + +/* + elements are uint32_t * +*/ + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result); +void newsnntp_listgroup_free(clist * l); + +/* + elements are struct newsnntp_xhdr_resp_item * +*/ + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result); +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void newsnntp_xhdr_free(clist * l); + +/* + elements are struct newsnntp_xover_resp_item * +*/ + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result); +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void newsnntp_xover_free(clist * l); +void xover_resp_item_free(struct newsnntp_xover_resp_item * n); +void newsnntp_xover_resp_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/nntp/newsnntp_socket.c b/kmicromail/libetpan/nntp/newsnntp_socket.c new file mode 100644 index 0000000..245839f --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp_socket.c @@ -0,0 +1,74 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "newsnntp_socket.h" + +#include "newsnntp.h" + +#include "connect.h" + +#include +#include + +#define DEFAULT_NNTP_PORT 119 +#define SERVICE_NAME_NNTP "nntp" +#define SERVICE_TYPE_TCP "tcp" + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTP_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return NEWSNNTP_ERROR_MEMORY; + } + + return newsnntp_connect(f, stream); +} diff --git a/kmicromail/libetpan/nntp/newsnntp_socket.h b/kmicromail/libetpan/nntp/newsnntp_socket.h new file mode 100644 index 0000000..fd44b44 --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp_socket.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_SOCKET_H + +#define NEWSNNTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/nntp/newsnntp_ssl.c b/kmicromail/libetpan/nntp/newsnntp_ssl.c new file mode 100644 index 0000000..84816bd --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp_ssl.c @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "newsnntp_ssl.h" + +#include "newsnntp.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_NNTPS_PORT 563 +#define SERVICE_NAME_NNTPS "nntps" +#define SERVICE_TYPE_TCP "tcp" + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTPS_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + } + + return newsnntp_connect(f, stream); +} diff --git a/kmicromail/libetpan/nntp/newsnntp_ssl.h b/kmicromail/libetpan/nntp/newsnntp_ssl.h new file mode 100644 index 0000000..59eace5 --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp_ssl.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_SSL_H + +#define NEWSNNTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/nntp/newsnntp_types.h b/kmicromail/libetpan/nntp/newsnntp_types.h new file mode 100644 index 0000000..0501088 --- a/dev/null +++ b/kmicromail/libetpan/nntp/newsnntp_types.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef NEWSNNTP_TYPES_H + +#define NEWSNNTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include + +enum { + NEWSNNTP_NO_ERROR = 0, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, + NEWSNNTP_ERROR_STREAM, + NEWSNNTP_ERROR_UNEXPECTED, + NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, + NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, + NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, + NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, + NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, + NEWSNNTP_ERROR_INVALID_RESPONSE, + NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, + NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, + NEWSNNTP_ERROR_POSTING_FAILED, + NEWSNNTP_ERROR_PROGRAM_ERROR, + NEWSNNTP_ERROR_NO_PERMISSION, + NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, + NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, + NEWSNNTP_ERROR_CONNECTION_REFUSED, + NEWSNNTP_ERROR_MEMORY, + NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, + NEWSNNTP_ERROR_BAD_STATE, +}; + +struct newsnntp +{ + mailstream * nntp_stream; + + int nntp_readonly; + + uint32_t nntp_progr_rate; + progress_function * nntp_progr_fun; + + MMAPString * nntp_stream_buffer; + MMAPString * nntp_response_buffer; + + char * nntp_response; +}; + +typedef struct newsnntp newsnntp; + +struct newsnntp_group_info +{ + char * grp_name; + uint32_t grp_first; + uint32_t grp_last; + uint32_t grp_count; + char grp_type; +}; + +struct newsnntp_group_time { + char * grp_name; + uint32_t grp_date; + char * grp_email; +}; + +struct newsnntp_distrib_value_meaning { + char * dst_value; + char * dst_meaning; +}; + +struct newsnntp_distrib_default_value { + uint32_t dst_weight; + char * dst_group_pattern; + char * dst_value; +}; + +struct newsnntp_group_description { + char * grp_name; + char * grp_description; +}; + +struct newsnntp_xhdr_resp_item { + uint32_t hdr_article; + char * hdr_value; +}; + +struct newsnntp_xover_resp_item { + uint32_t ovr_article; + char * ovr_subject; + char * ovr_author; + char * ovr_date; + char * ovr_message_id; + char * ovr_references; + size_t ovr_size; + uint32_t ovr_line_count; + clist * ovr_others; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/pop3/.libs/libmailpop3.a b/kmicromail/libetpan/pop3/.libs/libmailpop3.a new file mode 100644 index 0000000..55cb819 --- a/dev/null +++ b/kmicromail/libetpan/pop3/.libs/libmailpop3.a Binary files differ diff --git a/kmicromail/libetpan/pop3/mailpop3.c b/kmicromail/libetpan/pop3/mailpop3.c new file mode 100644 index 0000000..28fafe9 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3.c @@ -0,0 +1,1230 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* + POP3 Protocol + + RFC 1734 + RFC 1939 + RFC 2449 + + */ + +#include "mailpop3.h" +#include +#include +#include "md5.h" +#include "mail.h" +#include + + + + +enum { + POP3_STATE_DISCONNECTED, + POP3_STATE_AUTHORIZATION, + POP3_STATE_TRANSACTION +}; + + + +/* + mailpop3_msg_info structure +*/ + +static struct mailpop3_msg_info * +mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl) +{ + struct mailpop3_msg_info * msg; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + return NULL; + msg->msg_index = index; + msg->msg_size = size; + msg->msg_deleted = FALSE; + msg->msg_uidl = uidl; + + return msg; +} + +static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg) +{ + if (msg->msg_uidl != NULL) + free(msg->msg_uidl); + free(msg); +} + +static void mailpop3_msg_info_tab_free(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + + msg = carray_get(msg_tab, i); + mailpop3_msg_info_free(msg); + } + carray_free(msg_tab); +} + +static void mailpop3_msg_info_tab_reset(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + msg = carray_get(msg_tab, i); + msg->msg_deleted = FALSE; + } +} + +static inline struct mailpop3_msg_info * +mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index) +{ + struct mailpop3_msg_info * msg; + + if (index == 0) + return NULL; + + if (index > carray_count(msg_tab)) + return NULL; + + msg = carray_get(msg_tab, index - 1); + + return msg; +} + + + +int mailpop3_get_msg_info(mailpop3 * f, unsigned int index, + struct mailpop3_msg_info ** result) +{ + carray * tab; + struct mailpop3_msg_info * info; + + mailpop3_list(f, &tab); + + if (tab == NULL) + return MAILPOP3_ERROR_BAD_STATE; + + info = mailpop3_msg_info_tab_find_msg(tab, index); + if (info == NULL) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + * result = info; + + return MAILPOP3_NO_ERROR; +} + + +/* + mailpop3_capa +*/ + +struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param) +{ + struct mailpop3_capa * capa; + + capa = malloc(sizeof(* capa)); + if (capa == NULL) + return NULL; + capa->cap_name = name; + capa->cap_param = param; + + return capa; +} + + +void mailpop3_capa_free(struct mailpop3_capa * capa) +{ + clist_foreach(capa->cap_param, (clist_func) free, NULL); + clist_free(capa->cap_param); + free(capa->cap_name); + free(capa); +} + +/* + mailpop3 structure +*/ + +mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun) +{ + mailpop3 * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->pop3_timestamp = NULL; + f->pop3_response = NULL; + + f->pop3_stream = NULL; + + f->pop3_progr_rate = progr_rate; + f->pop3_progr_fun = progr_fun; + + f->pop3_stream_buffer = mmap_string_new(""); + if (f->pop3_stream_buffer == NULL) + goto free_f; + + f->pop3_response_buffer = mmap_string_new(""); + if (f->pop3_response_buffer == NULL) + goto free_stream_buffer; + + f->pop3_msg_tab = NULL; + f->pop3_deleted_count = 0; + f->pop3_state = POP3_STATE_DISCONNECTED; + + return f; + + free_stream_buffer: + mmap_string_free(f->pop3_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + + + +void mailpop3_free(mailpop3 * f) +{ + if (f->pop3_stream) + mailpop3_quit(f); + + mmap_string_free(f->pop3_response_buffer); + mmap_string_free(f->pop3_stream_buffer); + + free(f); +} + + + + + + + + + + + +/* + operations on mailpop3 structure +*/ + +#define RESPONSE_OK 0 +#define RESPONSE_ERR -1 + +static int send_command(mailpop3 * f, char * command); + +static char * read_line(mailpop3 * f); + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer); + +static int parse_response(mailpop3 * f, char * response); + + +/* get the timestamp in the connection response */ + +#define TIMESTAMP_START '<' +#define TIMESTAMP_END '>' + +static char * mailpop3_get_timestamp(char * response) +{ + char * begin_timestamp; + char * end_timestamp; + char * timestamp; + int len_timestamp; + + if (response == NULL) + return NULL; + + begin_timestamp = strchr(response, TIMESTAMP_START); + + end_timestamp = NULL; + if (begin_timestamp != NULL) { + end_timestamp = strchr(begin_timestamp, TIMESTAMP_END); + if (end_timestamp == NULL) + begin_timestamp = NULL; + } + + if (!begin_timestamp) + return NULL; + + len_timestamp = end_timestamp - begin_timestamp + 1; + + timestamp = malloc(len_timestamp + 1); + if (timestamp == NULL) + return NULL; + strncpy(timestamp, begin_timestamp, len_timestamp); + timestamp[len_timestamp] = '\0'; + + return timestamp; +} + +/* + connect a stream to the mailpop3 structure +*/ + +int mailpop3_connect(mailpop3 * f, mailstream * s) +{ + char * response; + int r; + char * timestamp; + + if (f->pop3_state != POP3_STATE_DISCONNECTED) + return MAILPOP3_ERROR_BAD_STATE; + + f->pop3_stream = s; + + response = read_line(f); + + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_UNAUTHORIZED; + + f->pop3_state = POP3_STATE_AUTHORIZATION; + + timestamp = mailpop3_get_timestamp(f->pop3_response); + if (timestamp != NULL) + f->pop3_timestamp = timestamp; + + return MAILPOP3_NO_ERROR; +} + + +/* + disconnect from a pop3 server +*/ + +int mailpop3_quit(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + int res; + + if ((f->pop3_state != POP3_STATE_AUTHORIZATION) + && (f->pop3_state != POP3_STATE_TRANSACTION)) { + res = MAILPOP3_ERROR_BAD_STATE; + goto close; + } + + snprintf(command, POP3_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + parse_response(f, response); + + res = MAILPOP3_NO_ERROR; + + close: + mailstream_close(f->pop3_stream); + + if (f->pop3_timestamp != NULL) { + free(f->pop3_timestamp); + f->pop3_timestamp = NULL; + } + + f->pop3_stream = NULL; + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + f->pop3_state = POP3_STATE_DISCONNECTED; + + return res; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int mailpop3_apop(mailpop3 * f, + const char * user, const char * password) +{ + char command[POP3_STRING_SIZE]; + MD5_CTX md5context; + unsigned char md5digest[16]; + char md5string[33]; + char * cmd_ptr; + int r; + int i; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + if (f->pop3_timestamp == NULL) + return MAILPOP3_ERROR_APOP_NOT_SUPPORTED; + + /* calculate md5 sum */ + + MD5Init(&md5context); + MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp)); + MD5Update(&md5context, password, strlen (password)); + MD5Final(md5digest, &md5context); + + cmd_ptr = md5string; + for(i = 0 ; i < 16 ; i++, cmd_ptr += 2) + snprintf(cmd_ptr, 3, "%02x", md5digest[i]); + * cmd_ptr = 0; + + /* send apop command */ + + snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_DENIED; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_user(mailpop3 * f, const char * user) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send user command */ + + snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_USER; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_pass(mailpop3 * f, const char * password) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send password command */ + + snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_PASSWORD; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +static int read_list(mailpop3 * f, carray ** result); + + + +static int read_uidl(mailpop3 * f, carray * msg_tab); + + + +static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "UIDL\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_uidl(f, msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + + + +static int mailpop3_do_list(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + carray * msg_tab; + char * response; + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_list(f, &msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + f->pop3_msg_tab = msg_tab; + f->pop3_deleted_count = 0; + + mailpop3_do_uidl(f, msg_tab); + + return MAILPOP3_NO_ERROR; +} + + + +static void mailpop3_list_if_needed(mailpop3 * f) +{ + if (f->pop3_msg_tab == NULL) + mailpop3_do_list(f); +} + +/* + mailpop3_list +*/ + +void mailpop3_list(mailpop3 * f, carray ** result) +{ + mailpop3_list_if_needed(f); + * result = f->pop3_msg_tab; +} + +static inline struct mailpop3_msg_info * +find_msg(mailpop3 * f, unsigned int index) +{ + mailpop3_list_if_needed(f); + + if (f->pop3_msg_tab == NULL) + return NULL; + + return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index); +} + + + + + + + + +static void mailpop3_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void mailpop3_top_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +void mailpop3_retr_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +/* + mailpop3_retr + + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int +mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo, + char ** result, size_t * result_len) +{ + char * response; + char * result_multiline; + MMAPString * buffer; + int r; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + buffer = mmap_string_new(""); + if (buffer == NULL) + return MAILPOP3_ERROR_MEMORY; + + result_multiline = read_multiline(f, msginfo->msg_size, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_STREAM; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return MAILPOP3_NO_ERROR; + } +} + +int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_top(mailpop3 * f, unsigned int index, + uint32_t count, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_dele(mailpop3 * f, unsigned int index) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + msginfo->msg_deleted = TRUE; + f->pop3_deleted_count ++; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_noop(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "NOOP\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_rset(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "RSET\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_reset(f->pop3_msg_tab); + f->pop3_deleted_count = 0; + } + + return MAILPOP3_NO_ERROR; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result) +{ + clist * capa_list; + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "CAPA\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; + + r = read_capa_resp(f, &capa_list); + if (r != MAILPOP3_NO_ERROR) + return r; + + * result = capa_list; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_capa_resp_free(clist * capa_list) +{ + clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL); + clist_free(capa_list); +} + +int mailpop3_stls(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "STLS\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_STLS_NOT_SUPPORTED; + + return MAILPOP3_NO_ERROR; +} + + + + + + + + + + + + + + + + + + + + + + + + +#define RESP_OK_STR "+OK" +#define RESP_ERR_STR "-ERR" + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + + +static int parse_response(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) { + + if (response[strlen(RESP_OK_STR)] == ' ') + msg = response + strlen(RESP_OK_STR) + 1; + else + msg = response + strlen(RESP_OK_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_OK; + } + else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) { + + if (response[strlen(RESP_ERR_STR)] == ' ') + msg = response + strlen(RESP_ERR_STR) + 1; + else + msg = response + strlen(RESP_ERR_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + } + + f->pop3_response = NULL; + return RESPONSE_ERR; +} + + + + + + + +static int read_list(mailpop3 * f, carray ** result) +{ + unsigned int index; + uint32_t size; + carray * msg_tab; + struct mailpop3_msg_info * msg; + char * line; + + msg_tab = carray_new(128); + if (msg_tab == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + size = strtol(line, &line, 10); + + msg = mailpop3_msg_info_new(index, size, NULL); + if (msg == NULL) + goto free_list; + + if (carray_count(msg_tab) < index) { + int r; + + r = carray_set_size(msg_tab, index); + if (r == -1) + goto free_list; + } + + carray_set(msg_tab, index - 1, msg); + } + + * result = msg_tab; + + return MAILPOP3_NO_ERROR; + + free_list: + mailpop3_msg_info_tab_free(msg_tab); + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_uidl(mailpop3 * f, carray * msg_tab) +{ + unsigned int index; + struct mailpop3_msg_info * msg; + char * line; + + while (1) { + char * uidl; + + line = read_line(f); + if (line == NULL) + goto err; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + uidl = strdup(line); + if (uidl == NULL) + continue; + + if (index > carray_count(msg_tab)) { + free(uidl); + continue; + } + + msg = carray_get(msg_tab, index - 1); + if (msg == NULL) { + free(uidl); + continue; + } + + msg->msg_uidl = uidl; + } + + return MAILPOP3_NO_ERROR; + + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result) +{ + char * line; + int res; + clist * list; + int r; + char * name; + clist * param_list; + + list = clist_new(); + if (list == NULL) { + res = MAILPOP3_NO_ERROR; + goto err; + } + + while (1) { + char * next_token; + char * param; + struct mailpop3_capa * capa; + + line = read_line(f); + if (line == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto free_list; + } + + if (mailstream_is_end_multiline(line)) + break; + + next_token = cut_token(line); + name = strdup(line); + if (name == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + + param_list = clist_new(); + if (param_list == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_capa_name; + } + + while (next_token != NULL) { + line = next_token; + next_token = cut_token(line); + param = strdup(line); + if (param == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + r = clist_append(param_list, param); + if (r < 0) { + free(param); + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + } + + capa = mailpop3_capa_new(name, param_list); + if (capa == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + + r = clist_append(list, capa); + if (r < 0) { + mailpop3_capa_free(capa); + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAILPOP3_NO_ERROR; + + free_param_list: + clist_foreach(param_list, (clist_func) free, NULL); + clist_free(param_list); + free_capa_name: + free(name); + free_list: + clist_foreach(list, (clist_func) mailpop3_capa_free, NULL); + clist_free(list); + err: + return res; +} + + + +static char * read_line(mailpop3 * f) +{ + return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer); +} + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->pop3_stream, size, + f->pop3_stream_buffer, multiline_buffer, + f->pop3_progr_rate, f->pop3_progr_fun); +} + +static int send_command(mailpop3 * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->pop3_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->pop3_stream); + if (r == -1) + return -1; + + return 0; +} diff --git a/kmicromail/libetpan/pop3/mailpop3.h b/kmicromail/libetpan/pop3/mailpop3.h new file mode 100644 index 0000000..b8552ab --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_H + +#define MAILPOP3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include + +#define POP3_STRING_SIZE 513 + +mailpop3 * mailpop3_new(size_t pop3_progr_rate, + progress_function * pop3_progr_fun); + +void mailpop3_free(mailpop3 * f); + +int mailpop3_connect(mailpop3 * f, mailstream * s); + +int mailpop3_quit(mailpop3 * f); + + +int mailpop3_apop(mailpop3 * f, const char * user, const char * password); + +int mailpop3_user(mailpop3 * f, const char * user); + +int mailpop3_pass(mailpop3 * f, const char * password); + +void mailpop3_list(mailpop3 * f, carray ** result); + +int mailpop3_retr(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len); + +int mailpop3_top(mailpop3 * f, uint32_t index, uint32_t count, + char ** result, size_t * result_len); + +int mailpop3_dele(mailpop3 * f, uint32_t index); + +int mailpop3_noop(mailpop3 * f); + +int mailpop3_rset(mailpop3 * f); + +void mailpop3_top_free(char * str); + +void mailpop3_retr_free(char * str); + +int mailpop3_get_msg_info(mailpop3 * f, uint32_t index, + struct mailpop3_msg_info ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result); + +void mailpop3_capa_resp_free(clist * capa_list); + +int mailpop3_stls(mailpop3 * f); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/pop3/mailpop3_helper.c b/kmicromail/libetpan/pop3/mailpop3_helper.c new file mode 100644 index 0000000..5a3c26b --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_helper.c @@ -0,0 +1,78 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailpop3_helper.h" + +#include + +int mailpop3_login_apop(mailpop3 * f, + char * user, + char * password) +{ + return mailpop3_apop(f, user, password); +} + + +/* + mailpop3_login + + must be used immediately after connect +*/ + +int mailpop3_login(mailpop3 * f, + char * user, + char * password) +{ + int r; + + if ((r = mailpop3_user(f, user)) != MAILPOP3_NO_ERROR) + return r; + + if ((r = mailpop3_pass(f, password)) != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_header_free(char * str) +{ + mailpop3_top_free(str); +} + +int mailpop3_header(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len) +{ + return mailpop3_top(f, index, 0, result, result_len); +} diff --git a/kmicromail/libetpan/pop3/mailpop3_helper.h b/kmicromail/libetpan/pop3/mailpop3_helper.h new file mode 100644 index 0000000..7337ad8 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_helper.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_HELPER_H + +#define MAILPOP3_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3.h" + +int mailpop3_login_apop(mailpop3 * f, + char * user, + char * password); + +int mailpop3_login(mailpop3 * f, + char * user, + char * password); + +int mailpop3_header(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len); + +void mailpop3_header_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/pop3/mailpop3_socket.c b/kmicromail/libetpan/pop3/mailpop3_socket.c new file mode 100644 index 0000000..3897969 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_socket.c @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailpop3_socket.h" + +#include "mailpop3.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_POP3_PORT 110 +#define SERVICE_NAME_POP3 "pop3" +#define SERVICE_TYPE_TCP "tcp" + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILPOP3_ERROR_MEMORY; + } + + return mailpop3_connect(f, stream); +} diff --git a/kmicromail/libetpan/pop3/mailpop3_socket.h b/kmicromail/libetpan/pop3/mailpop3_socket.h new file mode 100644 index 0000000..06f16f5 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_socket.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_SOCKET_H + +#define MAILPOP3_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/pop3/mailpop3_ssl.c b/kmicromail/libetpan/pop3/mailpop3_ssl.c new file mode 100644 index 0000000..8fbbcf2 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_ssl.c @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailpop3_ssl.h" + +#include "mailpop3.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_POP3S_PORT 995 +#define SERVICE_NAME_POP3S "pop3s" +#define SERVICE_TYPE_TCP "tcp" + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3S, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3S_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILPOP3_ERROR_CONNECTION_REFUSED; + } + + return mailpop3_connect(f, stream); +} diff --git a/kmicromail/libetpan/pop3/mailpop3_ssl.h b/kmicromail/libetpan/pop3/mailpop3_ssl.h new file mode 100644 index 0000000..926001c --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_ssl.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_SSL_H + +#define MAILPOP3_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/pop3/mailpop3_types.h b/kmicromail/libetpan/pop3/mailpop3_types.h new file mode 100644 index 0000000..20500f6 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILPOP3_TYPES_H + +#define MAILPOP3_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include + +enum { + MAILPOP3_NO_ERROR = 0, + MAILPOP3_ERROR_BAD_STATE, + MAILPOP3_ERROR_UNAUTHORIZED, + MAILPOP3_ERROR_STREAM, + MAILPOP3_ERROR_DENIED, + MAILPOP3_ERROR_BAD_USER, + MAILPOP3_ERROR_BAD_PASSWORD, + MAILPOP3_ERROR_CANT_LIST, + MAILPOP3_ERROR_NO_SUCH_MESSAGE, + MAILPOP3_ERROR_MEMORY, + MAILPOP3_ERROR_CONNECTION_REFUSED, + MAILPOP3_ERROR_APOP_NOT_SUPPORTED, + MAILPOP3_ERROR_CAPA_NOT_SUPPORTED, + MAILPOP3_ERROR_STLS_NOT_SUPPORTED, +}; + +struct mailpop3 +{ + char * pop3_response; /* response message */ + char * pop3_timestamp; /* connection timestamp */ + + /* internals */ + mailstream * pop3_stream; + size_t pop3_progr_rate; + progress_function * pop3_progr_fun; + + MMAPString * pop3_stream_buffer; /* buffer for lines reading */ + MMAPString * pop3_response_buffer; /* buffer for responses */ + + carray * pop3_msg_tab; /* list of pop3_msg_info structures */ + int pop3_state; /* state */ + + unsigned int pop3_deleted_count; +}; + +typedef struct mailpop3 mailpop3; + +struct mailpop3_msg_info +{ + unsigned int msg_index; + uint32_t msg_size; + char * msg_uidl; + int msg_deleted; +}; + + +struct mailpop3_capa { + char * cap_name; + clist * cap_param; /* (char *) */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/smtp/.libs/libmailsmtp.a b/kmicromail/libetpan/smtp/.libs/libmailsmtp.a new file mode 100644 index 0000000..b856a73 --- a/dev/null +++ b/kmicromail/libetpan/smtp/.libs/libmailsmtp.a Binary files differ diff --git a/kmicromail/libetpan/smtp/TODO b/kmicromail/libetpan/smtp/TODO new file mode 100644 index 0000000..96f44c6 --- a/dev/null +++ b/kmicromail/libetpan/smtp/TODO @@ -0,0 +1 @@ +- STARTTLS diff --git a/kmicromail/libetpan/smtp/mailsmtp.c b/kmicromail/libetpan/smtp/mailsmtp.c new file mode 100644 index 0000000..b3be432 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp.c @@ -0,0 +1,982 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa, + * All rights reserved. + * + * SMTP AUTH support by Juergen Graf + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailsmtp.h" +#include "connect.h" +#include "md5.h" +#include "base64.h" +#include "mail.h" + +#include +#include +#include +#include +#include + + +/* + RFC 2821 : SMTP + RFC 1891 : SMTP Service Extension for Delivery Status Notifications + + RFC 1428 : Transition of Internet Mail from Just-Send-8 to 8bit-SMTP/MIME + RFC 1652 : SMTP Service Extension for 8bit-MIMEtransport + RFC 1845 : SMTP Service Extension for Checkpoint/Restart + RFC 1846 : SMTP 521 Reply Code + RFC 1870 : SMTP Service Extension for Message Size Declaration + RFC 1985 : SMTP Service Extension for Remote Message Queue Starting + RFC 2034 : SMTP Service Extension for Returning Enhanced Error Codes + RFC 2442 : The Batch SMTP Media Type + RFC 2487 : SMTP Service Extension for Secure SMTP over TLS + RFC 2505 : Anti-Spam Recommendations for SMTP MTAs + RFC 2554 : SMTP Service Extension for Authentication + RFC 2645 : ON-DEMAND MAIL RELAY (ODMR) SMTP with Dynamic IP Addresses + RFC 2852 : Deliver By SMTP Service Extension + RFC 2920 : SMTP Service Extension for Command Pipelining + RFC 3030 : SMTP Service Extensions for Transmission of Large and Binary MIME + Messages +*/ + +#define SMTP_STATUS_CONTINUE 0x1000 + +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun) +{ + mailsmtp * session; + + session = malloc(sizeof(* session)); + if (session == NULL) + goto err; + + session->stream = NULL; + + session->progr_rate = progr_rate; + session->progr_fun = progr_fun; + + session->response = NULL; + + session->line_buffer = mmap_string_new(""); + if (session->line_buffer == NULL) + goto free_session; + + session->response_buffer = mmap_string_new(""); + if (session->response_buffer == NULL) + goto free_line_buffer; + + session->esmtp = 0; + session->auth = MAILSMTP_AUTH_NOT_CHECKED; + + return session; + + free_line_buffer: + mmap_string_free(session->line_buffer); + free_session: + free(session); + err: + return NULL; +} + +void mailsmtp_free(mailsmtp * session) +{ + if (session->stream) + mailsmtp_quit(session); + + mmap_string_free(session->line_buffer); + mmap_string_free(session->response_buffer); + free(session); +} + +static int send_command(mailsmtp * f, char * command); + +static int read_response(mailsmtp * session); + +/* smtp operations */ + +int mailsmtp_connect(mailsmtp * session, mailstream * s) +{ + int code; + + session->stream = s; + + code = read_response(session); + + switch (code) { + case 220: + return MAILSMTP_NO_ERROR; + + case 554: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE; + + default: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + + +#define SMTP_STRING_SIZE 513 + +int mailsmtp_quit(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + if (r == 0) + return MAILSMTP_ERROR_STREAM; + mailstream_close(session->stream); + session->stream = NULL; + + return MAILSMTP_NO_ERROR; +} + + + +#define HOSTNAME_SIZE 256 + +int mailsmtp_helo(mailsmtp * session) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = gethostname(hostname, HOSTNAME_SIZE); + if (r < 0) + return MAILSMTP_ERROR_HOSTNAME; + + snprintf(command, SMTP_STRING_SIZE, "HELO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_mail(mailsmtp * session, const char * from) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>\r\n", from); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_rcpt(mailsmtp * session, const char * to) +{ + return mailesmtp_rcpt(session, to, 0, NULL); +} + +int mailsmtp_data(mailsmtp * session) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "DATA\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 354: + return MAILSMTP_NO_ERROR; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int send_data(mailsmtp * session, const char * message, size_t size); + +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size) +{ + int r; + + r = send_data(session, message, size); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + + r = read_response(session); + + switch(r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* esmtp operations */ + + +/** + * called during mailesmtp_ehlo + * checks EHLO answer for server extensions and sets flags + * in session->esmtp + * checks AUTH methods in session->response and sets flags + * in session->auth + */ +#define isdelim(x) ((x) == ' ' || (x) == '\r' || (x) == '\n' || (x) == '\0') + +int mailesmtp_parse_ehlo(mailsmtp * session) +{ + char * response; + + /* restore data */ + session->esmtp = MAILSMTP_ESMTP; + session->auth = MAILSMTP_AUTH_CHECKED; + + response = session->response; + + /* ESMTP supported extensions : + DSN + EXPN + 8BITMIME + SIZE [] + ETRN + STARTTLS + AUTH + */ + while (response != NULL) { + if (!strncasecmp(response, "EXPN", 4) && isdelim(response[4])) + session->esmtp |= MAILSMTP_ESMTP_EXPN; + else if (!strncasecmp(response, "ETRN", 4) && isdelim(response[4])) + session->esmtp |= MAILSMTP_ESMTP_ETRN; + else if (!strncasecmp(response, "DSN", 3) && isdelim(response[3])) + session->esmtp |= MAILSMTP_ESMTP_DSN; + else if (!strncasecmp(response, "8BITMIME", 8) && isdelim(response[8])) + session->esmtp |= MAILSMTP_ESMTP_8BITMIME; + else if (!strncasecmp(response, "STARTTLS", 8) && isdelim(response[8])) + session->esmtp |= MAILSMTP_ESMTP_STARTTLS; + else if (!strncasecmp(response, "SIZE", 4) && isdelim(response[4])) { + session->esmtp |= MAILSMTP_ESMTP_SIZE; + /* TODO: grab optionnal max size */ + } else if (!strncasecmp(response, "AUTH ", 5)) { + response += 5; /* remove "AUTH " */ + while (response[0] != '\n' && response[0] != '\0') { + while (response[0] == ' ') response++; + if (strncasecmp(response, "LOGIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_LOGIN; + response += 5; + } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) { + session->auth |= MAILSMTP_AUTH_CRAM_MD5; + response += 8; + } else if (strncasecmp(response, "PLAIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_PLAIN; + response += 5; + } else { + /* unknown auth method - jump to next word or eol */ + while (!isdelim(response[0]) || response[0] == '\r') + response++; + } + } + } + response = strpbrk(response, "\n"); + if (response != NULL) + response++; + } + + return MAILSMTP_NO_ERROR; +} + + +int mailesmtp_ehlo(mailsmtp * session) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = gethostname(hostname, HOSTNAME_SIZE); + if (r != 0) + return MAILSMTP_ERROR_HOSTNAME; + + snprintf(command, SMTP_STRING_SIZE, "EHLO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return mailesmtp_parse_ehlo(session); + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* + if return_full is TRUE, the entire message is returned on error + envid can be NULL +*/ + + +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid) +{ + int r; + char command[SMTP_STRING_SIZE]; + char *body = ""; + +#if notyet + /* TODO: figure out a way for the user to explicity enable this or not */ + if (session->esmtp & MAILSMTP_ESMTP_8BITMIME) + body = " BODY=8BITMIME"; +#endif + + if (session->esmtp & MAILSMTP_ESMTP_DSN) { + if (envid) + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s ENVID=%s%s\r\n", + from, return_full ? "FULL" : "HDRS", envid, body); + else + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s%s\r\n", + from, return_full ? "FULL" : "HDRS", body); + } else + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>%s\r\n", + from, body); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt) +{ + int r; + char command[SMTP_STRING_SIZE]; + char notify_str[30] = ""; + char notify_info_str[30] = ""; + + if (notify != 0 && session->esmtp & MAILSMTP_ESMTP_DSN) { + if (notify & MAILSMTP_DSN_NOTIFY_SUCCESS) + strcat(notify_info_str, ",SUCCESS"); + if (notify & MAILSMTP_DSN_NOTIFY_FAILURE) + strcat(notify_info_str, ",FAILURE"); + if (notify & MAILSMTP_DSN_NOTIFY_DELAY) + strcat(notify_info_str, ",DELAY"); + + if (notify & MAILSMTP_DSN_NOTIFY_NEVER) + strcpy(notify_info_str, ",NEVER"); + + notify_info_str[0] = '='; + + strcpy(notify_str, " NOTIFY"); + strcat(notify_str, notify_info_str); + } + + if (orcpt && session->esmtp & MAILSMTP_ESMTP_DSN) + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s ORCPT=%s\r\n", + to, notify_str, orcpt); + else + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s\r\n", to, notify_str); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 251: /* not local user, will be forwarded */ + return MAILSMTP_NO_ERROR; + + case 550: + case 450: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 551: + return MAILSMTP_ERROR_USER_NOT_LOCAL; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int auth_map_errors(int err) +{ + switch (err) { + case 235: + return MAILSMTP_NO_ERROR; /* AUTH successfull */ + case 334: + return MAILSMTP_NO_ERROR; /* AUTH in progress */ + case 432: + return MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED; + case 454: + return MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE; + case 504: + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + case 530: + return MAILSMTP_ERROR_AUTH_REQUIRED; + case 534: + return MAILSMTP_ERROR_AUTH_TOO_WEAK; + case 538: + return MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED; + default: + /* opportunistic approach ;) */ + return MAILSMTP_NO_ERROR; + } +} + +static int mailsmtp_auth_login(mailsmtp * session, + const char * user, const char * pass) +{ + int err; + char command[SMTP_STRING_SIZE]; + char * user64, * pass64; + + user64 = NULL; + pass64 = NULL; + + user64 = encode_base64(user, strlen(user)); + if (user64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + pass64 = encode_base64(pass, strlen(pass)); + if (pass64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", user64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) + goto err_free; + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", pass64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + + err_free: + free(user64); + free(pass64); + + return err; +} + +static int mailsmtp_auth_plain(mailsmtp * session, + const char * user, const char * pass) +{ + int err, len; + char command[SMTP_STRING_SIZE]; + char * plain, * plain64; + + len = strlen(user) + strlen(pass) + 3; + plain = (char *) malloc(len); + if (plain == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err; + } + + snprintf(plain, len, "%c%s%c%s", '\0', user, '\0', pass); + plain64 = encode_base64(plain, len - 1); + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", plain64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + + err = read_response(session); + err = auth_map_errors(err); + +err_free: + free(plain64); + free(plain); + + err: + return err; +} + +static char * convert_hex(unsigned char *in, int len) +{ + static char hex[] = "0123456789abcdef"; + char * out; + int i; + + out = (char *) malloc(len * 2 + 1); + if (out == NULL) + return NULL; + + for (i = 0; i < len; i++) { + out[i * 2] = hex[in[i] >> 4]; + out[i * 2 + 1] = hex[in[i] & 15]; + } + + out[i*2] = 0; + + return out; +} + +static char * hash_md5(const char * sec_key, const char * data, int len) +{ + char key[65], digest[24]; + char * hash_hex; + + int sec_len, i; + + sec_len = strlen(sec_key); + + if (sec_len < 64) { + memcpy(key, sec_key, sec_len); + for (i = sec_len; i < 64; i++) { + key[i] = 0; + } + } else { + memcpy(key, sec_key, 64); + } + + hmac_md5(data, len, key, 64, digest); + hash_hex = convert_hex(digest, 16); + + return hash_hex; +} + +static int mailsmtp_auth_cram_md5(mailsmtp * session, + const char * user, const char * pass) +{ + int err; + char command[SMTP_STRING_SIZE]; + char *response, *auth_hex, *auth; + + response = decode_base64(session->response, strlen(session->response)); + if (response == NULL) return MAILSMTP_ERROR_MEMORY; + + auth_hex = hash_md5(pass, response, strlen(response)); + if (auth_hex == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free_response; + } + + snprintf(command, SMTP_STRING_SIZE, "%s %s", user, auth_hex); + + auth = encode_base64(command, strlen(command)); + if (auth == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free_auth_hex; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", auth); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + + err = read_response(session); + err = auth_map_errors(err); + +err_free: + free(auth); +err_free_auth_hex: + free(auth_hex); +err_free_response: + free(response); + return err; +} + +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type) +{ + int err; + char command[SMTP_STRING_SIZE]; + + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + snprintf(command, SMTP_STRING_SIZE, "AUTH LOGIN\r\n"); + break; + case MAILSMTP_AUTH_PLAIN: + snprintf(command, SMTP_STRING_SIZE, "AUTH PLAIN\r\n"); + break; + case MAILSMTP_AUTH_CRAM_MD5: + snprintf(command, SMTP_STRING_SIZE, "AUTH CRAM-MD5\r\n"); + break; + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } + + err = send_command(session, command); + if (err == -1) return MAILSMTP_ERROR_STREAM; + + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) return err; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + return mailsmtp_auth_login(session, user, pass); + case MAILSMTP_AUTH_PLAIN: + return mailsmtp_auth_plain(session, user, pass); + case MAILSMTP_AUTH_CRAM_MD5: + return mailsmtp_auth_cram_md5(session, user, pass); + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } +} + + +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass) +{ + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if (session->auth & MAILSMTP_AUTH_CRAM_MD5) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_CRAM_MD5); + } else if (session->auth & MAILSMTP_AUTH_PLAIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_PLAIN); + } else if (session->auth & MAILSMTP_AUTH_LOGIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_LOGIN); + } else { + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + } +} + +/* TODO: add mailesmtp_etrn, mailssmtp_expn */ + +int mailesmtp_starttls(mailsmtp * session) { + int r; + + if (!(session->esmtp & MAILSMTP_ESMTP_STARTTLS)) + return MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED; + + r = send_command(session, "STARTTLS\r\n"); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 220: + return MAILSMTP_NO_ERROR; + + case 454: + return MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int parse_response(mailsmtp * session, + char * response) +{ + char * message; + int code; + int cont = 0; + + code = strtol(response, &message, 10); + if (* message == ' ') + mmap_string_append(session->response_buffer, message + 1); + else if (* message == '-') { + cont = SMTP_STATUS_CONTINUE; + mmap_string_append(session->response_buffer, message + 1); + } + else + mmap_string_append(session->response_buffer, message); + + return code | cont; +} + +static char * read_line(mailsmtp * session) +{ + return mailstream_read_line_remove_eol(session->stream, + session->line_buffer); +} + +static int read_response(mailsmtp * session) +{ + char * line; + int code; + + mmap_string_assign(session->response_buffer, ""); + + do { + line = read_line(session); + + if (line != NULL) { + code = parse_response(session, line); + mmap_string_append_c(session->response_buffer, '\n'); + } + else + code = 0; + } + while ((code & SMTP_STATUS_CONTINUE) != 0); + + session->response = session->response_buffer->str; + + return code; +} + + + + + +static int send_command(mailsmtp * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->stream); + if (r == -1) + return -1; + + return 0; +} + +static int send_data(mailsmtp * session, const char * message, size_t size) +{ + if (mailstream_send_data(session->stream, message, size, + session->progr_rate, session->progr_fun) == -1) + return -1; + + if (mailstream_flush(session->stream) == -1) + return -1; + + return 0; +} + + +const char * mailsmtp_strerror(int errnum) +{ + switch (errnum) { + case MAILSMTP_NO_ERROR: + return "No error"; + case MAILSMTP_ERROR_UNEXPECTED_CODE: + return "Unexpected error code"; + case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: + return "Service not available"; + case MAILSMTP_ERROR_STREAM: + return "Stream error"; + case MAILSMTP_ERROR_HOSTNAME: + return "gethostname() failed"; + case MAILSMTP_ERROR_NOT_IMPLEMENTED: + return "Not implemented"; + case MAILSMTP_ERROR_ACTION_NOT_TAKEN: + return "Error, action not taken"; + case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: + return "Data exceeds storage allocation"; + case MAILSMTP_ERROR_IN_PROCESSING: + return "Error in processing"; + case MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: + return "Insufficient system storage"; + case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: + return "Mailbox unavailable"; + case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: + return "Mailbox name not allowed"; + case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: + return "Bad command sequence"; + case MAILSMTP_ERROR_USER_NOT_LOCAL: + return "User not local"; + case MAILSMTP_ERROR_TRANSACTION_FAILED: + return "Transaction failed"; + case MAILSMTP_ERROR_MEMORY: + return "Memory error"; + case MAILSMTP_ERROR_CONNECTION_REFUSED: + return "Connection refused"; + case MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: + return "TLS not available on server for temporary reason"; + case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: + return "TLS not supported by server"; + default: + return "Unknown error code"; + } +} diff --git a/kmicromail/libetpan/smtp/mailsmtp.h b/kmicromail/libetpan/smtp/mailsmtp.h new file mode 100644 index 0000000..548a5b7 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp.h @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_H + +#define MAILSMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun); +void mailsmtp_free(mailsmtp * session); + +int mailsmtp_connect(mailsmtp * session, mailstream * s); +int mailsmtp_quit(mailsmtp * session); + +/** + * Tries AUTH with detected method - "better" method first: + * CRAM-MD5 -> PLAIN -> LOGIN + */ +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass); + +/** + * tries to autenticate with the server using given auth-type + * returns MAILSMTP_NO_ERROR on success + */ +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type); + +int mailsmtp_helo(mailsmtp * session); +int mailsmtp_mail(mailsmtp * session, const char * from); +int mailsmtp_rcpt(mailsmtp * session, const char * to); +int mailsmtp_data(mailsmtp * session); +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size); +int mailesmtp_ehlo(mailsmtp * session); +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid); +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt); +int mailesmtp_starttls(mailsmtp * session); + +const char * mailsmtp_strerror(int errnum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/smtp/mailsmtp_helper.c b/kmicromail/libetpan/smtp/mailsmtp_helper.c new file mode 100644 index 0000000..32d6564 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_helper.c @@ -0,0 +1,232 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailsmtp.h" +#include +#include +#include "mail.h" + +int mailsmtp_init(mailsmtp * session) +{ + int r; + session->esmtp = 0; + r = mailesmtp_ehlo(session); + + if (r == MAILSMTP_NO_ERROR) { + // session->esmtp = TRUE; + return MAILSMTP_NO_ERROR; + } + + r = mailsmtp_helo(session); + /* if (r == MAILSMTP_NO_ERROR) { */ +/* session->esmtp = FALSE; */ +/* return MAILSMTP_NO_ERROR; */ +/* } */ + + return r; +} + + + +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + if (!session->esmtp) + return mailsmtp_send(session, from, addresses, message, size); + + r = mailesmtp_mail(session, from, return_full, envid); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailesmtp_rcpt(session, addr->address, addr->notify, addr->orcpt); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + r = mailsmtp_mail(session, from); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailsmtp_rcpt(session, addr->address); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + + + + + + + + + + + + + +/* esmtp addresses and smtp addresses */ + +static struct esmtp_address * esmtp_address_new(char * addr, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + + esmtpa = malloc(sizeof(* esmtpa)); + if (esmtpa == NULL) + return NULL; + + esmtpa->address = strdup(addr); + if (esmtpa->address == NULL) { + free(esmtpa); + return NULL; + } + + if (orcpt != NULL) { + esmtpa->orcpt = strdup(orcpt); + if (esmtpa->orcpt == NULL) { + free(esmtpa->address); + free(esmtpa); + return NULL; + } + } + else + esmtpa->orcpt = NULL; + + esmtpa->notify = notify; + + return esmtpa; +} + +static void esmtp_address_free(struct esmtp_address * addr) +{ + if (addr->orcpt) + free(addr->orcpt); + if (addr->address) + free(addr->address); + + free(addr); +} + +clist * esmtp_address_list_new() +{ + return clist_new(); +} + +void esmtp_address_list_free(clist * l) +{ + clist_foreach(l, (clist_func) esmtp_address_free, NULL); + clist_free(l); +} + +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + int r; + + esmtpa = esmtp_address_new(address, notify, orcpt); + if (esmtpa == NULL) + return -1; + + r = clist_append(list, esmtpa); + if (r < 0) { + esmtp_address_free(esmtpa); + return -1; + } + + return 0; +} + +clist * smtp_address_list_new() +{ + return esmtp_address_list_new(); +} + +int smtp_address_list_add(clist * list, char * address) +{ + return esmtp_address_list_add(list, address, 0, NULL); +} + +void smtp_address_list_free(clist * l) +{ + esmtp_address_list_free(l); +} diff --git a/kmicromail/libetpan/smtp/mailsmtp_helper.h b/kmicromail/libetpan/smtp/mailsmtp_helper.h new file mode 100644 index 0000000..6bbe3c9 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_helper.h @@ -0,0 +1,74 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_HELPER_H + +#define MAILSMTP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailsmtp_types.h" +#include "clist.h" + +int mailsmtp_init(mailsmtp * session); + +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size); + +clist * esmtp_address_list_new(); +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt); +void esmtp_address_list_free(clist * l); + +clist * smtp_address_list_new(); +int smtp_address_list_add(clist * list, char * address); +void smtp_address_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/smtp/mailsmtp_socket.c b/kmicromail/libetpan/smtp/mailsmtp_socket.c new file mode 100644 index 0000000..b847bf2 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_socket.c @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_SMTP_PORT 25 +#define SERVICE_NAME_SMTP "smtp" +#define SERVICE_TYPE_TCP "tcp" + +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTP_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILSMTP_ERROR_MEMORY; + } + + return mailsmtp_connect(session, stream); +} + +int mailsmtp_socket_starttls(mailsmtp * session) { + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + + r = mailesmtp_starttls(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + low = mailstream_get_low(session->stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAILSMTP_ERROR_STREAM; + + new_low = mailstream_low_ssl_open(fd); + if (new_low == NULL) + return MAILSMTP_ERROR_STREAM; + + mailstream_low_free(low); + mailstream_set_low(session->stream, new_low); + + return MAILSMTP_NO_ERROR; +} diff --git a/kmicromail/libetpan/smtp/mailsmtp_socket.h b/kmicromail/libetpan/smtp/mailsmtp_socket.h new file mode 100644 index 0000000..6691d9e --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_socket.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_SOCKET_H + +#define MAILSMTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port); +int mailsmtp_socket_starttls(mailsmtp * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/smtp/mailsmtp_ssl.c b/kmicromail/libetpan/smtp/mailsmtp_ssl.c new file mode 100644 index 0000000..eea31de --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_ssl.c @@ -0,0 +1,74 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "connect.h" +#include +#include + +#define DEFAULT_SMTPS_PORT 465 +#define SERVICE_NAME_SMTPS "smtps" +#define SERVICE_TYPE_TCP "tcp" + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTPS_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILSMTP_ERROR_CONNECTION_REFUSED; + } + + return mailsmtp_connect(session, stream); +} diff --git a/kmicromail/libetpan/smtp/mailsmtp_ssl.h b/kmicromail/libetpan/smtp/mailsmtp_ssl.h new file mode 100644 index 0000000..9de9732 --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_ssl.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_SSL_H + +#define MAILSMTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/smtp/mailsmtp_types.h b/kmicromail/libetpan/smtp/mailsmtp_types.h new file mode 100644 index 0000000..b63d5ea --- a/dev/null +++ b/kmicromail/libetpan/smtp/mailsmtp_types.h @@ -0,0 +1,126 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSMTP_TYPES_H + +#define MAILSMTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" +#include "mmapstring.h" + +enum { + MAILSMTP_NO_ERROR = 0, + MAILSMTP_ERROR_UNEXPECTED_CODE, + MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE, + MAILSMTP_ERROR_STREAM, + MAILSMTP_ERROR_HOSTNAME, + MAILSMTP_ERROR_NOT_IMPLEMENTED, + MAILSMTP_ERROR_ACTION_NOT_TAKEN, + MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION, + MAILSMTP_ERROR_IN_PROCESSING, + MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE, + MAILSMTP_ERROR_MAILBOX_UNAVAILABLE, + MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED, + MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND, + MAILSMTP_ERROR_USER_NOT_LOCAL, + MAILSMTP_ERROR_TRANSACTION_FAILED, + MAILSMTP_ERROR_MEMORY, + MAILSMTP_ERROR_AUTH_NOT_SUPPORTED, + MAILSMTP_ERROR_AUTH_LOGIN, + MAILSMTP_ERROR_AUTH_REQUIRED, + MAILSMTP_ERROR_AUTH_TOO_WEAK, + MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED, + MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE, + MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED, + MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE, + MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED, + MAILSMTP_ERROR_CONNECTION_REFUSED +}; + +enum { + MAILSMTP_AUTH_NOT_CHECKED = 0, + MAILSMTP_AUTH_CHECKED = 1, + MAILSMTP_AUTH_CRAM_MD5 = 2, + MAILSMTP_AUTH_PLAIN = 4, + MAILSMTP_AUTH_LOGIN = 8 +}; + +enum { + MAILSMTP_ESMTP = 1, + MAILSMTP_ESMTP_EXPN = 2, + MAILSMTP_ESMTP_8BITMIME = 4, + MAILSMTP_ESMTP_SIZE = 8, + MAILSMTP_ESMTP_ETRN = 16, + MAILSMTP_ESMTP_STARTTLS = 32, + MAILSMTP_ESMTP_DSN = 64, +}; + +struct mailsmtp { + mailstream * stream; + + size_t progr_rate; + progress_function * progr_fun; + + char * response; + + MMAPString * line_buffer; + MMAPString * response_buffer; + + int esmtp; // contains flags MAILSMTP_ESMTP_* + int auth; // contains flags MAILSMTP_AUTH_* +}; + +typedef struct mailsmtp mailsmtp; + +#define MAILSMTP_DSN_NOTIFY_SUCCESS 1 +#define MAILSMTP_DSN_NOTIFY_FAILURE 2 +#define MAILSMTP_DSN_NOTIFY_DELAY 4 +#define MAILSMTP_DSN_NOTIFY_NEVER 8 + +struct esmtp_address { + char * address; + int notify; + char * orcpt; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tests/README b/kmicromail/libetpan/tests/README new file mode 100644 index 0000000..66d8b2f --- a/dev/null +++ b/kmicromail/libetpan/tests/README @@ -0,0 +1,58 @@ +compose-msg +----------- + +creates a RFC 2822 message with MIME parts + +syntax: compose-msg "text" filename + + + +all the following programs will take as argument : + + --driver=(pop3|imap|nntp|mbox|mh) -d pop3 (pop3|imap|nntp|mbox|mh) + + default driver is mbox + + --server={server-name} -s {server-name} + --port={port-number} -p {port-number} + --tls -t + --starttls -x + --user={login} -u {login} + --password={password} -v {password} + --path={mailbox} -l {mailbox} + --apop -a + --cache={directory} -c {directory} + +the default driver is mbox with the path /var/mail/$USER + +frm-simple, frm, frm-tree +------------------------- + +frm-simple will list all the mails of a mailbox without any MIME decoding. + +frm will list all the mails of a mailbox and will decode the fields. + +frm-tree will do the same thing as frm and will also show the threads + of the folder. + + +fetch-attachment +---------------- + + fetch-attachment gets all the named attachment of the given message +of the chosen mailbox and writes them on the current directory. + + The program should be given message numbers (as given by frm) as +additionnal arguments. + + +readmsg-simple, readmsg +----------------------- + + readmsg-simple will display the content of the given messages. +All the content (headers and body) will be displayed. + + readmsg will display only the text parts of the given messages. + + The program should be given message numbers (as given by frm) as +additionnal arguments. diff --git a/kmicromail/libetpan/tests/compose-msg.c b/kmicromail/libetpan/tests/compose-msg.c new file mode 100644 index 0000000..f68660b --- a/dev/null +++ b/kmicromail/libetpan/tests/compose-msg.c @@ -0,0 +1,317 @@ +#include +#include +#include + +#define DEST_CHARSET "iso-8859-1" + +/* build a mime parameter */ + +static struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} + + +/* build sample fields */ + +static struct mailimf_fields * build_fields(void) +{ + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + char * subject; + int r; + struct mailimf_fields * new_fields; + + /* subject field */ + + subject = strdup("this is a sample"); + if (subject == NULL) { + goto err; + } + + /* from field */ + + from = mailimf_mailbox_list_new_empty(); + if (from == NULL) { + goto free_subject; + } + + r = mailimf_mailbox_list_add_parse(from, + "DINH Viet Hoa "); + if (r != MAILIMF_NO_ERROR) { + goto free_from; + } + + /* to field */ + + to = mailimf_address_list_new_empty(); + if (to == NULL) { + goto free_from; + } + + r = mailimf_address_list_add_parse(to, + "Paul "); + if (r != MAILIMF_NO_ERROR) { + goto free_to; + } + + new_fields = mailimf_fields_new_with_data(from /* from */, + NULL /* sender */, NULL /* reply-to */, + to, NULL /* cc */, NULL /* bcc */, NULL /* in-reply-to */, + NULL /* references */, + subject); + if (new_fields == NULL) + goto free_to; + + return new_fields; + + free_to: + mailimf_address_list_free(to); + free_from: + mailimf_mailbox_list_free(from); + free_subject: + free(subject); + err: + return NULL; +} + + + +/* text is a string, build a mime part containing this string */ + +static struct mailmime * build_body_text(char * text) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + int r; + + /* text/plain part */ + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) { + goto err; + } + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + r = mailmime_set_body_text(mime_sub, text, strlen(text)); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + +/* build a mime part containing the given file */ + +static struct mailmime * build_body_file(char * filename) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + char * dup_filename; + int r; + + /* text/plain part */ + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto err; + + mime_fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + dup_filename, MAILMIME_MECHANISM_BASE64); + if (mime_fields == NULL) + goto free_dup_filename; + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto free_mime; + + r = mailmime_set_body_file(mime_sub, dup_filename); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + goto err; + free_dup_filename: + free(dup_filename); + err: + return NULL; +} + + +/* build an empty message */ + +static struct mailmime * build_message(struct mailimf_fields * fields) +{ + struct mailmime * mime; + + /* message */ + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + goto err; + } + + mailmime_set_imf_fields(mime, fields); + + return mime; + + err: + return NULL; +} + + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + char * text; + char * filename; + struct mailmime * message; + struct mailmime * text_part; + struct mailmime * file_part; + int r; + int col; + + if (argc < 3) { + printf("syntax: compose-msg \"text\" filename\n"); + return 1; + } + + fields = build_fields(); + if (fields == NULL) + goto err; + + message = build_message(fields); + if (message == NULL) + goto free_fields; + + text = argv[1]; + text_part = build_body_text(text); + if (text_part == NULL) + goto free_message; + + filename = argv[2]; + file_part = build_body_file(filename); + if (file_part == NULL) + goto free_text; + + r = mailmime_smart_add_part(message, text_part); + if (r != MAILIMF_NO_ERROR) + goto free_file; + + r = mailmime_smart_add_part(message, file_part); + if (r != MAILIMF_NO_ERROR) + goto free_file_alone; + + col = 0; + mailmime_write(stdout, &col, message); + + mailmime_free(message); + + return 0; + + free_file_alone: + mailmime_free(file_part); + goto free_text; + free_file: + mailmime_free(file_part); + free_text: + mailmime_free(text_part); + free_message: + mailmime_free(message); + goto err; + free_fields: + mailimf_fields_free(fields); + err: + printf("error memory\n"); + return 1; +} diff --git a/kmicromail/libetpan/tests/fetch-attachment.c b/kmicromail/libetpan/tests/fetch-attachment.c new file mode 100644 index 0000000..a79ef8b --- a/dev/null +++ b/kmicromail/libetpan/tests/fetch-attachment.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include + +#include + +#include "option-parser.h" +#include "readmsg-common.h" + +/* write content to the given filename */ + +static int etpan_write_data(char * filename, char * data, size_t len) +{ + size_t write_len; + FILE * f; + int res; + mode_t old_umask; + + old_umask = umask(0077); + f = fopen(filename, "w"); + umask(old_umask); + if (f == NULL) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len < len) { + res = ERROR_FILE; + goto close; + } + + fclose(f); + + return NO_ERROR; + + close: + fclose(f); + err: + return res; +} + + +/* save attachment */ + +static int save_mime_content(mailmessage * msg_info, + struct mailmime * mime_part) +{ + char * body; + size_t body_len; + int r; + char * filename; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime_part->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime_part->mm_mime_fields, + mime_part->mm_content_type); + + filename = fields.fld_disposition_filename; + + if (filename == NULL) + filename = fields.fld_content_name; + + if (filename == NULL) + return ERROR_INVAL; + + r = etpan_fetch_message(msg_info, mime_part, &fields, &body, &body_len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + printf("writing %s, %i bytes\n", filename, body_len); + + r = etpan_write_data(filename, body, body_len); + if (r != NO_ERROR) { + res = r; + goto free; + } + + mailmime_decoded_part_free(body); + + return NO_ERROR; + + free: + mailmime_decoded_part_free(body); + err: + return res; +} + + + +/* fetch attachments */ + +static int etpan_fetch_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + save_mime_content(msg_info, mime); + + break; + + case MAILMIME_MULTIPLE: + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_fetch_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_fetch_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_fetch_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/frm-common.c b/kmicromail/libetpan/tests/frm-common.c new file mode 100644 index 0000000..eeeadf0 --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-common.c @@ -0,0 +1,158 @@ +#include "frm-common.h" + +#include +#include + +#define DEST_CHARSET "iso-8859-1" + +/* get part of the from field to display */ + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr) +{ + struct mailimf_mailbox * mb; + + if (fields->fld_from == NULL) { + * from = NULL; + * is_addr = 0; + return; + } + + if (clist_isempty(fields->fld_from->frm_mb_list->mb_list)) { + * from = NULL; + * is_addr = 0; + return; + } + + mb = clist_begin(fields->fld_from->frm_mb_list->mb_list)->data; + + if (mb->mb_display_name != NULL) { + * from = mb->mb_display_name; + * is_addr = 0; + } + else { + * from = mb->mb_addr_spec; + * is_addr = 1; + } +} + +/* remove all CR and LF of a string and replace them with SP */ + +void strip_crlf(char * str) +{ + char * p; + + for(p = str ; * p != '\0' ; p ++) { + if ((* p == '\n') || (* p == '\r')) + * p = ' '; + } +} + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +void print_mail_info(char * prefix, mailmessage * msg) +{ + char * from; + char * subject; + char * decoded_from; + char * decoded_subject; + size_t cur_token; + int r; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + decoded_subject = NULL; + decoded_from = NULL; + + /* from field */ + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + decoded_from = NULL; + else { + if (!is_addr) { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + from, strlen(from), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(from); + if (decoded_from == NULL) + goto err; + } + } + else { + decoded_from = strdup(from); + if (decoded_from == NULL) { + goto err; + } + } + } + + if (decoded_from == NULL) + dsp_from = ""; + else { + dsp_from = decoded_from; + strip_crlf(dsp_from); + } + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + decoded_subject = NULL; + else { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + goto free_from; + } + } + + if (decoded_subject == NULL) + dsp_subject = ""; + else { + dsp_subject = decoded_subject; + strip_crlf(dsp_subject); + } + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %s%-53.53s", + msg->msg_index, dsp_from, prefix, dsp_subject); + + printf("%s\n", output); + + if (decoded_subject != NULL) + free(decoded_subject); + if (decoded_from != NULL) + free(decoded_from); + + return; + + free_from: + if (decoded_from) + free(decoded_from); + err: +} diff --git a/kmicromail/libetpan/tests/frm-common.h b/kmicromail/libetpan/tests/frm-common.h new file mode 100644 index 0000000..c1a27c2 --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-common.h @@ -0,0 +1,14 @@ +#ifndef FRM_COMMON_H + +#define FRM_COMMON_H + +#include + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr); + +void strip_crlf(char * str); + +void print_mail_info(char * prefix, mailmessage * msg); + +#endif diff --git a/kmicromail/libetpan/tests/frm-simple.c b/kmicromail/libetpan/tests/frm-simple.c new file mode 100644 index 0000000..7c3640f --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-simple.c @@ -0,0 +1,227 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include + +#include +#include + +#define DEST_CHARSET "iso-8859-1" + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +static void simple_print_mail_info(mailmessage * msg) +{ + char * from; + char * subject; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + /* from field */ + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + dsp_from = strdup(""); + else + dsp_from = strdup(from); + if (dsp_from == NULL) + goto err; + + strip_crlf(dsp_from); + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + dsp_subject = strdup(""); + else + dsp_subject = strdup(subject); + + if (dsp_subject == NULL) + goto free_from; + + strip_crlf(dsp_subject); + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %-53.53s\n", + msg->msg_index % 1000, dsp_from, dsp_subject); + + printf("%s\n", output); + + free(dsp_subject); + free(dsp_from); + + return; + + free_from: + free(dsp_from); + err: +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + simple_print_mail_info(msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/frm-tree.c b/kmicromail/libetpan/tests/frm-tree.c new file mode 100644 index 0000000..3a8464a --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-tree.c @@ -0,0 +1,234 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include + +#include +#include + +#define DEST_CHARSET "iso-8859-1" + +/* display tree */ + +static void +display_sub_tree(MMAPString * prefix, + struct mailmessage_tree * msg_tree, + int level, int has_next, unsigned int * pcount) +{ + carray * list; + uint32_t cur; + + if (msg_tree->node_msg != NULL) { + print_mail_info(prefix->str, msg_tree->node_msg); + (* pcount) ++; + } + + list = msg_tree->node_children; + + if (carray_count(list) != 0) { + char old_prefix[2]; + + if (level > 1) { + memcpy(old_prefix, prefix->str + prefix->len - 2, 2); + if (has_next) + memcpy(prefix->str + prefix->len - 2, "| ", 2); + else + memcpy(prefix->str + prefix->len - 2, " ", 2); + } + for(cur = 0 ; cur < carray_count(list) ; cur ++) { + int sub_has_next; + + if (cur != carray_count(list) - 1) { + if (level > 0) { + if (mmap_string_append(prefix, "+-") == NULL) + return; + } + sub_has_next = 1; + } + else { + if (level > 0) { + if (mmap_string_append(prefix, "\\-") == NULL) + return; + } + sub_has_next = 0; + } + + display_sub_tree(prefix, carray_get(list, cur), + level + 1, sub_has_next, pcount); + + if (mmap_string_truncate(prefix, prefix->len - 2) == NULL) { + return; + } + } + if (level > 1) { + memcpy(prefix->str + prefix->len - 2, old_prefix, 2); + } + } +} + +static void display_tree(struct mailmessage_tree * env_tree, + unsigned int * pcount) +{ + MMAPString * prefix; + + prefix = mmap_string_new(""); + if (prefix == NULL) + return; + + display_sub_tree(prefix, env_tree, 0, 0, pcount); + + mmap_string_free(prefix); +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + struct mailmessage_list * env_list; + struct mailmessage_tree * env_tree; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* build threads */ + + r = mail_build_thread(MAIL_THREAD_REFERENCES_NO_SUBJECT, + DEST_CHARSET, + env_list, &env_tree, + mailthread_tree_timecomp); + if (r != MAIL_NO_ERROR) { + printf("can't build tree\n"); + goto free_msg_list; + } + + /* display message tree */ + + count = 0; + display_tree(env_tree, &count); + + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_tree_free_recursive(env_tree); + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/frm.c b/kmicromail/libetpan/tests/frm.c new file mode 100644 index 0000000..8ce9d9b --- a/dev/null +++ b/kmicromail/libetpan/tests/frm.c @@ -0,0 +1,158 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include + +#include +#include + +#define DEST_CHARSET "iso-8859-1" + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + print_mail_info("", msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error connecting folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/option-parser.c b/kmicromail/libetpan/tests/option-parser.c new file mode 100644 index 0000000..57a1597 --- a/dev/null +++ b/kmicromail/libetpan/tests/option-parser.c @@ -0,0 +1,234 @@ +#define _GNU_SOURCE +#include + +#include +#include +#include + +#include + +#include "option-parser.h" + +/* + options + + --driver (pop3|imap|nntp|mbox|mh|maildir) -d + + default driver is mbox + + --server {server-name} -s + --port {port-number} -p + --tls -t + --starttls -x + --user {login} -u + --password {password} -v + --path {mailbox} -l + --apop -a + --cache {directory} -c + --flags {directory} -f +*/ + +struct storage_name { + int id; + char * name; +}; + +static struct storage_name storage_tab[] = { + {POP3_STORAGE, "pop3"}, + {IMAP_STORAGE, "imap"}, + {NNTP_STORAGE, "nntp"}, + {MBOX_STORAGE, "mbox"}, + {MH_STORAGE, "mh"}, + {MAILDIR_STORAGE, "maildir"}, +}; + +static int get_driver(char * name) +{ + int driver_type; + unsigned int i; + + driver_type = -1; + for(i = 0 ; i < sizeof(storage_tab) / sizeof(struct storage_name) ; i++) { + if (strcasecmp(name, storage_tab[i].name) == 0) { + driver_type = i; + break; + } + } + + return driver_type; +} + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory) +{ + int index; + static struct option long_options[] = { + {"driver", 1, 0, 'd'}, + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"tls", 0, 0, 't'}, + {"starttls", 0, 0, 'x'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"path", 1, 0, 'l'}, + {"apop", 0, 0, 'a'}, + {"cache", 1, 0, 'c'}, + {"flags", 1, 0, 'f'}, + }; + int r; + char location[PATH_MAX]; + char * env_user; + + index = 0; + + * driver = MBOX_STORAGE; + * server = NULL; + * port = 0; + * connection_type = CONNECTION_TYPE_PLAIN; + * user = NULL; + * password = NULL; + * auth_type = POP3_AUTH_TYPE_PLAIN; + env_user = getenv("USER"); + if (env_user != NULL) { + snprintf(location, PATH_MAX, "/var/mail/%s", env_user); + * path = strdup(location); + } + else + * path = NULL; + * cache_directory = NULL; + * flags_directory = NULL; + + while (1) { + r = getopt_long(argc, argv, "d:s:p:txu:v:l:ac:f:", long_options, &index); + + if (r == -1) + break; + + switch (r) { + case 'd': + * driver = get_driver(optarg); + break; + case 's': + if (* server != NULL) + free(* server); + * server = strdup(optarg); + break; + case 'p': + * port = strtoul(optarg, NULL, 10); + break; + case 't': + * connection_type = CONNECTION_TYPE_TLS; + break; + case 'x': + * connection_type = CONNECTION_TYPE_STARTTLS; + break; + case 'u': + if (* user != NULL) + free(* user); + * user = strdup(optarg); + break; + case 'v': + if (* password != NULL) + free(* password); + * password = strdup(optarg); + break; + case 'l': + if (* path != NULL) + free(* path); + * path = strdup(optarg); + break; + case 'a': + * auth_type = POP3_AUTH_TYPE_APOP; + break; + case 'c': + if (* cache_directory != NULL) + free(* cache_directory); + * cache_directory = strdup(optarg); + break; + case 'f': + if (* flags_directory != NULL) + free(* flags_directory); + * flags_directory = strdup(optarg); + break; + } + } + + return 0; +} + +int init_storage(struct mailstorage * storage, + int driver, char * server, int port, + int connection_type, char * user, char * password, int auth_type, + char * path, char * cache_directory, char * flags_directory) +{ + int r; + int cached; + + cached = (cache_directory != NULL); + + switch (driver) { + case POP3_STORAGE: + r = pop3_mailstorage_init(storage, server, port, NULL, connection_type, + auth_type, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing POP3 storage\n"); + goto err; + } + break; + + case IMAP_STORAGE: + r = imap_mailstorage_init(storage, server, port, NULL, connection_type, + IMAP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing IMAP storage\n"); + goto err; + } + break; + + case NNTP_STORAGE: + r = nntp_mailstorage_init(storage, server, port, NULL, connection_type, + NNTP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing NNTP storage\n"); + goto err; + } + break; + + case MBOX_STORAGE: + r = mbox_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing mbox storage\n"); + goto err; + } + break; + + case MH_STORAGE: + r = mh_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing MH storage\n"); + goto err; + } + break; + case MAILDIR_STORAGE: + r = maildir_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing maildir storage\n"); + goto err; + } + break; + } + + return MAIL_NO_ERROR; + + err: + return r; +} diff --git a/kmicromail/libetpan/tests/option-parser.h b/kmicromail/libetpan/tests/option-parser.h new file mode 100644 index 0000000..d765332 --- a/dev/null +++ b/kmicromail/libetpan/tests/option-parser.h @@ -0,0 +1,28 @@ +#ifndef OPTION_PARSER + +#define OPTION_PARSER + +#include + +enum { + POP3_STORAGE = 0, + IMAP_STORAGE, + NNTP_STORAGE, + MBOX_STORAGE, + MH_STORAGE, + MAILDIR_STORAGE, +}; + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory); + +int init_storage(struct mailstorage * storage, + int driver, char * server, int port, + int connection_type, char * user, char * password, int auth_type, + char * path, char * cache_directory, char * flags_directory); + +#endif diff --git a/kmicromail/libetpan/tests/readmsg-common.c b/kmicromail/libetpan/tests/readmsg-common.c new file mode 100644 index 0000000..060497d --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-common.c @@ -0,0 +1,720 @@ +#include "readmsg-common.h" + +#include +#include +#include +#include +#include +#include + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* + fetch the data of the mailmime_data structure whether it is a file + or a string. + + data must be freed with mmap_string_unref() +*/ + +#if 0 +static int fetch_data(struct mailmime_data * data, + char ** result, size_t * result_len) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + MMAPString * mmapstr; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + mmapstr = mmap_string_new_len(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = ERROR_MEMORY; + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (text == MAP_FAILED) { + res = ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(text, buf.st_size); + if (mmapstr == NULL) { + res = r; + goto unmap; + } + + munmap(text, buf.st_size); + } + else { + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = r; + goto close; + } + } + + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + default: + return ERROR_INVAL; + } + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; +} +#endif + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_fields_parse(data, len, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + + + +#define MAX_MAIL_COL 72 + +/* write decoded mailbox */ + +static int +etpan_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + * col = 1; + } + } + + if (mb->mb_display_name) { + char * decoded_from; + size_t cur_token; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + mb->mb_display_name, strlen(mb->mb_display_name), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(mb->mb_display_name); + if (decoded_from == NULL) + return ERROR_MEMORY; + } + + r = mailimf_quoted_string_write(f, col, decoded_from, + strlen(decoded_from)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return ERROR_FILE; + } + + if (* col > 1) { + + if (* col + strlen(decoded_from) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return r; + } + * col = 1; + } + } + + free(decoded_from); + + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + + + return NO_ERROR; + +} + +/* write decoded mailbox list */ + +int +etpan_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_mailbox_write(f, col, mb); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded group */ + +static int +etpan_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + if (group->grp_mb_list != NULL) { + r = etpan_mailbox_list_write(f, col, group->grp_mb_list); + if (r != NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + return NO_ERROR; +} + +/* write decoded address */ + +int +etpan_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = etpan_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = etpan_group_write(f, col, addr->ad_data.ad_group); + if (r != NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + +/* write decoded address list */ + +int +etpan_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_address_write(f, col, addr); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded subject */ + +static int etpan_subject_write(FILE * f, int * col, + char * subject) +{ + int r; + char * decoded_subject; + size_t cur_token; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + return ERROR_MEMORY; + } + + r = mailimf_string_write(f, col, decoded_subject, strlen(decoded_subject)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_subject); + return ERROR_FILE; + } + + free(decoded_subject); + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + * col = 0; + + return NO_ERROR; +} + +/* write decoded fields */ + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_FROM: + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_reply_to->rt_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_TO: + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_CC: + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_BCC: + r = mailimf_string_write(f, col, "Bcc: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_SUBJECT: + r = etpan_subject_write(f, col, field->fld_data.fld_subject->sbj_value); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_resent_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + break; + + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_resent_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_ORIG_DATE: + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_OPTIONAL_FIELD: + if ((strcasecmp(field->fld_data.fld_optional_field->fld_name, + "X-Mailer") == 0) + || (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Resent-", 7) == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Newsgroups") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Followup-To") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "User-Agent") == 0)) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + } + break; + + case MAILIMF_FIELD_MESSAGE_ID: + case MAILIMF_FIELD_SENDER: + case MAILIMF_FIELD_IN_REPLY_TO: + case MAILIMF_FIELD_REFERENCES: + default: + break; + } + } + + return NO_ERROR; + + err: + return ERROR_FILE; +} diff --git a/kmicromail/libetpan/tests/readmsg-common.h b/kmicromail/libetpan/tests/readmsg-common.h new file mode 100644 index 0000000..70265f2 --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-common.h @@ -0,0 +1,34 @@ +#ifndef READMSG_COMMON_H + +#define READMSG_COMMON_H + +#include + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +int etpan_mime_is_text(struct mailmime * build_info); + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content); + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len); + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime); + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +#endif diff --git a/kmicromail/libetpan/tests/readmsg-simple.c b/kmicromail/libetpan/tests/readmsg-simple.c new file mode 100644 index 0000000..ea57d6d --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-simple.c @@ -0,0 +1,133 @@ +#include +#include +#include + +#include + +#include "option-parser.h" + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + char * data; + size_t size; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found **\n", msg_num); + optind ++; + continue; + } + + r = mailmessage_fetch(msg, &data, &size); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + fwrite(data, 1, size, stdout); + + mailmessage_fetch_result_free(msg, data); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/readmsg.c b/kmicromail/libetpan/tests/readmsg.c new file mode 100644 index 0000000..822c93c --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg.c @@ -0,0 +1,355 @@ +#include +#include +#include + +#include +#include + +#include "option-parser.h" +#include "readmsg-common.h" + + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_render_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/smtpsend.c b/kmicromail/libetpan/tests/smtpsend.c new file mode 100644 index 0000000..d5229d9 --- a/dev/null +++ b/kmicromail/libetpan/tests/smtpsend.c @@ -0,0 +1,278 @@ +/* + * Simple Mail Submission Agent using SMTP with libEtPan! + * TODO: Full sendmail like interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _GNU_SOURCE +#include + +/* globals */ +char *smtp_server; +uint smtp_port = 25; +char *smtp_user; +char *smtp_password; +char *smtp_from; +int smtp_tls = 0; +int smtp_esmtp = 1; + +struct mem_message { + char *data; + size_t len; + MMAPString *mstring; +}; + +#define BLOCKSIZE 4096 + +int collect(struct mem_message *message) { + struct stat sb; + int len; + + memset(message, 0, sizeof(struct mem_message)); + + /* if stdin is a file whose size is known, try to mmap it */ + if (!fstat(0, &sb) && S_ISREG(sb.st_mode) && sb.st_size >= 0) { + message->len = sb.st_size; + if ((message->data = mmap(NULL, message->len, PROT_READ, MAP_SHARED, + STDIN_FILENO, 0)) != MAP_FAILED) + return 0; + } + + /* read the buffer from stdin by blocks, until EOF or error. + save the message in a mmap_string */ + if ((message->mstring = mmap_string_sized_new(BLOCKSIZE)) == NULL) { + perror("mmap_string_new"); + goto error; + } + message->len = 0; + + while ((len = read(STDIN_FILENO, + message->mstring->str + message->len, BLOCKSIZE)) > 0) { + message->len += len; + /* reserve room for next block */ + if ((mmap_string_set_size(message->mstring, + message->len + BLOCKSIZE)) == NULL) { + perror("mmap_string_set_size"); + goto error; + } + } + + if (len == 0) { + message->data = message->mstring->str; + return 0; /* OK */ + } + + perror("read"); + + error: + if (message->mstring != NULL) + mmap_string_free(message->mstring); + return -1; +} + +char *guessfrom() { + uid_t uid; + struct passwd *pw; + char hostname[256]; + int len; + char *gfrom; + + if (gethostname(hostname, sizeof(hostname))) { + perror("gethostname"); + return NULL; + } + hostname[sizeof(hostname) - 1] = '\0'; + + uid = getuid(); + pw = getpwuid(uid); + + len = ((pw != NULL) ? strlen(pw->pw_name) : 12) + + strlen(hostname) + 2; + + if ((gfrom = malloc(len)) == NULL) { + perror("malloc"); + return NULL; + } + if (pw != NULL && pw->pw_name != NULL) + snprintf(gfrom, len, "%s@%s", pw->pw_name, hostname); + else + snprintf(gfrom, len, "#%u@%s", uid, hostname); + return gfrom; +} + +void release(struct mem_message *message) { + if (message->mstring != NULL) + mmap_string_free(message->mstring); + else if (message->data != NULL) + munmap(message->data, message->len); +} + +int send_message(char *data, size_t len, char**rcpts) { + int s = -1; + int ret; + char **r; + int esmtp = 0; + mailsmtp *smtp = NULL; + + if ((smtp = mailsmtp_new(0, NULL)) == NULL) { + perror("mailsmtp_new"); + goto error; + } + + /* first open the stream */ + if ((ret = mailsmtp_socket_connect(smtp, + (smtp_server != NULL ? smtp_server : "localhost"), + smtp_port)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_socket_connect: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + /* then introduce ourselves */ + if (smtp_esmtp && (ret = mailesmtp_ehlo(smtp)) == MAILSMTP_NO_ERROR) + esmtp = 1; + else if (!smtp_esmtp || ret == MAILSMTP_ERROR_NOT_IMPLEMENTED) + ret = mailsmtp_helo(smtp); + if (ret != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_helo: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_tls && + (ret = mailsmtp_socket_starttls(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_starttls: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_user != NULL && + (ret = mailsmtp_auth(smtp, smtp_user, + (smtp_password != NULL) ? smtp_password : "")) + != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_auth: %s: %s\n", smtp_user, mailsmtp_strerror(ret)); + goto error; + } + + /* source */ + if ((ret = (esmtp ? + mailesmtp_mail(smtp, smtp_from, 1, "etPanSMTPTest") : + mailsmtp_mail(smtp, smtp_from))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_mail: %s, %s\n", smtp_from, mailsmtp_strerror(ret)); + goto error; + } + + /* recipients */ + for (r = rcpts; *r != NULL; r++) { + if ((ret = (esmtp ? + mailesmtp_rcpt(smtp, *r, + MAILSMTP_DSN_NOTIFY_FAILURE|MAILSMTP_DSN_NOTIFY_DELAY, + NULL) : + mailsmtp_rcpt(smtp, *r))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_rcpt: %s: %s\n", *r, mailsmtp_strerror(ret)); + goto error; + } + } + + /* message */ + if ((ret = mailsmtp_data(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data: %s\n", mailsmtp_strerror(ret)); + goto error; + } + if ((ret = mailsmtp_data_message(smtp, data, len)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data_message: %s\n", mailsmtp_strerror(ret)); + goto error; + } + mailsmtp_free(smtp); + return 0; + + error: + if (smtp != NULL) + mailsmtp_free(smtp); + if (s >= 0) + close(s); + return -1; +} + +int main(int argc, char **argv) { + struct mem_message message; + int index, r; + + static struct option long_options[] = { + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"from", 1, 0, 'f'}, + {"tls", 0, 0, 'S'}, + {"no-esmtp", 0, 0, 'E'}, + }; + + while(1) { + if ((r = getopt_long(argc, argv, "s:p:u:v:f:SE", long_options, &index)) < 0) + break; + switch (r) { + case 's': + if (smtp_server != NULL) + free(smtp_server); + smtp_server = strdup(optarg); + break; + case 'p': + smtp_port = strtoul(optarg, NULL, 10); + break; + case 'u': + if (smtp_user != NULL) + free(smtp_user); + smtp_user = strdup(optarg); + break; + case 'v': + if (smtp_password != NULL) + free(smtp_password); + smtp_password = strdup(optarg); + break; + case 'f': + if (smtp_from != NULL) + free(smtp_from); + smtp_from = strdup(optarg); + break; + case 'S': + smtp_tls = 1; + break; + case 'E': + smtp_esmtp = 0; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + fprintf(stderr, "usage: smtpsend [-f from] [-u user] [-v password] [-s server] [-p port] [-S] ...\n"); + return EXIT_FAILURE; + } + + if (smtp_from == NULL && (smtp_from = guessfrom()) == NULL) { + fprintf(stderr, "can't guess a valid from, please use -f option.\n"); + return EXIT_FAILURE; + } + + /* reads message from stdin */ + if (collect(&message)) + return EXIT_FAILURE; + + send_message(message.data, message.len, argv); + + release(&message); + return EXIT_SUCCESS; +} diff --git a/kmicromail/libetpan/tools/.libs/libtools.a b/kmicromail/libetpan/tools/.libs/libtools.a new file mode 100644 index 0000000..43424ef --- a/dev/null +++ b/kmicromail/libetpan/tools/.libs/libtools.a Binary files differ diff --git a/kmicromail/libetpan/tools/base64.c b/kmicromail/libetpan/tools/base64.c new file mode 100644 index 0000000..1532bac --- a/dev/null +++ b/kmicromail/libetpan/tools/base64.c @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "base64.h" + +#include + +#define OUTPUT_SIZE 513 +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +static char index_64[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +char * encode_base64(const char * in, int len) +{ + char * output, * tmp; + unsigned char oval; + int out_len; + + out_len = ((len + 2) / 3 * 4) + 1; + + if ((len > 0) && (in == NULL)) + return NULL; + + output = malloc(out_len); + if (!output) + return NULL; + + tmp = output; + while (len >= 3) { + *tmp++ = basis_64[in[0] >> 2]; + *tmp++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *tmp++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *tmp++ = basis_64[in[2] & 0x3f]; + in += 3; + len -= 3; + } + if (len > 0) { + *tmp++ = basis_64[in[0] >> 2]; + oval = (in[0] << 4) & 0x30; + if (len > 1) oval |= in[1] >> 4; + *tmp++ = basis_64[oval]; + *tmp++ = (len < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c]; + *tmp++ = '='; + } + + *tmp = '\0'; + + return output; +} + +char * decode_base64(const char * in, int len) +{ + char * output, * out; + int i, c1, c2, c3, c4, out_len; + + out_len = 0; + + output = malloc(OUTPUT_SIZE); + if (output == NULL) + return NULL; + out = output; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + + for (i = 0; i < (len / 4); i++) { + c1 = in[0]; + c2 = in[1]; + c3 = in[2]; + c4 = in[3]; + if (CHAR64(c1) == -1 || CHAR64(c2) == -1 || + (c3 != '=' && CHAR64(c3) == -1) || + (c4 != '=' && CHAR64(c4) == -1)) + return NULL; + + in += 4; + *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c3 != '=') { + *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c4 != '=') { + *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + } + } + } + + *output = 0; + + return out; +} + + diff --git a/kmicromail/libetpan/tools/base64.h b/kmicromail/libetpan/tools/base64.h new file mode 100644 index 0000000..aa5f3e5 --- a/dev/null +++ b/kmicromail/libetpan/tools/base64.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef BASE64_H +#define BASE64_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * creates (malloc) a new base64 encoded string from a standard 8bit string + * don't forget to free it when time comes ;) + */ +char * encode_base64(const char * in, int len); + +/** + * creates (malloc) a new standard 8bit string from an base64 encoded string + * don't forget to free it when time comes ;) + */ +char * decode_base64(const char * in, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/carray.c b/kmicromail/libetpan/tools/carray.c new file mode 100644 index 0000000..a8e78c9 --- a/dev/null +++ b/kmicromail/libetpan/tools/carray.c @@ -0,0 +1,143 @@ + +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include +#include +#include "carray.h" + +carray * carray_new(unsigned int initsize) { + carray * array; + + array = (carray *) malloc(sizeof(carray)); + if (!array) return NULL; + + array->len = 0; + array->max = initsize; + array->array = (void **) malloc(sizeof(void *) * initsize); + if (!array->array) { + free(array); + return NULL; + } + return array; +} + +int carray_add(carray * array, void * data, unsigned int * index) { + int r; + + r = carray_set_size(array, array->len + 1); + if (r < 0) + return r; + + array->array[array->len - 1] = data; + if (index != NULL) + * index = array->len - 1; + + return 0; +} + +int carray_set_size(carray * array, unsigned int new_size) +{ + if (new_size > array->max) { + unsigned int n = array->max * 2; + void * new; + + while (n <= new_size) + n *= 2; + + new = (void **) realloc(array->array, sizeof(void *) * n); + if (!new) + return -1; + array->array = new; + array->max = n; + } + array->len = new_size; + + return 0; +} + +int carray_delete_fast(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + array->array[indx] = NULL; + + return 0; +} + +int carray_delete(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + array->array[indx] = array->array[array->len]; + return 0; +} + +int carray_delete_slow(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + memmove(array->array + indx, array->array + indx + 1, + (array->len - indx) * sizeof(void *)); + return 0; +} + +#ifdef NO_MACROS +void ** carray_data(carray * array) { + return array->array; +} + +unsigned int carray_count(carray * array) { + return array->len; +} + +void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +void carray_set(carray * array, unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +void carray_free(carray * array) { + free(array->array); + free(array); +} diff --git a/kmicromail/libetpan/tools/carray.h b/kmicromail/libetpan/tools/carray.h new file mode 100644 index 0000000..06003aa --- a/dev/null +++ b/kmicromail/libetpan/tools/carray.h @@ -0,0 +1,124 @@ + +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CARRAY_H +#define CARRAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct carray_s { + void ** array; + unsigned int len; + unsigned int max; +}; + +typedef struct carray_s carray; + +/* Creates a new array of pointers, with initsize preallocated cells */ +carray * carray_new(unsigned int initsize); + +/* Adds the pointer to data in the array. + Returns the index of the pointer in the array or -1 on error */ +int carray_add(carray * array, void * data, unsigned int * index); + +int carray_set_size(carray * array, unsigned int new_size); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS changed. */ +int carray_delete(carray * array, unsigned int indx); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS not changed. */ +int carray_delete_slow(carray * array, unsigned int indx); + +/* remove without decreasing the size of the array */ +int carray_delete_fast(carray * array, unsigned int indx); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns the array itself */ +void ** carray_data(carray *); + +/* Returns the number of elements in the array */ +int carray_count(carray *); + +/* Returns the contents of one cell */ +void * carray_get(carray * array, unsigned int indx); + +/* Sets the contents of one cell */ +void carray_set(carray * array, unsigned int indx, void * value); + +#else + +#if 0 +#define carray_data(a) (a->array) +#define carray_count(a) (a->len) +#define carray_get(a, indx) (a->array[indx]) +#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0) +#endif + +static inline void ** carray_data(carray * array) { + return array->array; +} + +static inline unsigned int carray_count(carray * array) { + return array->len; +} + +static inline void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +static inline void carray_set(carray * array, + unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +void carray_free(carray * array); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/charconv.c b/kmicromail/libetpan/tools/charconv.c new file mode 100644 index 0000000..bf3de51 --- a/dev/null +++ b/kmicromail/libetpan/tools/charconv.c @@ -0,0 +1,251 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "charconv.h" + +#include "config.h" +#ifdef HAVE_ICONV +#include +#endif +#include +#include +#include +#include + +#include "mmapstring.h" + +#ifdef HAVE_ICONV +static size_t mail_iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + char **inrepls, char *outrepl) +{ + /* + XXX - force conversion of (* inbuf) to (char *) + because prototype of iconv() is the following : + + size_t iconv(iconv_t cd, char **restrict inbuf, + size_t *restrict inbytesleft, char **restrict outbuf, + size_t *restrict outbytesleft); + */ + + size_t ret = 0, ret1; + char *ib = (char *) *inbuf; + size_t ibl = *inbytesleft; + char *ob = *outbuf; + size_t obl = *outbytesleft; + + for (;;) + { + ret1 = iconv (cd, &ib, &ibl, &ob, &obl); + if (ret1 != (size_t)-1) + ret += ret1; + if (ibl && obl && errno == EILSEQ) + { + if (inrepls) + { + /* Try replacing the input */ + char **t; + for (t = inrepls; *t; t++) + { + char *ib1 = *t; + size_t ibl1 = strlen (*t); + char *ob1 = ob; + size_t obl1 = obl; + iconv (cd, &ib1, &ibl1, &ob1, &obl1); + if (!ibl1) + { + ++ib, --ibl; + ob = ob1, obl = obl1; + ++ret; + break; + } + } + if (*t) + continue; + } + if (outrepl) + { + /* Try replacing the output */ + size_t n = strlen (outrepl); + if (n <= obl) + { + memcpy (ob, outrepl, n); + ++ib, --ibl; + ob += n, obl -= n; + ++ret; + continue; + } + } + } + *inbuf = ib, *inbytesleft = ibl; + *outbuf = ob, *outbytesleft = obl; + return ret; + } +} +#endif + +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result) +{ +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + iconv_t conv; + size_t r; + char * out; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; + int res; + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 4 * length; + + out = malloc(out_size + 1); + if (out == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto close_iconv; + } + + pout = out; + old_out_size = out_size; + + r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + count = old_out_size - out_size; + pout = realloc(out, count + 1); + if (pout != NULL) + out = pout; + + * result = out; + + return MAIL_CHARCONV_NO_ERROR; + + free: + free(out); + close_iconv: + iconv_close(conv); + err: + return res; +#endif +}; + +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len) +{ +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + iconv_t conv; + size_t iconv_r; + int r; + char * out; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; + MMAPString * mmapstr; + int res; + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 4 * length; + + mmapstr = mmap_string_sized_new(out_size + 1); + if (mmapstr == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto err; + } + + out = mmapstr->str; + + pout = out; + old_out_size = out_size; + + iconv_r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (iconv_r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + + count = old_out_size - out_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto free; + } + + * result = out; + * result_len = count; + + return MAIL_CHARCONV_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return -1; +#endif +}; + +void charconv_buffer_free(char * str) +{ + mmap_string_unref(str); +} diff --git a/kmicromail/libetpan/tools/charconv.h b/kmicromail/libetpan/tools/charconv.h new file mode 100644 index 0000000..5a435ff --- a/dev/null +++ b/kmicromail/libetpan/tools/charconv.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CHARCONV_H + +#define CHARCONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum { + MAIL_CHARCONV_NO_ERROR = 0, + MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET, + MAIL_CHARCONV_ERROR_MEMORY, + MAIL_CHARCONV_ERROR_CONV, +}; + +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result); + +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len); + +void charconv_buffer_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/chash.c b/kmicromail/libetpan/tools/chash.c new file mode 100644 index 0000000..2055221 --- a/dev/null +++ b/kmicromail/libetpan/tools/chash.c @@ -0,0 +1,395 @@ + +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include +#include + +#include "chash.h" + +/* This defines the maximum (average) number of entries per bucket. + The hash is resized everytime inserting an entry makes the + average go over that value. */ +#define CHASH_MAXDEPTH 3 + +static inline unsigned int chash_func(const char * key, unsigned int len) { +#if 0 + register unsigned int c = 0, t; + register const char * k = key; + + while (len--) { + c += (c << 4) + *k++; + if ((t = c & 0xF0000000)) { + c ^= t >> 24; + c ^= t; + } + } + return c; +#endif + register unsigned int c = 5381; + register const char * k = key; + + while (len--) { + c = ((c << 5) + c) + *k++; + } + + return c; +} + +static inline char * chash_dup(const void * data, unsigned int len) +{ + void * r; + + r = (char *) malloc(len); + if (!r) + return NULL; + memcpy(r, data, len); + return r; +} + +chash * chash_new(unsigned int size, int flags) +{ + chash * h; + + h = (chash *) malloc(sizeof(chash)); + if (h == NULL) + return NULL; + + h->count = 0; + h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (h->cells == NULL) { + free(h); + return NULL; + } + h->size = size; + h->copykey = flags & CHASH_COPYKEY; + h->copyvalue = flags & CHASH_COPYVALUE; + + return h; +} + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result) +{ + unsigned int func; + chashiter * iter; + + func = chash_func(key->data, key->len); + + /* look for the key in existing cells */ + iter = hash->cells[func % hash->size]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + * result = iter->value; /* found */ + + return 0; + } + iter = iter->next; + } + + return -1; +} + +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue) +{ + unsigned int func, indx; + chashiter * iter, * cell; + int r; + + if (hash->count > hash->size * CHASH_MAXDEPTH) { + r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1); + if (r < 0) + goto err; + } + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, replacing entry */ + if (hash->copyvalue) { + char * data; + + data = chash_dup(value->data, value->len); + if (data == NULL) + goto err; + + free(iter->value.data); + iter->value.data = data; + iter->value.len = value->len; + } else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + iter->value.data = value->data; + iter->value.len = value->len; + } + if (!hash->copykey) + iter->key.data = key->data; + + if (oldvalue != NULL) { + oldvalue->data = value->data; + oldvalue->len = value->len; + } + + return 0; + } + iter = iter->next; + } + + if (oldvalue != NULL) { + oldvalue->data = NULL; + oldvalue->len = 0; + } + + /* not found, adding entry */ + cell = (struct chashcell *) malloc(sizeof(struct chashcell)); + if (cell == NULL) + goto err; + + if (hash->copykey) { + cell->key.data = chash_dup(key->data, key->len); + if (cell->key.data == NULL) + goto free; + } + else + cell->key.data = key->data; + + cell->key.len = key->len; + if (hash->copyvalue) { + cell->value.data = chash_dup(value->data, value->len); + if (cell->value.data == NULL) + goto free_key_data; + } + else + cell->value.data = value->data; + + cell->value.len = value->len; + cell->func = func; + cell->next = hash->cells[indx]; + hash->cells[indx] = cell; + hash->count++; + + return 0; + + free_key_data: + if (hash->copykey) + free(cell->key.data); + free: + free(cell); + err: + return -1; +} + +int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue) +{ + /* chashdatum result = { NULL, TRUE }; */ + unsigned int func, indx; + chashiter * iter, * old; + + /* + if (!keylen) + keylen = strlen(key) + 1; + */ + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + old = NULL; + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, deleting */ + if (old) + old->next = iter->next; + else + hash->cells[indx] = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + } + free(iter); + hash->count--; + return 0; + } + old = iter; + iter = iter->next; + } + + return -1; /* not found */ +} + +void chash_free(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + free(hash->cells); + free(hash); +} + +void chash_clear(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + memset(hash->cells, 0, hash->size * sizeof(* hash->cells)); + hash->count = 0; +} + +chashiter * chash_begin(chash * hash) { + chashiter * iter; + unsigned int indx = 0; + + iter = hash->cells[0]; + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +chashiter * chash_next(chash * hash, chashiter * iter) { + unsigned int indx; + + if (!iter) + return NULL; + + indx = iter->func % hash->size; + iter = iter->next; + + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +int chash_resize(chash * hash, unsigned int size) +{ + struct chashcell ** cells; + unsigned int indx, nindx; + chashiter * iter, * next; + + if (hash->size == size) + return 0; + + cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (!cells) + return -1; + + /* browse initial hash and copy items in second hash */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + nindx = iter->func % size; + iter->next = cells[nindx]; + cells[nindx] = iter; + iter = next; + } + } + free(hash->cells); + hash->size = size; + hash->cells = cells; + + return 0; +} + +#ifdef NO_MACROS +int chash_count(chash * hash) { + return hash->count; +} + +int chash_size(chash * hash) { + return hash->size; +} + +void chash_value(chashiter * iter, chashdatum * result) { + * result = iter->value; +} + +void chash_key(chashiter * iter, chashdatum * result) { + * result = iter->key; +} +#endif diff --git a/kmicromail/libetpan/tools/chash.h b/kmicromail/libetpan/tools/chash.h new file mode 100644 index 0000000..3b2b7d3 --- a/dev/null +++ b/kmicromail/libetpan/tools/chash.h @@ -0,0 +1,166 @@ + +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CHASH_H +#define CHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void * data; + unsigned int len; +} chashdatum; + +struct chash { + unsigned int size; + unsigned int count; + int copyvalue; + int copykey; + struct chashcell ** cells; +}; + +typedef struct chash chash; + +struct chashcell { + unsigned int func; + chashdatum key; + chashdatum value; + struct chashcell * next; +}; + +typedef struct chashcell chashiter; + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +#define CHASH_DEFAULTSIZE 13 + +/* Allocates a new (empty) hash using this initial size and the given flags, + specifying which data should be copied in the hash. + CHASH_COPYNONE : Keys/Values are not copied. + CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. + CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. + CHASH_COPYALL : Both keys and values are dupped in the hash. + */ +chash * chash_new(unsigned int size, int flags); + +/* Frees a hash */ +void chash_free(chash * hash); + +/* Removes all elements from a hash */ +void chash_clear(chash * hash); + +/* Adds an entry in the hash table. + Length can be 0 if key/value are strings. + If an entry already exists for this key, it is replaced, and its value + is returned. Otherwise, the data pointer will be NULL and the length + field be set to TRUE or FALSe to indicate success or failure. */ +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue); + +/* Retrieves the data associated to the key if it is found in the hash table. + The data pointer and the length will be NULL if not found*/ +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + +/* Removes the entry associated to this key if it is found in the hash table, + and returns its contents if not dupped (otherwise, pointer will be NULL + and len TRUE). If entry is not found both pointer and len will be NULL. */ +int chash_delete(chash * hash, + chashdatum * key, + chashdatum * oldvalue); + +/* Resizes the hash table to the passed size. */ +int chash_resize(chash * hash, unsigned int size); + +/* Returns an iterator to the first non-empty entry of the hash table */ +chashiter * chash_begin(chash * hash); + +/* Returns the next non-empty entry of the hash table */ +chashiter * chash_next(chash * hash, chashiter * iter); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS +/* Returns the size of the hash table */ +unsigned int chash_size(chash * hash); + +/* Returns the number of entries in the hash table */ +unsigned int chash_count(chash * hash); + +/* Returns the key part of the entry pointed by the iterator */ +void chash_key(chashiter * iter, chashdatum * result); + +/* Returns the value part of the entry pointed by the iterator */ +void chash_value(chashiter * iter, chashdatum * result); + +#else +static inline unsigned int chash_size(chash * hash) +{ + return hash->size; +} + +static inline unsigned int chash_count(chash * hash) +{ + return hash->count; +} + +static inline void chash_key(chashiter * iter, chashdatum * result) +{ + * result = iter->key; +} + +static inline void chash_value(chashiter * iter, chashdatum * result) +{ + * result = iter->value; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/cinthash.c b/kmicromail/libetpan/tools/cinthash.c new file mode 100644 index 0000000..02ee727 --- a/dev/null +++ b/kmicromail/libetpan/tools/cinthash.c @@ -0,0 +1,248 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include +#include "cinthash.h" + +struct cinthash_list { + unsigned long hash; + void * data; + struct cinthash_list * next; +}; + +static struct cinthash_list HASH_LISTHEAD_NEW = { 0, NULL, NULL }; + +static inline int hash_list_add(cinthash_t * table, + unsigned long hash, void * data) +{ + struct cinthash_list * ht; + int index; + + index = hash % table->hashtable_size; + + ht = malloc(sizeof(struct cinthash_list)); + if (ht == NULL) + return -1; + + ht->hash = hash; + ht->data = data; + ht->next = table->table[index].next; + + table->table[index].next = ht; + + return 0; +} + +static inline void hash_list_free(struct cinthash_list * list) +{ + struct cinthash_list * cur; + struct cinthash_list * next; + + next = list; + while (next != NULL) { + cur = next; + next = cur->next; + free(cur); + } +} + +static inline int hash_list_remove(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = &table->table[index] ; cur->next != NULL ; cur = cur->next) { + if (cur->next->hash == hash) { + struct cinthash_list * hash_data; + + hash_data = cur->next; + cur->next = cur->next->next; + + free(hash_data); + + return 0; + } + } + + return -1; +} + +static inline void * hash_list_find(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) { + if (cur->hash == hash) + return cur->data; + } + + return NULL; +} + +cinthash_t * cinthash_new(unsigned long hashtable_size) +{ + cinthash_t * ht; + unsigned long i; + + ht = malloc(sizeof(cinthash_t)); + if (ht == NULL) + return NULL; + + ht->table = malloc(sizeof(struct cinthash_list) * hashtable_size); + if (ht->table == NULL) + return NULL; + + ht->hashtable_size = hashtable_size; + ht->count = 0; + + for(i = 0 ; i < hashtable_size ; i++) + ht->table[i] = HASH_LISTHEAD_NEW; + + return ht; +} + +void cinthash_free(cinthash_t * table) +{ + unsigned long i; + + for(i = 0 ; i < table->hashtable_size ; i++) + hash_list_free(table->table[i].next); + + free(table->table); + + free(table); +} + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].data == NULL) { + table->table[index].hash = hash; + table->table[index].data = data; + table->table[index].next = NULL; + + table->count ++; + + return 0; + } + else { + int r; + + r = hash_list_add(table, hash, data); + if (r == -1) + return -1; + + table->count ++; + + return 0; + } +} + +int cinthash_remove(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) { + table->table[index].hash = 0; + table->table[index].data = NULL; + + table->count --; + + return 0; + } + else { + int r; + + r = hash_list_remove(table, hash); + + table->count --; + + return 0; + } +} + +void * cinthash_find(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) + return table->table[index].data; + + return hash_list_find(table, hash); +} + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].hash, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->hash, data); + } + } +} + +void cinthash_foreach_data(cinthash_t * table, + void (* func)(void *, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].data, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->data, data); + } + } +} diff --git a/kmicromail/libetpan/tools/cinthash.h b/kmicromail/libetpan/tools/cinthash.h new file mode 100644 index 0000000..7e59dff --- a/dev/null +++ b/kmicromail/libetpan/tools/cinthash.h @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CINTHASH_H + +#define CINTHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cinthash_t { + struct cinthash_list * table; + unsigned long hashtable_size ; + unsigned long count; +} cinthash_t; + +cinthash_t * cinthash_new(unsigned long hashtable_size); +void cinthash_free(cinthash_t * table); + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data); +int cinthash_remove(cinthash_t * table, unsigned long hash); +void * cinthash_find(cinthash_t * table, unsigned long hash); + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data); + +void cinthash_foreach_data(cinthash_t * table, + void (* fun)(void *, void *), + void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/clist.c b/kmicromail/libetpan/tools/clist.c new file mode 100644 index 0000000..e5c680d --- a/dev/null +++ b/kmicromail/libetpan/tools/clist.c @@ -0,0 +1,266 @@ + +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include +#include "clist.h" + +clist * clist_new() { + clist * lst; + + lst = (clist *) malloc(sizeof(clist)); + if (!lst) return NULL; + + lst->first = lst->last = NULL; + lst->count = 0; + + return lst; +} + +void clist_free(clist * lst) { + clistcell * l1, * l2; + + l1 = lst->first; + while (l1) { + l2 = l1->next; + free(l1); + l1 = l2; + } + + free(lst); +} + +#ifdef NO_MACROS +int clist_isempty(clist * lst) { + return ((lst->first==lst->last) && (lst->last==NULL)); +} + +clistiter * clist_begin(clist * lst) { + return lst->first; +} + +clistiter * clist_end(clist * lst) { + return lst->last; +} + +clistiter * clist_next(clistiter * iter) { + if (iter) + return iter->next; + else + return NULL; +} + +clistiter * clist_previous(clistiter * iter) { + if (iter) + return iter->previous; + else + return NULL; +} + +void * clist_content(clistiter * iter) { + if (iter) + return iter->data; + else + return NULL; +} + +int clist_count(clist * lst) { + return lst->count; +} + +int clist_prepend(clist * lst, void * data) { + return clist_insert_before(lst, lst->first, data); +} + +int clist_append(clist * lst, void * data) { + return clist_insert_after(lst, lst->last, data); +} +#endif + +int clist_insert_before(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter->previous; + c->next = iter; + c->next->previous = c; + if (c->previous) + c->previous->next = c; + else + lst->first = c; + + return 0; +} + +int clist_insert_after(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter; + c->next = iter->next; + if (c->next) + c->next->previous = c; + else + lst->last = c; + c->previous->next = c; + + return 0; +} + +clistiter * clist_delete(clist * lst, clistiter * iter) { + clistiter * ret; + + if (!iter) return NULL; + + if (iter->previous) + iter->previous->next = iter->next; + else + lst->first = iter->next; + + if (iter->next) { + iter->next->previous = iter->previous; + ret = iter->next; + } else { + lst->last = iter->previous; + ret = NULL; + } + + free(iter); + lst->count--; + + return ret; +} + + + +void clist_foreach(clist * lst, clist_func func, void * data) +{ + clistiter * cur; + + for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next) + func(cur->data, data); +} + +void clist_concat(clist * dest, clist * src) +{ + if (src->first == NULL) { + /* do nothing */ + } + else if (dest->last == NULL) { + dest->first = src->first; + dest->last = src->last; + } + else { + dest->last->next = src->first; + src->first->previous = dest->last; + dest->last = src->last; + } + + dest->count += src->count; + src->last = src->first = NULL; +} + +static inline clistiter * internal_clist_nth(clist * lst, int index) +{ + clistiter * cur; + + cur = clist_begin(lst); + while ((index > 0) && (cur != NULL)) { + cur = cur->next; + index --; + } + + if (cur == NULL) + return NULL; + + return cur; +} + +void * clist_nth_data(clist * lst, int index) +{ + clistiter * cur; + + cur = internal_clist_nth(lst, index); + if (cur == NULL) + return NULL; + + return cur->data; +} + +clistiter * clist_nth(clist * lst, int index) +{ + return internal_clist_nth(lst, index); +} diff --git a/kmicromail/libetpan/tools/clist.h b/kmicromail/libetpan/tools/clist.h new file mode 100644 index 0000000..bd97f59 --- a/dev/null +++ b/kmicromail/libetpan/tools/clist.h @@ -0,0 +1,134 @@ + +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2000, Gaël Roualland + * interface changes - 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CLIST_H +#define CLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clistcell_s { + void * data; + struct clistcell_s * previous; + struct clistcell_s * next; +} clistcell; + +struct clist_s { + clistcell * first; + clistcell * last; + int count; +}; + +typedef struct clist_s clist; +typedef clistcell clistiter; + +/* Allocate a new pointer list */ +clist * clist_new(); + +/* Destroys a list. Data pointed by data pointers is NOT freed. */ +void clist_free(clist *); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns TRUE if list is empty */ +int clist_isempty(clist *); + +/* Returns the number of elements in the list */ +int clist_count(clist *); + +/* Returns an iterator to the first element of the list */ +clistiter * clist_begin(clist *); + +/* Returns an iterator to the last element of the list */ +clistiter * clist_end(clist *); + +/* Returns an iterator to the next element of the list */ +clistiter * clist_next(clistiter *); + +/* Returns an iterator to the previous element of the list */ +clistiter * clist_previous(clistiter *); + +/* Returns the data pointer of this element of the list */ +void* clist_content(clistiter *); + +/* Inserts this data pointer at the beginning of the list */ +int clist_prepend(clist *, void *); + +/* Inserts this data pointer at the end of the list */ +int clist_append(clist *, void *); +#else +#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL)) +#define clist_count(lst) (lst->count) +#define clist_begin(lst) (lst->first) +#define clist_end(lst) (lst->last) +#define clist_next(iter) (iter ? iter->next : NULL) +#define clist_previous(iter) (iter ? iter->previous : NULL) +#define clist_content(iter) (iter ? iter->data : NULL) +#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data)) +#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data)) +#endif + +/* Inserts this data pointer before the element pointed by the iterator */ +int clist_insert_before(clist *, clistiter *, void *); + +/* Inserts this data pointer after the element pointed by the iterator */ +int clist_insert_after(clist *, clistiter *, void *); + +/* Deletes the element pointed by the iterator. + Returns an iterator to the next element. */ +clistiter * clist_delete(clist *, clistiter *); + +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + +void clist_concat(clist * dest, clist * src); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/connect.c b/kmicromail/libetpan/tools/connect.c new file mode 100644 index 0000000..c67c18c --- a/dev/null +++ b/kmicromail/libetpan/tools/connect.c @@ -0,0 +1,86 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "connect.h" + +#include +#include +#include +#include +#include +#include + +uint16_t mail_get_service_port(const char * name, char * protocol) +{ + struct servent * service; + + service = getservbyname(name, protocol); + + if (service == NULL) + return 0; + + return service->s_port; +} + +int mail_tcp_connect(const char * server, uint16_t port) +{ + struct hostent * remotehost; + struct sockaddr_in sa; + int s; + int r; + + s = socket(PF_INET, SOCK_STREAM, 0); + if (s == -1) + goto err; + + remotehost = gethostbyname(server); + if (remotehost == NULL) + goto close_socket; + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length); + + r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); + if (r == -1) + goto close_socket; + + return s; + + close_socket: + close(s); + err: + return -1; +} diff --git a/kmicromail/libetpan/tools/connect.h b/kmicromail/libetpan/tools/connect.h new file mode 100644 index 0000000..9e44501 --- a/dev/null +++ b/kmicromail/libetpan/tools/connect.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef CONNECT_H + +#define CONNECT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol); +int mail_tcp_connect(const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/tools/hmac-md5.h b/kmicromail/libetpan/tools/hmac-md5.h new file mode 100644 index 0000000..2ae6098 --- a/dev/null +++ b/kmicromail/libetpan/tools/hmac-md5.h @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* hmac-md5.h -- HMAC_MD5 functions + */ + +/* + * $Id$ + */ + +#ifndef HMAC_MD5_H +#define HMAC_MD5_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define HMAC_MD5_SIZE 16 + +/* intermediate MD5 context */ +typedef struct HMAC_MD5_CTX_s { + MD5_CTX ictx, octx; +} HMAC_MD5_CTX; + +/* intermediate HMAC state + * values stored in network byte order (Big Endian) + */ +typedef struct HMAC_MD5_STATE_s { + UINT4 istate[4]; + UINT4 ostate[4]; +} HMAC_MD5_STATE; + +/* One step hmac computation + * + * digest may be same as text or key + */ +void hmac_md5(const unsigned char *text, int text_len, + const unsigned char *key, int key_len, + unsigned char digest[HMAC_MD5_SIZE]); + +/* create context from key + */ +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, int key_len); + +/* precalculate intermediate state from key + */ +void hmac_md5_precalc(HMAC_MD5_STATE *hmac, + const unsigned char *key, int key_len); + +/* initialize context from intermediate state + */ +void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); + +#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) + +/* finish hmac from intermediate result. Intermediate result is zeroed. + */ +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac); + +#ifdef __cplusplus +} +#endif + +#endif /* HMAC_MD5_H */ diff --git a/kmicromail/libetpan/tools/mail.h b/kmicromail/libetpan/tools/mail.h new file mode 100644 index 0000000..d4c63c4 --- a/dev/null +++ b/kmicromail/libetpan/tools/mail.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_H + +#define MAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mail_cache_db.c b/kmicromail/libetpan/tools/mail_cache_db.c new file mode 100644 index 0000000..5b6e9c9 --- a/dev/null +++ b/kmicromail/libetpan/tools/mail_cache_db.c @@ -0,0 +1,364 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include + +#ifndef CONFIG_H +#define CONFIG_H +#include "config.h" +#endif + +#include "libetpan-config.h" + +#include "maillock.h" + +#if DBVERS >= 1 +#include +#endif + +#if DBVERS >= 1 +static struct mail_cache_db * mail_cache_db_new(DB * db) +{ + struct mail_cache_db * cache_db; + + cache_db = malloc(sizeof(* cache_db)); + if (cache_db == NULL) + return NULL; + cache_db->internal_database = db; + + return cache_db; +} + +static void mail_cache_db_free(struct mail_cache_db * cache_db) +{ + free(cache_db); +} +#endif + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db) +{ +#if DBVERS >= 1 + DB * dbp; + int r; + struct mail_cache_db * cache_db; + +#if DB_VERSION_MAJOR >= 3 + r = db_create(&dbp, NULL, 0); + if (r != 0) + goto err; + +#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1)) + r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE, + S_IRUSR | S_IWUSR); +#else + r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR); +#endif + if (r != 0) + goto close_db; +#else +#if DBVERS > 1 + r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR, + NULL, NULL, &dbp); + if (r != 0) + goto err; +#elif DBVERS == 1 + dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL); + if (dbp == NULL) + goto err; +#else + goto err; +#endif +#endif + + cache_db = mail_cache_db_new(dbp); + if (cache_db == NULL) + goto close_db; + + * pcache_db = cache_db; + + return 0; + + close_db: +#if DBVERS > 1 + dbp->close(cache_db->internal_database, 0); +#elif DBVERS == 1 + dbp->close(cache_db->internal_database); +#endif + err: + return -1; +#else + return -1; +#endif +} + +void mail_cache_db_close(struct mail_cache_db * cache_db) +{ +#if DBVERS >= 1 + DB * dbp; + + dbp = cache_db->internal_database; + +#if DBVERS > 1 + dbp->close(cache_db->internal_database, 0); +#elif DBVERS == 1 + dbp->close(cache_db->internal_database); +#endif + + mail_cache_db_free(cache_db); +#endif +} + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db) +{ + int r; + struct mail_cache_db * cache_db; + + r = maillock_write_lock(filename, -1); + if (r < 0) + goto err; + + r = mail_cache_db_open(filename, &cache_db); + if (r < 0) + goto unlock; + + * pcache_db = cache_db; + + return 0; + + unlock: + maillock_write_unlock(filename, -1); + err: + return -1; +} + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db) +{ + maillock_write_unlock(filename, -1); + mail_cache_db_close(cache_db); +} + + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + db_data.data = (void *) value; + db_data.size = value_len; + +#if DBVERS > 1 + r = dbp->put(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->put(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + return r; +#else + return -1; +#endif +} + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->get(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->get(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + if (r != 0) + return r; + + * pvalue = db_data.data; + * pvalue_len = db_data.size; + + return 0; +#else + return -1; +#endif +} + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->del(dbp, NULL, &db_key, 0); +#elif DBVERS == 1 + r = dbp->del(dbp, &db_key, 0); +#else + r = -1; +#endif + + return r; +#else + return -1; +#endif +} + +#if DBVERS > 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBC * dbcp; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->cursor(dbp, NULL, &dbcp, 0); + if (r != 0) + return r; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + + while (1) { + chashdatum hash_key; + chashdatum hash_data; + + r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); + if (r != 0) + break; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbcp->c_del(dbcp, 0); + if (r != 0) + return r; + } + } + + r = dbcp->c_close(dbcp); + if (r != 0) + return r; + + return 0; +} +#elif DBVERS == 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->seq(dbp, &db_key, &db_data, R_FIRST); + if (r == -1) + return r; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbp->del(dbp, &db_key, 0); + if (r != 0) + return r; + } + + r = dbp->seq(dbp, &db_key, &db_data, R_NEXT); + if (r == -1) + return r; + } + + return 0; +} +#else +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + return -1; +} +#endif diff --git a/kmicromail/libetpan/tools/mail_cache_db.h b/kmicromail/libetpan/tools/mail_cache_db.h new file mode 100644 index 0000000..0ca17d9 --- a/dev/null +++ b/kmicromail/libetpan/tools/mail_cache_db.h @@ -0,0 +1,138 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_CACHE_DB_H + +#define MAIL_CACHE_DB_H + +#include +#include "mail_cache_db_types.h" +#include "chash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + this module will handle a database "f(key) -> value" in a file + + berkeley DB or other can be used for implementation of low-level file. +*/ + +/* + mail_cache_db_open() + + This function opens the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_close() + + This function closes the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close(struct mail_cache_db * cache_db); + +/* + mail_cache_db_open_lock() + + This function opens and locks the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_open_unlock() + + This function closes and unlocks the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db); + +/* + mail_cache_db_put() + + This function will store a given key and value in the database. +*/ + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len); + +/* + mail_cache_db_get() + + This function will retrieve the value corresponding to a given key + from the database. +*/ + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len); + +/* + mail_cache_db_del() + + This function will delete the given key and the corresponding value + from the database. +*/ + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len); + +/* + mail_cache_clean_up() + + This function will delete the key all the key/value pairs of the + database file which key does not exist in the given hash. +*/ + +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mail_cache_db_types.h b/kmicromail/libetpan/tools/mail_cache_db_types.h new file mode 100644 index 0000000..f346c5f --- a/dev/null +++ b/kmicromail/libetpan/tools/mail_cache_db_types.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAIL_CACHE_DB_TYPES_H + +#define MAIL_CACHE_DB_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_cache_db { + void * internal_database; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/maillock.c b/kmicromail/libetpan/tools/maillock.c new file mode 100644 index 0000000..6128f34 --- a/dev/null +++ b/kmicromail/libetpan/tools/maillock.c @@ -0,0 +1,286 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id $ + */ + +#include "maillock.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#include +#include + +/* ********************************************************************** */ + +/* lock primitives */ + +/* the lock code is modified from the dot lock file code from mail.local.c */ + +/* + SENDMAIL LICENSE + +The following license terms and conditions apply, unless a different +license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor, +Emeryville, CA 94608, or by electronic mail at license@sendmail.com. + +License Terms: + +Use, Modification and Redistribution (including distribution of any +modified or derived work) in source and binary forms is permitted only if +each of the following conditions is met: + +1. Redistributions qualify as "freeware" or "Open Source Software" under + one of the following terms: + + (a) Redistributions are made at no charge beyond the reasonable cost of + materials and delivery. + + (b) Redistributions are accompanied by a copy of the Source Code or by an + irrevocable offer to provide a copy of the Source Code for up to three + years at the cost of materials and delivery. Such redistributions + must allow further use, modification, and redistribution of the Source + Code under substantially the same terms as this license. For the + purposes of redistribution "Source Code" means the complete compilable + and linkable source code of sendmail including all modifications. + +2. Redistributions of source code must retain the copyright notices as they + appear in each source code file, these license terms, and the + disclaimer/limitation of liability set forth as paragraph 6 below. + +3. Redistributions in binary form must reproduce the Copyright Notice, + these license terms, and the disclaimer/limitation of liability set + forth as paragraph 6 below, in the documentation and/or other materials + provided with the distribution. For the purposes of binary distribution + the "Copyright Notice" refers to the following language: + "Copyright (c) 1998-2002 Sendmail, Inc. All rights reserved." + +4. Neither the name of Sendmail, Inc. nor the University of California nor + the names of their contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. The name "sendmail" is a trademark of Sendmail, Inc. + +5. All redistributions must comply with the conditions imposed by the + University of California on certain embedded code, whose copyright + notice and conditions for redistribution are as follows: + + (a) Copyright (c) 1988, 1993 The Regents of the University of + California. All rights reserved. + + (b) Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + (i) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (ii) Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + (iii) Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY + SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF + CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +*/ + +/* + TODO : lock, prefer fcntl() over flock() + AND use dotlock code above +*/ + +#define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ + +static int lock_common(const char * filename, int fd, short locktype) +{ + char lockfilename[PATH_MAX]; + struct flock lock; + /* dot lock file */ + int statfailed = 0; + time_t start; + int r; + int res; + + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = locktype; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLKW, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + + /* dot lock file */ + + if (strlen(filename) + 6 > PATH_MAX) { + res = -1; + goto unlock; + } + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + + time(&start); + while (1) { + int fd; + struct stat st; + time_t now; + + /* global timeout */ + time(&now); + if (now > start + LOCKTO_GLOB) { + res = -1; + goto unlock; + } + + fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0); + if (fd >= 0) { + /* defeat lock checking programs which test pid */ + write(fd, "0", 2); + close(fd); + break; + } + + /* libEtPan! - adds a delay of 5 seconds between each tries */ + sleep(5); + + if (stat(lockfilename, &st) < 0) { + if (statfailed++ > 5) { + res = -1; + goto unlock; + } + continue; + } + statfailed = 0; + time(&now); + + if (now < st.st_ctime + LOCKTO_RM) + continue; + + /* try to remove stale lockfile */ + if (unlink(lockfilename) < 0) { + res = -1; + goto unlock; + } + + /* + libEtPan! - removes this delay of 5 seconds, + maybe it was misplaced ? + */ +#if 0 + sleep(5); +#endif + } + + return 0; + + unlock: + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + err: + return res; +} + +static int unlock_common(const char * filename, int fd) +{ + char lockfilename[PATH_MAX]; + struct flock lock; + int r; + + if (strlen(filename) + 6 > PATH_MAX) + return -1; + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + + unlink(lockfilename); + + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + + return 0; +} + +int maillock_read_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_RDLCK); +} + +int maillock_read_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} + +int maillock_write_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_WRLCK); +} + +int maillock_write_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} diff --git a/kmicromail/libetpan/tools/maillock.h b/kmicromail/libetpan/tools/maillock.h new file mode 100644 index 0000000..2f64e35 --- a/dev/null +++ b/kmicromail/libetpan/tools/maillock.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILLOCK_H + +#define MAILLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +int maillock_read_lock(const char * filename, int fd); +int maillock_read_unlock(const char * filename, int fd); +int maillock_write_lock(const char * filename, int fd); +int maillock_write_unlock(const char * filename, int fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mailstream.c b/kmicromail/libetpan/tools/mailstream.c new file mode 100644 index 0000000..0f55e67 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream.c @@ -0,0 +1,394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstream.h" +#include "maillock.h" +#include +#include +#include +#include + +#define DEFAULT_NETWORK_TIMEOUT 300 + +#ifdef LIBETPAN_MAILSTREAM_DEBUG + +#define STREAM_DEBUG + +#include + +#define LOG_FILE "libetpan-stream-debug.log" + +int mailstream_debug = 0; + +#define STREAM_LOG_BUF(buf, size) \ + if (mailstream_debug) { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fwrite((buf), 1, (size), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } + +#define STREAM_LOG(str) \ + if (mailstream_debug) { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fputs((str), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } + +#else + +#define STREAM_LOG_BUF(buf, size) do { } while (0) +#define STREAM_LOG(buf) do { } while (0) + +#endif + + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size) +{ + mailstream * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + goto err; + + s->read_buffer = malloc(buffer_size); + if (s->read_buffer == NULL) + goto free_s; + s->read_buffer_len = 0; + + s->write_buffer = malloc(buffer_size); + if (s->write_buffer == NULL) + goto free_read_buffer; + s->write_buffer_len = 0; + + s->buffer_max_size = buffer_size; + s->low = low; + + return s; + + free_read_buffer: + free(s->read_buffer); + free_s: + free(s); + err: + return NULL; +} + +static size_t write_to_internal_buffer(mailstream * s, + const void * buf, size_t count) +{ + memcpy(s->write_buffer + s->write_buffer_len, buf, count); + s->write_buffer_len += count; + + return count; +} + +static size_t write_direct(mailstream * s, const void * buf, size_t count) +{ + size_t left; + const char * cur_buf; + ssize_t written; + + cur_buf = buf; + left = count; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written == -1) { + if (count == left) + return -1; + else + return count - left; + } + + cur_buf += written; + left -= written; + } + + return count; +} + +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count) +{ + int r; + + if (s == NULL) + return -1; + + if (count + s->write_buffer_len > s->buffer_max_size) { + r = mailstream_flush(s); + if (r == -1) + return -1; + + if (count > s->buffer_max_size) + return write_direct(s, buf, count); + } + +#ifdef STREAM_DEBUG + STREAM_LOG(">>>>>>> send >>>>>>\n"); + STREAM_LOG_BUF(buf, count); + STREAM_LOG("\n"); + STREAM_LOG(">>>>>>> end send >>>>>>\n"); +#endif + + return write_to_internal_buffer(s, buf, count); +} + +int mailstream_flush(mailstream * s) +{ + char * cur_buf; + size_t left; + ssize_t written; + + if (s == NULL) + return -1; + + cur_buf = s->write_buffer; + left = s->write_buffer_len; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written == -1) + goto move_buffer; + cur_buf += written; + left -= written; + } + + s->write_buffer_len = 0; + + return 0; + + move_buffer: + memmove(s->write_buffer, cur_buf, left); + s->write_buffer_len = left; + return -1; +} + +static ssize_t read_from_internal_buffer(mailstream * s, + void * buf, size_t count) +{ + if (count >= s->read_buffer_len) + count = s->read_buffer_len; + if (count != 0) + memcpy(buf, s->read_buffer, count); + + s->read_buffer_len -= count; + if (s->read_buffer_len != 0) + memmove(s->read_buffer, s->read_buffer + count, + s->read_buffer_len); + + return count; +} + +static ssize_t read_through_buffer(mailstream * s, void * buf, size_t count) +{ + size_t left; + char * cur_buf; + ssize_t bytes_read; + + cur_buf = buf; + left = count; + + while (left > 0) { + bytes_read = mailstream_low_read(s->low, cur_buf, left); + + if (bytes_read == -1) { + if (count == left) + return -1; + else + return count - left; + } + else if (bytes_read == 0) + return count - left; + + cur_buf += bytes_read; + left -= bytes_read; + } + + return count; +} + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count) +{ + ssize_t read_bytes; + char * cur_buf; + size_t left; + + if (s == NULL) + return -1; + + left = count; + cur_buf = buf; + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + + if (left == 0) { +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, read_bytes); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return read_bytes; + } + + if (left > s->buffer_max_size) { + read_bytes = read_through_buffer(s, cur_buf, left); + if (read_bytes == -1) { + if (count == left) + return -1; + else { + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + } + + cur_buf += read_bytes; + left -= read_bytes; + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + + read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size); + if (read_bytes == -1) { + if (left == count) + return -1; + else { +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + } + else + s->read_buffer_len += read_bytes; + + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; +} + +mailstream_low * mailstream_get_low(mailstream * s) +{ + return s->low; +} + +void mailstream_set_low(mailstream * s, mailstream_low * low) +{ + s->low = low; +} + +int mailstream_close(mailstream * s) +{ + mailstream_low_close(s->low); + mailstream_low_free(s->low); + + free(s->read_buffer); + free(s->write_buffer); + + free(s); + + return 0; +} + + + +ssize_t mailstream_feed_read_buffer(mailstream * s) +{ + ssize_t read_bytes; + + if (s == NULL) + return -1; + + if (s->read_buffer_len == 0) { + read_bytes = mailstream_low_read(s->low, s->read_buffer, + s->buffer_max_size); + if (read_bytes == -1) + return -1; + s->read_buffer_len += read_bytes; + } + + return s->read_buffer_len; +} + +struct timeval mailstream_network_delay = + { .tv_sec = DEFAULT_NETWORK_TIMEOUT, .tv_usec = 0 }; + diff --git a/kmicromail/libetpan/tools/mailstream.h b/kmicromail/libetpan/tools/mailstream.h new file mode 100644 index 0000000..a4e35cd --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_H + +#define MAILSTREAM_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count); +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); +int mailstream_close(mailstream * s); +int mailstream_flush(mailstream * s); +ssize_t mailstream_feed_read_buffer(mailstream * s); +mailstream_low * mailstream_get_low(mailstream * s); +void mailstream_set_low(mailstream * s, mailstream_low * low); + +#ifdef LIBETPAN_MAILSTREAM_DEBUG +extern int mailstream_debug; +#endif + +#define LIBETPAN_MAILSTREAM_NETWORK_DELAY +extern struct timeval mailstream_network_delay; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/tools/mailstream_helper.c b/kmicromail/libetpan/tools/mailstream_helper.c new file mode 100644 index 0000000..146f955 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_helper.c @@ -0,0 +1,383 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstream_helper.h" +#include +#include +#include "mail.h" + +static void remove_trailing_eol(MMAPString * mmapstr) +{ + if (mmapstr->str[mmapstr->len - 1] == '\n') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } + if (mmapstr->str[mmapstr->len - 1] == '\r') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } +} + +char * mailstream_read_line(mailstream * stream, MMAPString * line) +{ + if (mmap_string_assign(line, "") == NULL) + return NULL; + + return mailstream_read_line_append(stream, line); +} + +static char * mailstream_read_len_append(mailstream * stream, + MMAPString * line, + size_t i) +{ + size_t cur_size; + + cur_size = line->len; + if (mmap_string_set_size(line, line->len + i) == NULL) + return NULL; + if (mailstream_read(stream, line->str + cur_size, i) < 0) + return NULL; + return line->str; +} + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line) +{ + if (stream == NULL) + return NULL; + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (stream->read_buffer[i] == '\n') + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + } + else { + ssize_t r; + + r = mailstream_feed_read_buffer(stream); + if (r == -1) + return NULL; + + if (r == 0) + break; + } + } + while (1); + + return line->str; +} + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line) +{ + if (!mailstream_read_line(stream, line)) + return NULL; + + remove_trailing_eol(line); + + return line->str; +} + +int mailstream_is_end_multiline(const char * line) +{ + if (line[0] != '.') + return FALSE; + if (line[1] != 0) + return FALSE; + return TRUE; +} + +#if 1 +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t count; + char * line; + size_t last; + + if (mmap_string_assign(multiline_buffer, "") == NULL) + return NULL; + + count = 0; + last = 0; + + while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) { + if (mailstream_is_end_multiline(line)) + return multiline_buffer->str; + + if (line[0] == '.') { + if (mmap_string_append(multiline_buffer, line + 1) == NULL) + return NULL; + } + else { + if (mmap_string_append(multiline_buffer, line) == NULL) + return NULL; + } + if (mmap_string_append(multiline_buffer, "\r\n") == NULL) + return NULL; + + count += strlen(line); + if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL)) + if (count - last >= progr_rate) { + (* progr_fun)(count, size); + last = count; + } + } + + return NULL; +} + +#else + +/* + high speed but don't replace the line break with '\n' and neither + remove the '.' +*/ + +static gboolean end_of_multiline(const char * str, gint len) +{ + gint index; + + index = len - 1; + + if (str[index] != '\n') + return FALSE; + if (index == 0) + return FALSE; + + index --; + + if (str[index] == '\r') { + index --; + if (index == 0) + return FALSE; + } + + if (str[index] != '.') + return FALSE; + if (index == 0) + return FALSE; + + index--; + + if (str[index] != '\n') + return FALSE; + + return TRUE; +} + +char * mailstream_read_multiline(mailstream * stream, size_t size, + MMAPString * stream_buffer, + MMAPString * line, + size_t progr_rate, + progress_function * progr_fun) +{ + if (stream == NULL) + return NULL; + + mmap_string_assign(line, ""); + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (end_of_multiline(stream->read_buffer, i + 1)) + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + if (end_of_multiline(line->str, line->len)) + return line->str; + } + else + if (mailstream_feed_read_buffer(stream) == -1) + return NULL; + } + while (1); + + return line->str; +} +#endif + + + +static ssize_t send_data_line(mailstream * s, const char * line, size_t length) +{ + int fix_eol; + const char * start; + size_t count; + + start = line; + + fix_eol = 0; + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + } + + if (* line == '\n') { + line ++; + + count ++; + length --; + + fix_eol = 1; + break; + } + + line ++; + length --; + count ++; + } + + if (start[0] == '.') + if (mailstream_write(s, ".", 1) == -1) + goto err; + + if (fix_eol) { + if (mailstream_write(s, start, count - 1) == -1) + goto err; + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + else { + if (mailstream_write(s, start, count) == -1) + goto err; + } + + +#if 0 + while (* line != '\n') { + if (* line == '\r') + pos = line; + if (* line == '\0') + return line; + if (mailstream_write(s, line, 1) == -1) + goto err; + line ++; + } + if (pos + 1 == line) { + if (mailstream_write(s, line, 1) == -1) + goto err; + } + else { + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + line ++; +#endif + + return count; + + err: + return -1; +} + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun) +{ + const char * current; + size_t count; + size_t last; + size_t remaining; + + count = 0; + last = 0; + + current = message; + remaining = size; + + while (remaining > 0) { + ssize_t length; + + length = send_data_line(s, current, remaining); + if (length < 0) + goto err; + + current += length; + + count += length; + if ((progr_rate != 0) && (progr_fun != NULL)) + if (count - last >= progr_rate) { + (* progr_fun)(count, size); + last = count; + } + + remaining -= length; + } + if (mailstream_write(s, "\r\n.\r\n", 5) == -1) + goto err; + + if (mailstream_flush(s) == -1) + goto err; + + return 0; + + err: + return -1; +} diff --git a/kmicromail/libetpan/tools/mailstream_helper.h b/kmicromail/libetpan/tools/mailstream_helper.h new file mode 100644 index 0000000..d030b1d --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_helper.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_HELPER_H + +#define MAILSTREAM_HELPER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_is_end_multiline(const char * line); + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mailstream_low.c b/kmicromail/libetpan/tools/mailstream_low.c new file mode 100644 index 0000000..34c96f1 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_low.c @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstream_low.h" +#include + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver) +{ + mailstream_low * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + return NULL; + + s->data = data; + s->driver = driver; + + return s; +} + +int mailstream_low_close(mailstream_low * s) +{ + if (s == NULL) + return -1; + s->driver->mailstream_close(s); + + return 0; +} + +int mailstream_low_get_fd(mailstream_low * s) +{ + if (s == NULL) + return -1; + return s->driver->mailstream_get_fd(s); +} + +void mailstream_low_free(mailstream_low * s) +{ + s->driver->mailstream_free(s); +} + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count) +{ + if (s == NULL) + return -1; + return s->driver->mailstream_read(s, buf, count); +} + +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count) +{ + if (s == NULL) + return -1; + return s->driver->mailstream_write(s, buf, count); +} diff --git a/kmicromail/libetpan/tools/mailstream_low.h b/kmicromail/libetpan/tools/mailstream_low.h new file mode 100644 index 0000000..fb8914c --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_low.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_LOW_H + +#define MAILSTREAM_LOW_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count); +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); +int mailstream_low_close(mailstream_low * s); +int mailstream_low_get_fd(mailstream_low * s); +void mailstream_low_free(mailstream_low * s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mailstream_socket.c b/kmicromail/libetpan/tools/mailstream_socket.c new file mode 100644 index 0000000..29e50e1 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_socket.c @@ -0,0 +1,239 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailstream_socket.h" +#include +#include +#include + +/* + these 3 headers MUST be included before + to insure compatibility with Mac OS X (this is true for 10.2) +*/ +#include +#include +#include +#include +#include + +/* mailstream_low, socket */ + +static int mailstream_low_socket_close(mailstream_low * s); +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_socket_free(mailstream_low * s); +static int mailstream_low_socket_get_fd(mailstream_low * s); + +static mailstream_low_driver local_mailstream_socket_driver = { + mailstream_read: mailstream_low_socket_read, + mailstream_write: mailstream_low_socket_write, + mailstream_close: mailstream_low_socket_close, + mailstream_free: mailstream_low_socket_free, + mailstream_get_fd: mailstream_low_socket_get_fd, +}; + +mailstream_low_driver * mailstream_socket_driver = +&local_mailstream_socket_driver; + +/* file descriptor must be given in (default) blocking-mode */ + +static struct mailstream_socket_data * socket_data_new(int fd) +{ + struct mailstream_socket_data * socket_data; + + socket_data = malloc(sizeof(* socket_data)); + if (socket_data == NULL) + goto err; + + socket_data->fd = fd; + + return socket_data; + + err: + return NULL; +} + +static void socket_data_free(struct mailstream_socket_data * socket_data) +{ + free(socket_data); +} + +static void socket_data_close(struct mailstream_socket_data * socket_data) +{ + close(socket_data->fd); + socket_data->fd = -1; +} + +mailstream_low * mailstream_low_socket_open(int fd) +{ + mailstream_low * s; + struct mailstream_socket_data * socket_data; + + socket_data = socket_data_new(fd); + if (socket_data == NULL) + goto err; + + s = mailstream_low_new(socket_data, mailstream_socket_driver); + if (s == NULL) + goto free_socket_data; + + return s; + + free_socket_data: + socket_data_free(socket_data); + err: + return NULL; +} + +static int mailstream_low_socket_close(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_close(socket_data); + + return 0; +} + +static void mailstream_low_socket_free(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_free(socket_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_socket_get_fd(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + return socket_data->fd; +} + + +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + + /* timeout */ + { + fd_set fds_read; + fd_set fds_excp; + struct timeval timeout; + int r; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_read); + FD_SET(socket_data->fd, &fds_read); + FD_ZERO(&fds_excp); + FD_SET(socket_data->fd, &fds_excp); + r = select(socket_data->fd + 1, &fds_read, NULL, &fds_excp, &timeout); + if (r == 0) + return -1; + if (FD_ISSET(socket_data->fd, &fds_excp)) + return -1; + if (!FD_ISSET(socket_data->fd, &fds_read)) + return 0; + } + return recv(socket_data->fd,buf,count,MSG_NOSIGNAL); + //return read(socket_data->fd, buf, count); +} + +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + /* timeout */ + { + fd_set fds_write; + fd_set fds_excp; + struct timeval timeout; + int r; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_write); + FD_SET(socket_data->fd, &fds_write); + FD_ZERO(&fds_excp); + FD_SET(socket_data->fd, &fds_excp); + r = select(socket_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout); + if (r == 0) + return -1; + if (FD_ISSET(socket_data->fd, &fds_excp)) + return -1; + if (!FD_ISSET(socket_data->fd, &fds_write)) + return 0; + } + + return send(socket_data->fd,buf,count,MSG_NOSIGNAL); + //return write(socket_data->fd, buf, count); +} + + +/* mailstream */ + +mailstream * mailstream_socket_open(int fd) +{ + mailstream_low * low; + mailstream * s; + + low = mailstream_low_socket_open(fd); + if (low == NULL) + goto err; + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +} + diff --git a/kmicromail/libetpan/tools/mailstream_socket.h b/kmicromail/libetpan/tools/mailstream_socket.h new file mode 100644 index 0000000..6a26e33 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_socket.h @@ -0,0 +1,61 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_SOCKET_H + +#define MAILSTREAM_SOCKET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +extern mailstream_low_driver * mailstream_socket_driver; + +mailstream_low * mailstream_low_socket_open(int fd); +mailstream * mailstream_socket_open(int fd); + +struct mailstream_socket_data { + int fd; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mailstream_ssl.c b/kmicromail/libetpan/tools/mailstream_ssl.c new file mode 100644 index 0000000..9f5008d --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_ssl.c @@ -0,0 +1,312 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* + NOTE : + + The user has to call himself SSL_library_init() if he wants to + use SSL. +*/ + +#include "mailstream_ssl.h" +#include +#include + +#ifndef CONFIG_H +#define CONFIG_H +#include "config.h" +#endif + +/* + these 3 headers MUST be included before + to insure compatibility with Mac OS X (this is true for 10.2) +*/ +#include +#include +#include +#include + +/* mailstream_low, ssl */ + +#ifdef USE_SSL +#include +#include +#endif + +#ifdef USE_SSL +struct mailstream_ssl_data { + int fd; + SSL * ssl_conn; + SSL_CTX * ssl_ctx; +}; +#endif + +#ifdef USE_SSL +static pthread_mutex_t ssl_lock = PTHREAD_MUTEX_INITIALIZER; +static int ssl_init_done = 0; +#endif + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s); +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_ssl_free(mailstream_low * s); +static int mailstream_low_ssl_get_fd(mailstream_low * s); + +static mailstream_low_driver local_mailstream_ssl_driver = { + mailstream_read: mailstream_low_ssl_read, + mailstream_write: mailstream_low_ssl_write, + mailstream_close: mailstream_low_ssl_close, + mailstream_free: mailstream_low_ssl_free, + mailstream_get_fd: mailstream_low_ssl_get_fd, +}; + +mailstream_low_driver * mailstream_ssl_driver = &local_mailstream_ssl_driver; +#endif + +/* file descriptor must be given in (default) blocking-mode */ + +#ifdef USE_SSL +static struct mailstream_ssl_data * ssl_data_new(int fd) +{ + struct mailstream_ssl_data * ssl_data; + SSL * ssl_conn; + int r; + SSL_CTX * tmp_ctx; + int fd_flags; + int old_fd_flags; + + pthread_mutex_lock(&ssl_lock); + if (!ssl_init_done) { + SSL_library_init(); + ssl_init_done = 1; + } + pthread_mutex_unlock(&ssl_lock); + + tmp_ctx = SSL_CTX_new(TLSv1_client_method()); + if (tmp_ctx == NULL) + goto err; + + ssl_conn = (SSL *) SSL_new(tmp_ctx); + if (ssl_conn == NULL) + goto free_ctx; + + if (SSL_set_fd(ssl_conn, fd) == 0) + goto free_ssl_conn; + + SSL_set_read_ahead(ssl_conn, 1); + + r = SSL_connect(ssl_conn); + if (r <= 0) + goto free_ssl_conn; + + fd_flags = fcntl(fd, F_GETFL, 0); + old_fd_flags = fd_flags; + fd_flags |= O_NDELAY; + r = fcntl(fd, F_SETFL, fd_flags); + if (r < 0) + goto free_ssl_conn; + + ssl_data = malloc(sizeof(* ssl_data)); + if (ssl_data == NULL) + goto reset_fd_flags; + + ssl_data->fd = fd; + ssl_data->ssl_conn = ssl_conn; + ssl_data->ssl_ctx = tmp_ctx; + + return ssl_data; + + reset_fd_flags: + fcntl(fd, F_SETFL, old_fd_flags); + free_ctx: + SSL_CTX_free(tmp_ctx); + free_ssl_conn: + SSL_free(ssl_conn); + err: + return NULL; +} + +static void ssl_data_free(struct mailstream_ssl_data * ssl_data) +{ + free(ssl_data); +} + +static void ssl_data_close(struct mailstream_ssl_data * ssl_data) +{ + SSL_free(ssl_data->ssl_conn); + ssl_data->ssl_conn = NULL; + SSL_CTX_free(ssl_data->ssl_ctx); + ssl_data->ssl_ctx = NULL; + close(ssl_data->fd); + ssl_data->fd = -1; +} +#endif + +mailstream_low * mailstream_low_ssl_open(int fd) +{ +#ifdef USE_SSL + mailstream_low * s; + struct mailstream_ssl_data * ssl_data; + + ssl_data = ssl_data_new(fd); + if (ssl_data == NULL) + goto err; + + s = mailstream_low_new(ssl_data, mailstream_ssl_driver); + if (s == NULL) + goto free_ssl_data; + + return s; + + free_ssl_data: + ssl_data_free(ssl_data); + err: + return NULL; +#else + return NULL; +#endif +} + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_close(ssl_data); + + return 0; +} + +static void mailstream_low_ssl_free(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_free(ssl_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_ssl_get_fd(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + return ssl_data->fd; +} + +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + while (1) { + int ssl_r; + fd_set fds_read; + struct timeval timeout; + + r = SSL_read(ssl_data->ssl_conn, buf, count); + if (r > 0) + return r; + + ssl_r = SSL_get_error(ssl_data->ssl_conn, r); + switch (ssl_r) { + case SSL_ERROR_NONE: + return r; + + case SSL_ERROR_ZERO_RETURN: + return r; + + case SSL_ERROR_WANT_READ: + timeout = mailstream_network_delay; + + FD_ZERO(&fds_read); + FD_SET(ssl_data->fd, &fds_read); + r = select(ssl_data->fd + 1, &fds_read, NULL, NULL, &timeout); + if (r == 0) + return -1; + break; + + default: + return r; + } + } +} + +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + return SSL_write(ssl_data->ssl_conn, buf, count); +} +#endif + +/* mailstream */ + +mailstream * mailstream_ssl_open(int fd) +{ +#ifdef USE_SSL + mailstream_low * low; + mailstream * s; + + low = mailstream_low_ssl_open(fd); + if (low == NULL) + goto err; + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +#else + return NULL; +#endif +} + diff --git a/kmicromail/libetpan/tools/mailstream_ssl.h b/kmicromail/libetpan/tools/mailstream_ssl.h new file mode 100644 index 0000000..a37b3d4 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_ssl.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_SSL_H + +#define MAILSTREAM_SSL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +#ifdef USE_SSL +extern mailstream_low_driver * mailstream_ssl_driver; +#endif + +mailstream_low * mailstream_low_ssl_open(int fd); +mailstream * mailstream_ssl_open(int fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mailstream_types.h b/kmicromail/libetpan/tools/mailstream_types.h new file mode 100644 index 0000000..2165149 --- a/dev/null +++ b/kmicromail/libetpan/tools/mailstream_types.h @@ -0,0 +1,87 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAILSTREAM_TYPES_H + +#define MAILSTREAM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBETPAN_MAILSTREAM_DEBUG + +struct _mailstream; + +typedef struct _mailstream mailstream; + +struct _mailstream_low; + +typedef struct _mailstream_low mailstream_low; + +struct _mailstream { + size_t buffer_max_size; + + char * write_buffer; + size_t write_buffer_len; + + char * read_buffer; + size_t read_buffer_len; + + mailstream_low * low; +}; + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + +typedef void progress_function(size_t current, size_t maximum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mapping.c b/kmicromail/libetpan/tools/mapping.c new file mode 100644 index 0000000..426a03c --- a/dev/null +++ b/kmicromail/libetpan/tools/mapping.c @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mapping.h" + +#include +#include + +int get_mapping(size_t length, int prot, int flags, + int fd, off_t offset, + void ** presult, void ** pmapping, size_t * pmapping_size) +{ + void * mapping; + size_t mapping_size; + void * result; + size_t page_size; + off_t delta; + + page_size = getpagesize(); + delta = offset % page_size; + + mapping = mmap(NULL, length + offset, prot, flags, fd, offset - delta); + if (mapping == MAP_FAILED) + return -1; + + result = ((char *) mapping) + delta; + + mapping_size = length + offset; + + * pmapping = mapping; + * pmapping_size = mapping_size; + * presult = result; + + return 0; +} diff --git a/kmicromail/libetpan/tools/mapping.h b/kmicromail/libetpan/tools/mapping.h new file mode 100644 index 0000000..8e72f98 --- a/dev/null +++ b/kmicromail/libetpan/tools/mapping.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef MAPPING_H + +#define MAPPING_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int get_mapping(size_t length, int prot, int flags, + int fd, off_t offset, + void ** presult, void ** pmapping, size_t * pmapping_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/md5.c b/kmicromail/libetpan/tools/md5.c new file mode 100644 index 0000000..50307e0 --- a/dev/null +++ b/kmicromail/libetpan/tools/md5.c @@ -0,0 +1,570 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm +*/ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*/ + +/* do i need all of this just for htonl()? damn. */ +#include +#include +#include +#include + +#include "md5global.h" +#include "md5.h" +#include "hmac-md5.h" + +/* Constants for MD5Transform routine. +*/ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + + */ +#ifdef I +/* This might be defined via NANA */ +#undef I +#endif + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + + */ + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. +*/ + +#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. +*/ + +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. + +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the context. +*/ + +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. + +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform + (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); + +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + + */ + +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. + +*/ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. + +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + + */ + +static void MD5Transform (state, block) +UINT4 state[4]; +unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + */ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + + */ + +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + + */ + +static void Decode (output, input, len) +UINT4 *output; +unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) + | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. +*/ + +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, + int key_len) +{ + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + MD5Init(&hmac->ictx); /* init inner context */ + MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ + + MD5Init(&hmac->octx); /* init outer context */ + MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ + + /* scrub the pads and key context (if used) */ + MD5_memset(&k_ipad, 0, sizeof(k_ipad)); + MD5_memset(&k_opad, 0, sizeof(k_opad)); + MD5_memset(&tk, 0, sizeof(tk)); + + /* and we're done. */ +} + +/* The precalc and import routines here rely on the fact that we pad + * the key out to 64 bytes and use that to initialize the md5 + * contexts, and that updating an md5 context with 64 bytes of data + * leaves nothing left over; all of the interesting state is contained + * in the state field, and none of it is left over in the count and + * buffer fields. So all we have to do is save the state field; we + * can zero the others when we reload it. Which is why the decision + * was made to pad the key out to 64 bytes in the first place. */ +void hmac_md5_precalc(HMAC_MD5_STATE *state, + const unsigned char *key, + int key_len) +{ + HMAC_MD5_CTX hmac; + unsigned lupe; + + hmac_md5_init(&hmac, key, key_len); + for (lupe = 0; lupe < 4; lupe++) { + state->istate[lupe] = htonl(hmac.ictx.state[lupe]); + state->ostate[lupe] = htonl(hmac.octx.state[lupe]); + } + MD5_memset(&hmac, 0, sizeof(hmac)); +} + + +void hmac_md5_import(HMAC_MD5_CTX *hmac, + HMAC_MD5_STATE *state) +{ + unsigned lupe; + MD5_memset(hmac, 0, sizeof(HMAC_MD5_CTX)); + for (lupe = 0; lupe < 4; lupe++) { + hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); + hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); + } + /* Init the counts to account for our having applied + * 64 bytes of key; this works out to 0x200 (64 << 3; see + * MD5Update above...) */ + hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; +} + +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac) +{ + MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ + MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ + MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ +} + + +void hmac_md5(text, text_len, key, key_len, digest) +const unsigned char* text; /* pointer to data stream */ +int text_len; /* length of data stream */ +const unsigned char* key; /* pointer to authentication key */ +int key_len; /* length of authentication key */ +unsigned char *digest; /* caller digest to be filled in */ +{ + MD5_CTX context; + + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ + +} diff --git a/kmicromail/libetpan/tools/md5.h b/kmicromail/libetpan/tools/md5.h new file mode 100644 index 0000000..e62f157 --- a/dev/null +++ b/kmicromail/libetpan/tools/md5.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "md5global.h" + +#ifndef MD5_H + +#define MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); + +void hmac_md5 PROTO_LIST ((unsigned char *, int, unsigned char *, int, caddr_t)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/md5global.h b/kmicromail/libetpan/tools/md5global.h new file mode 100644 index 0000000..9089c9a --- a/dev/null +++ b/kmicromail/libetpan/tools/md5global.h @@ -0,0 +1,79 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +/* GLOBAL.H - RSAREF types and constants + */ + +#ifndef MD5GLOBAL_H + +#define MD5GLOBAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned long int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/tools/mmapstring.c b/kmicromail/libetpan/tools/mmapstring.c new file mode 100644 index 0000000..8c44842 --- a/dev/null +++ b/kmicromail/libetpan/tools/mmapstring.c @@ -0,0 +1,526 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mmapstring.h" + +#include "chash.h" + +#include +#include +#include +#include +#include + +#include "libetpan-config.h" + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024) + +#define DEFAULT_TMP_PATH "/tmp" + +static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH; + +static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL; + +/* MMAPString references */ + +static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER; +static chash * mmapstring_hashtable = NULL; + +static void mmapstring_hashtable_init() +{ + mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +void mmap_string_set_tmpdir(char * directory) +{ + strncpy(tmpdir, directory, PATH_MAX); + tmpdir[PATH_MAX - 1] = 0; +} + + +int mmap_string_ref(MMAPString * string) +{ + chash * ht; + int r; + chashdatum key; + chashdatum data; + + pthread_mutex_lock(&mmapstring_lock); + if (mmapstring_hashtable == NULL) { + mmapstring_hashtable_init(); + } + ht = mmapstring_hashtable; + + if (ht == NULL) { + pthread_mutex_unlock(&mmapstring_lock); + return -1; + } + + key.data = &string->str; + key.len = sizeof(string->str); + data.data = string; + data.len = 0; + + r = chash_set(mmapstring_hashtable, &key, &data, NULL); + pthread_mutex_unlock(&mmapstring_lock); + + if (r < 0) + return r; + + return 0; +} + +int mmap_string_unref(char * str) +{ + MMAPString * string; + chash * ht; + chashdatum key; + chashdatum data; + int r; + + pthread_mutex_lock(&mmapstring_lock); + ht = mmapstring_hashtable; + + if (ht == NULL) { + pthread_mutex_unlock(&mmapstring_lock); + return -1; + } + + key.data = &str; + key.len = sizeof(str); + + r = chash_get(ht, &key, &data); + if (r < 0) + string = NULL; + else + string = data.data; + + if (string != NULL) { + chash_delete(ht, &key, NULL); + if (chash_count(ht) == 0) { + chash_free(ht); + mmapstring_hashtable = NULL; + } + } + + pthread_mutex_unlock(&mmapstring_lock); + + if (string != NULL) { + mmap_string_free(string); + return 0; + } + else + return -1; +} + + + +/* MMAPString */ + +#define MY_MAXSIZE ((size_t) -1) + +static inline size_t +nearest_power (size_t base, size_t num) +{ + if (num > MY_MAXSIZE / 2) { + return MY_MAXSIZE; + } + else { + size_t n = base; + + while (n < num) + n <<= 1; + + return n; + } +} + +void mmap_string_set_ceil(size_t ceil) +{ + mmap_string_ceil = ceil; +} + +/* Strings. + */ + +static MMAPString * mmap_string_realloc_file(MMAPString * string) +{ + char * data; + + if (string->fd == -1) { + char tmpfilename[PATH_MAX]; + int fd; + + * tmpfilename = 0; + strcat(tmpfilename, tmpdir); + strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX"); + + fd = mkstemp(tmpfilename); + if (fd == -1) + return NULL; + + if (unlink(tmpfilename) == -1) { + close(fd); + return NULL; + } + + if (ftruncate(fd, string->allocated_len) == -1) { + close(fd); + return NULL; + } + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) { + close(fd); + return NULL; + } + + if (string->str != NULL) + memcpy(data, string->str, string->len + 1); + + string->fd = fd; + string->mmapped_size = string->allocated_len; + free(string->str); + string->str = data; + } + else { + if (munmap(string->str, string->mmapped_size) == -1) + return NULL; + + if (ftruncate(string->fd, string->allocated_len) == -1) + return NULL; + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, string->fd, 0); + + if (data == MAP_FAILED) + return NULL; + + string->mmapped_size = string->allocated_len; + string->str = data; + } + + return string; +} + +static MMAPString * mmap_string_realloc_memory(MMAPString * string) +{ + char * tmp; + + tmp = realloc (string->str, string->allocated_len); + + if (tmp == NULL) + string = NULL; + else + string->str = tmp; + + return string; +} + +static MMAPString * +mmap_string_maybe_expand (MMAPString* string, + size_t len) +{ + if (string->len + len >= string->allocated_len) + { + size_t old_size; + MMAPString * newstring; + + old_size = string->allocated_len; + + string->allocated_len = nearest_power (1, string->len + len + 1); + +#ifndef MMAP_UNAVAILABLE + if (string->allocated_len > mmap_string_ceil) + newstring = mmap_string_realloc_file(string); + else { +#endif + newstring = mmap_string_realloc_memory(string); +#ifndef MMAP_UNAVAILABLE + if (newstring == NULL) + newstring = mmap_string_realloc_file(string); + } +#endif + + if (newstring == NULL) + string->allocated_len = old_size; + } + + return string; +} + +MMAPString* +mmap_string_sized_new (size_t dfl_size) +{ + MMAPString *string; + + string = malloc(sizeof(* string)); + if (string == NULL) + return NULL; + + string->allocated_len = 0; + string->len = 0; + string->str = NULL; + string->fd = -1; + string->mmapped_size = 0; + + if (mmap_string_maybe_expand (string, MAX (dfl_size, 2)) == NULL) + return NULL; + + string->str[0] = 0; + + return string; +} + +MMAPString* +mmap_string_new (const char *init) +{ + MMAPString *string; + + string = mmap_string_sized_new (init ? strlen (init) + 2 : 2); + if (string == NULL) + return NULL; + + if (init) + mmap_string_append (string, init); + + return string; +} + +MMAPString* +mmap_string_new_len (const char *init, + size_t len) +{ + MMAPString *string; + + if (len <= 0) + return mmap_string_new (init); + else + { + string = mmap_string_sized_new (len); + + if (init) + mmap_string_append_len (string, init, len); + + return string; + } +} + +void +mmap_string_free (MMAPString *string) +{ + if (string == NULL) + return; + + if (string->fd != -1) { + munmap(string->str, string->mmapped_size); + close(string->fd); + } + else { + free (string->str); + } + free(string); +} + +MMAPString* +mmap_string_assign (MMAPString *string, + const char *rval) +{ + mmap_string_truncate (string, 0); + if (mmap_string_append (string, rval) == NULL) + return NULL; + + return string; +} + +MMAPString* +mmap_string_truncate (MMAPString *string, + size_t len) +{ + string->len = MIN (len, string->len); + string->str[string->len] = 0; + + return string; +} + +/** + * mmap_string_set_size: + * @string: a #MMAPString + * @len: the new length + * + * Sets the length of a #MMAPString. If the length is less than + * the current length, the string will be truncated. If the + * length is greater than the current length, the contents + * of the newly added area are undefined. (However, as + * always, string->str[string->len] will be a nul byte.) + * + * Return value: @string + **/ +MMAPString* +mmap_string_set_size (MMAPString *string, + size_t len) +{ + if (len >= string->allocated_len) + if (mmap_string_maybe_expand (string, len - string->len) == NULL) + return NULL; + + string->len = len; + string->str[len] = 0; + + return string; +} + +/* +static int in_mapped_zone(MMAPString * string, char * val) +{ + return (val >= string->str) && (val < string->str + string->mmapped_size); +} +*/ + +MMAPString* +mmap_string_insert_len (MMAPString *string, + size_t pos, + const char *val, + size_t len) +{ + if (mmap_string_maybe_expand (string, len) == NULL) + return NULL; + + if (pos < string->len) + memmove (string->str + pos + len, string->str + pos, string->len - pos); + + /* insert the new string */ + memmove (string->str + pos, val, len); + + string->len += len; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_append (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, string->len, val, strlen(val)); +} + +MMAPString* +mmap_string_append_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, string->len, val, len); +} + +MMAPString* +mmap_string_append_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, string->len, c); +} + +MMAPString* +mmap_string_prepend (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, 0, val, strlen(val)); +} + +MMAPString* +mmap_string_prepend_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, 0, val, len); +} + +MMAPString* +mmap_string_prepend_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, 0, c); +} + +MMAPString* +mmap_string_insert (MMAPString *string, + size_t pos, + const char *val) +{ + return mmap_string_insert_len (string, pos, val, strlen(val)); +} + +MMAPString* +mmap_string_insert_c (MMAPString *string, + size_t pos, + char c) +{ + if (mmap_string_maybe_expand (string, 1) == NULL) + return NULL; + + /* If not just an append, move the old stuff */ + if (pos < string->len) + memmove (string->str + pos + 1, string->str + pos, string->len - pos); + + string->str[pos] = c; + + string->len += 1; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_erase (MMAPString *string, + size_t pos, + size_t len) +{ + if ((pos + len) < string->len) + memmove (string->str + pos, string->str + pos + len, + string->len - (pos + len)); + + string->len -= len; + + string->str[string->len] = 0; + + return string; +} diff --git a/kmicromail/libetpan/tools/mmapstring.h b/kmicromail/libetpan/tools/mmapstring.h new file mode 100644 index 0000000..6d7227d --- a/dev/null +++ b/kmicromail/libetpan/tools/mmapstring.h @@ -0,0 +1,136 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#ifndef __MMAP_STRING_H__ + +#define __MMAP_STRING_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +#define TMPDIR "/tmp" +*/ + +typedef struct _MMAPString MMAPString; + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; + /* + char * old_non_mmapped_str; + */ +}; + +/* configure location of mmaped files */ + +void mmap_string_set_tmpdir(char * directory); + +/* Strings + */ + +MMAPString * mmap_string_new (const char * init); + +MMAPString * mmap_string_new_len (const char * init, + size_t len); + +MMAPString * mmap_string_sized_new (size_t dfl_size); + +void mmap_string_free (MMAPString * string); + +MMAPString * mmap_string_assign (MMAPString * string, + const char * rval); + +MMAPString * mmap_string_truncate (MMAPString *string, + size_t len); + +MMAPString * mmap_string_set_size (MMAPString * string, + size_t len); + +MMAPString * mmap_string_insert_len (MMAPString * string, + size_t pos, + const char * val, + size_t len); + +MMAPString * mmap_string_append (MMAPString * string, + const char * val); + +MMAPString * mmap_string_append_len (MMAPString * string, + const char * val, + size_t len); + +MMAPString * mmap_string_append_c (MMAPString * string, + char c); + +MMAPString * mmap_string_prepend (MMAPString * string, + const char * val); + +MMAPString * mmap_string_prepend_c (MMAPString * string, + char c); + +MMAPString * mmap_string_prepend_len (MMAPString * string, + const char * val, + size_t len); + +MMAPString * mmap_string_insert (MMAPString * string, + size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c (MMAPString *string, + size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, + size_t pos, + size_t len); + +void mmap_string_set_ceil(size_t ceil); + +int mmap_string_ref(MMAPString * string); +int mmap_string_unref(char * str); + +#ifdef __cplusplus +} +#endif + + +#endif /* __MMAP_STRING_H__ */ diff --git a/kmicromail/libmailwrapper/.cvsignore b/kmicromail/libmailwrapper/.cvsignore new file mode 100644 index 0000000..581c299 --- a/dev/null +++ b/kmicromail/libmailwrapper/.cvsignore @@ -0,0 +1,6 @@ +logindialogui.cpp +logindialogui.h +sendmailprogressui.cpp +sendmailprogressui.h +.moc +Makefile diff --git a/kmicromail/libmailwrapper/abstractmail.cpp b/kmicromail/libmailwrapper/abstractmail.cpp new file mode 100644 index 0000000..128a7c0 --- a/dev/null +++ b/kmicromail/libmailwrapper/abstractmail.cpp @@ -0,0 +1,172 @@ +#include "abstractmail.h" +#include "imapwrapper.h" +#include "pop3wrapper.h" +#include "nntpwrapper.h" +#include "mhwrapper.h" +#include "mailtypes.h" + + + +#include +#include +#include +#include +#include +#include + +using namespace Opie::Core; +AbstractMail* AbstractMail::getWrapper(IMAPaccount *a) +{ + return new IMAPwrapper(a); +} + +AbstractMail* AbstractMail::getWrapper(POP3account *a) +{ + return new POP3wrapper(a); +} + +AbstractMail* AbstractMail::getWrapper(NNTPaccount *a) +{ + return new NNTPwrapper(a); +} + +AbstractMail* AbstractMail::getWrapper(const QString&a,const QString&name) +{ + return new MHwrapper(a,name); +} + +AbstractMail* AbstractMail::getWrapper(Account*a) +{ + if (!a) return 0; + switch (a->getType()) { + case MAILLIB::A_IMAP: + return new IMAPwrapper((IMAPaccount*)a); + break; + case MAILLIB::A_POP3: + return new POP3wrapper((POP3account*)a); + break; + case MAILLIB::A_NNTP: + return new NNTPwrapper((NNTPaccount*)a); + break; + default: + return 0; + } +} + +encodedString* AbstractMail::decode_String(const encodedString*text,const QString&enc) +{ + // odebug << "Decode string start" << oendl; + char*result_text; + size_t index = 0; + /* reset for recursive use! */ + size_t target_length = 0; + result_text = 0; + int mimetype = MAILMIME_MECHANISM_7BIT; + if (enc.lower()=="quoted-printable") { + mimetype = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } else if (enc.lower()=="base64") { + mimetype = MAILMIME_MECHANISM_BASE64; + } else if (enc.lower()=="8bit") { + mimetype = MAILMIME_MECHANISM_8BIT; + } else if (enc.lower()=="binary") { + mimetype = MAILMIME_MECHANISM_BINARY; + } + + int err = mailmime_part_parse(text->Content(),text->Length(),&index,mimetype, + &result_text,&target_length); + + encodedString* result = new encodedString(); + if (err == MAILIMF_NO_ERROR) { + result->setContent(result_text,target_length); + } + //odebug << "Decode string finished" << oendl; + return result; +} + +QString AbstractMail::convert_String(const char*text) +{ + //size_t index = 0; + char*res = 0; + int err = MAILIMF_NO_ERROR; + + QString result(text); + + /* due a bug in libetpan it isn't usable this moment */ +/* int err = mailmime_encoded_phrase_parse("iso-8859-1", + text, strlen(text),&index, "iso-8859-1",&res);*/ + //odebug << "Input: " << text << "" << oendl; + if (err == MAILIMF_NO_ERROR && res && strlen(res)) { +// result = QString(res); +// odebug << "Res: " << res << ", length: " << strlen(res) << "" << oendl; + } + if (res) free(res); + return result; +} + +/* cp & paste from launcher */ +QString AbstractMail::gen_attachment_id() +{ + QFile file( "/proc/sys/kernel/random/uuid" ); + if (!file.open(IO_ReadOnly ) ) + return QString::null; + + QTextStream stream(&file); + + return "{" + stream.read().stripWhiteSpace() + "}"; +} + +int AbstractMail::createMbox(const QString&,const FolderP&,const QString& ,bool) +{ + return 0; +} + +QString AbstractMail::defaultLocalfolder() +{ + // QString f = getenv( "HOME" ); + QString f = locateLocal( "data", "kmicromail/localmail"); + // f += "/Applications/opiemail/localmail"; + return f; +} + +QString AbstractMail::draftFolder() +{ + return QString("Drafts"); +} + +/* temporary - will be removed when implemented in all classes */ +void AbstractMail::deleteMails(const QString &,const QValueList > &) +{ +} + +void AbstractMail::mvcpAllMails(const FolderP&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + QValueList t; + listMessages(fromFolder->getName(),t); + encodedString*st = 0; + while (t.count()>0) { + RecMailP r = (*t.begin()); + st = fetchRawBody(r); + if (st) { + targetWrapper->storeMessage(st->Content(),st->Length(),targetFolder); + delete st; + } + t.remove(t.begin()); + } + if (moveit) { + deleteAllMail(fromFolder); + } +} + +void AbstractMail::mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + encodedString*st = 0; + st = fetchRawBody(mail); + if (st) { + targetWrapper->storeMessage(st->Content(),st->Length(),targetFolder); + delete st; + } + if (moveit) { + deleteMail(mail); + } +} diff --git a/kmicromail/libmailwrapper/abstractmail.h b/kmicromail/libmailwrapper/abstractmail.h new file mode 100644 index 0000000..e5d64a6 --- a/dev/null +++ b/kmicromail/libmailwrapper/abstractmail.h @@ -0,0 +1,72 @@ +#ifndef __abstract_mail_ +#define __abstract_mail_ + +#include "maildefines.h" + +#include "settings.h" + +#include +#include +#include "mailtypes.h" + +class IMAPwrapper; +class POP3wrapper; +class Folder; +class encodedString; +struct folderStat; + +class AbstractMail:public QObject +{ + Q_OBJECT +public: + AbstractMail(){}; + virtual ~AbstractMail(){} + virtual QValueList >* listFolders()=0; + virtual void listMessages(const QString & mailbox,QValueList&target )=0; + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX")=0; + virtual RecBodyP fetchBody(const RecMailP&mail)=0; + virtual QString fetchTextPart(const RecMailP&mail,const RecPartP&part)=0; + virtual encodedString* fetchDecodedPart(const RecMailP&mail,const RecPartP&part)=0; + virtual encodedString* fetchRawPart(const RecMailP&mail,const RecPartP&part)=0; + virtual encodedString* fetchRawBody(const RecMailP&mail)=0; + + virtual void deleteMail(const RecMailP&mail)=0; + virtual void answeredMail(const RecMailP&mail)=0; + virtual int deleteAllMail(const Opie::Core::OSmartPointer&)=0; + virtual void deleteMails(const QString & FolderName,const QValueList >&target); + virtual int deleteMbox(const Opie::Core::OSmartPointer&)=0; + virtual void storeMessage(const char*msg,size_t length, const QString&folder)=0; + + virtual void mvcpAllMails(const Opie::Core::OSmartPointer&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + virtual void mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + + virtual void cleanMimeCache(){}; + /* mail box methods */ + /* parameter is the box to create. + * if the implementing subclass has prefixes, + * them has to be appended automatic. + */ + virtual int createMbox(const QString&,const Opie::Core::OSmartPointer&parentfolder=0, + const QString& delemiter="/",bool getsubfolder=false); + virtual void logout()=0; + + static AbstractMail* getWrapper(IMAPaccount *a); + static AbstractMail* getWrapper(POP3account *a); + static AbstractMail* getWrapper(NNTPaccount *a); + /* mbox only! */ + static AbstractMail* getWrapper(const QString&a,const QString&name="Local Folders"); + static AbstractMail* getWrapper(Account*a); + + static QString defaultLocalfolder(); + static QString draftFolder(); + + virtual MAILLIB::ATYPE getType()const=0; + virtual const QString&getName()const=0; + +protected: + static encodedString*decode_String(const encodedString*text,const QString&enc); + static QString convert_String(const char*text); + static QString gen_attachment_id(); +}; +#endif diff --git a/kmicromail/libmailwrapper/config.in b/kmicromail/libmailwrapper/config.in new file mode 100644 index 0000000..7da4a05 --- a/dev/null +++ b/kmicromail/libmailwrapper/config.in @@ -0,0 +1,4 @@ + config LIBMAILWRAPPER + boolean "libmailwrapper (libetpan wrapper library)" + default "y" + depends ( LIBQPE || LIBQPE-X11 ) && LIBETPAN_DEP diff --git a/kmicromail/libmailwrapper/generatemail.cpp b/kmicromail/libmailwrapper/generatemail.cpp new file mode 100644 index 0000000..49315ba --- a/dev/null +++ b/kmicromail/libmailwrapper/generatemail.cpp @@ -0,0 +1,460 @@ +#include "generatemail.h" +#include "mailwrapper.h" + +#include + +//#include + +#include +#include + +using namespace Opie::Core; +const char* Generatemail::USER_AGENT="OpieMail v0.6"; + +Generatemail::Generatemail() +{ +} + +Generatemail::~Generatemail() +{ +} + +void Generatemail::addRcpts( clist *list, mailimf_address_list *addr_list ) { + clistiter *it, *it2; + + for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { + mailimf_address *addr; + addr = (mailimf_address *) it->data; + + if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { + esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); + } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { + clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; + for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { + mailimf_mailbox *mbox; + mbox = (mailimf_mailbox *) it2->data; + esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); + } + } + } +} + +char *Generatemail::getFrom( mailimf_field *ffrom) { + char *from = NULL; + if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) + && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { + clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; + clistiter *it; + for ( it = clist_begin( cl ); it; it = it->next ) { + mailimf_mailbox *mb = (mailimf_mailbox *) it->data; + from = strdup( mb->mb_addr_spec ); + } + } + + return from; +} + +char *Generatemail::getFrom( mailmime *mail ) { + /* no need to delete - its just a pointer to structure content */ + mailimf_field *ffrom = 0; + ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); + return getFrom(ffrom); +} + +mailimf_field *Generatemail::getField( mailimf_fields *fields, int type ) { + mailimf_field *field; + clistiter *it; + + it = clist_begin( fields->fld_list ); + while ( it ) { + field = (mailimf_field *) it->data; + if ( field->fld_type == type ) { + return field; + } + it = it->next; + } + + return NULL; +} + +mailimf_address_list *Generatemail::parseAddresses(const QString&addr ) { + mailimf_address_list *addresses; + + if ( addr.isEmpty() ) + return NULL; + + addresses = mailimf_address_list_new_empty(); + + bool literal_open = false; + unsigned int startpos = 0; + QStringList list; + QString s; + unsigned int i = 0; + for (; i < addr.length();++i) { + switch (addr[i]) { + case '\"': + literal_open = !literal_open; + break; + case ',': + if (!literal_open) { + s = addr.mid(startpos,i-startpos); + if (!s.isEmpty()) { + list.append(s); + } + // !!!! this is a MUST BE! + startpos = ++i; + } + break; + default: + break; + } + } + s = addr.mid(startpos,i-startpos); + if (!s.isEmpty()) { + list.append(s); + } + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); it++ ) { + int err = mailimf_address_list_add_parse( addresses, (char*)(*it).latin1() ); + if ( err != MAILIMF_NO_ERROR ) { + qDebug(" Error parsing"); // *it + } else { + } + } + return addresses; +} + +mailmime *Generatemail::buildFilePart(const QString&filename,const QString&mimetype,const QString&TextContent ) { + mailmime * filePart = 0; + mailmime_fields * fields = 0; + mailmime_content * content = 0; + mailmime_parameter * param = 0; + char*name = 0; + char*file = 0; + int err; + + int pos = filename.findRev( '/' ); + + if (filename.length()>0) { + QString tmp = filename.right( filename.length() - ( pos + 1 ) ); + name = strdup( tmp.latin1() ); // just filename + file = strdup( filename.latin1() ); // full name with path + } + + int disptype = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + int mechanism = MAILMIME_MECHANISM_BASE64; + + if ( mimetype.startsWith( "text/" ) ) { + param = mailmime_parameter_new( strdup( "charset" ), + strdup( "iso-8859-1" ) ); + mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + + fields = mailmime_fields_new_filename( + disptype, name, + mechanism ); + content = mailmime_content_new_with_str( (char*)mimetype.latin1() ); + if (content!=0 && fields != 0) { + if (param) { + clist_append(content->ct_parameters,param); + param = 0; + } + if (filename.length()>0) { + QFileInfo f(filename); + param = mailmime_parameter_new(strdup("name"),strdup(f.fileName().latin1())); + clist_append(content->ct_parameters,param); + param = 0; + } + filePart = mailmime_new_empty( content, fields ); + } + if (filePart) { + if (filename.length()>0) { + err = mailmime_set_body_file( filePart, file ); + } else { + err = mailmime_set_body_text(filePart,strdup(TextContent.data()),TextContent.length()); + } + if (err != MAILIMF_NO_ERROR) { + qDebug("Error setting body with file "); + mailmime_free( filePart ); + filePart = 0; + } + } + + if (!filePart) { + if ( param != NULL ) { + mailmime_parameter_free( param ); + } + if (content) { + mailmime_content_free( content ); + } + if (fields) { + mailmime_fields_free( fields ); + } else { + if (name) { + free( name ); + } + if (file) { + free( file ); + } + } + } + return filePart; // Success :) + +} + +void Generatemail::addFileParts( mailmime *message,const QList&files ) { + const Attachment *it; + unsigned int count = files.count(); + for ( unsigned int i = 0; i < count; ++i ) { + mailmime *filePart; + int err; + it = ((QList)files).at(i); + + filePart = buildFilePart( it->getFileName(), it->getMimeType(),"" ); + if ( filePart == NULL ) { + continue; + } + err = mailmime_smart_add_part( message, filePart ); + if ( err != MAILIMF_NO_ERROR ) { + mailmime_free( filePart ); + } + } +} + +mailmime *Generatemail::buildTxtPart(const QString&str ) { + mailmime *txtPart; + mailmime_fields *fields; + mailmime_content *content; + mailmime_parameter *param; + int err; + + param = mailmime_parameter_new( strdup( "charset" ), + strdup( "iso-8859-1" ) ); + if ( param == NULL ) + goto err_free; + + content = mailmime_content_new_with_str( "text/plain" ); + if ( content == NULL ) + goto err_free_param; + + err = clist_append( content->ct_parameters, param ); + if ( err != MAILIMF_NO_ERROR ) + goto err_free_content; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if ( fields == NULL ) + goto err_free_content; + + txtPart = mailmime_new_empty( content, fields ); + if ( txtPart == NULL ) + goto err_free_fields; + + err = mailmime_set_body_text( txtPart, (char*)str.data(), str.length() ); + if ( err != MAILIMF_NO_ERROR ) + goto err_free_txtPart; + + return txtPart; // Success :) + +err_free_txtPart: + mailmime_free( txtPart ); +err_free_fields: + mailmime_fields_free( fields ); +err_free_content: + mailmime_content_free( content ); +err_free_param: + mailmime_parameter_free( param ); +err_free: + ; + + return NULL; // Error :( +} + +mailimf_mailbox *Generatemail::newMailbox(const QString&name, const QString&mail ) { + return mailimf_mailbox_new( strdup( name.latin1() ), + strdup( mail.latin1() ) ); +} + +mailimf_fields *Generatemail::createImfFields(const Opie::Core::OSmartPointer&mail ) +{ + mailimf_fields *fields = NULL; + mailimf_field *xmailer = NULL; + mailimf_mailbox *sender=0,*fromBox=0; + mailimf_mailbox_list *from=0; + mailimf_address_list *to=0, *cc=0, *bcc=0, *reply=0; + clist*in_reply_to = 0; + char *subject = strdup( mail->getSubject().latin1() ); + int err; + int res = 1; + + sender = newMailbox( mail->getName(), mail->getMail() ); + if ( sender == NULL ) { + res = 0; + } + + if (res) { + fromBox = newMailbox( mail->getName(), mail->getMail() ); + } + if ( fromBox == NULL ) { + res = 0; + } + + if (res) { + from = mailimf_mailbox_list_new_empty(); + } + if ( from == NULL ) { + res = 0; + } + + if (res && from) { + err = mailimf_mailbox_list_add( from, fromBox ); + if ( err != MAILIMF_NO_ERROR ) { + res = 0; + } + } + + if (res) to = parseAddresses( mail->getTo() ); + if (res) cc = parseAddresses( mail->getCC() ); + if (res) bcc = parseAddresses( mail->getBCC() ); + if (res) reply = parseAddresses( mail->getReply() ); + + if (res && mail->Inreply().count()>0) { + in_reply_to = clist_new(); + char*c_reply; + unsigned int nsize = 0; + for (QStringList::ConstIterator it=mail->Inreply().begin(); + it != mail->Inreply().end();++it) { + if ((*it).isEmpty()) + continue; + QString h((*it)); + while (h.length()>0 && h[0]=='<') { + h.remove(0,1); + } + while (h.length()>0 && h[h.length()-1]=='>') { + h.remove(h.length()-1,1); + } + if (h.isEmpty()) continue; + nsize = strlen(h.latin1()); + /* yes! must be malloc! */ + c_reply = (char*)malloc( (nsize+1)*sizeof(char)); + memset(c_reply,0,nsize+1); + memcpy(c_reply,h.latin1(),nsize); + clist_append(in_reply_to,c_reply); + } + } + + if (res) { + fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc, + in_reply_to, NULL, subject ); + if ( fields == NULL ) { + res = 0; + } + } + if (res) xmailer = mailimf_field_new_custom( strdup( "User-Agent" ), + strdup( USER_AGENT ) ); + if ( xmailer == NULL ) { + res = 0; + } else { + err = mailimf_fields_add( fields, xmailer ); + if ( err != MAILIMF_NO_ERROR ) { + res = 0; + } + } + if (!res ) { + if (xmailer) { + mailimf_field_free( xmailer ); + xmailer = NULL; + } + if (fields) { + mailimf_fields_free( fields ); + fields = NULL; + } else { + if (reply) + mailimf_address_list_free( reply ); + if (bcc) + mailimf_address_list_free( bcc ); + if (cc) + mailimf_address_list_free( cc ); + if (to) + mailimf_address_list_free( to ); + if (fromBox) { + mailimf_mailbox_free( fromBox ); + } else if (from) { + mailimf_mailbox_list_free( from ); + } + if (sender) { + mailimf_mailbox_free( sender ); + } + if (subject) { + free( subject ); + } + } + } + return fields; +} + +mailmime *Generatemail::createMimeMail(const Opie::Core::OSmartPointer &mail ) { + mailmime *message, *txtPart; + mailimf_fields *fields; + int err; + + fields = createImfFields( mail ); + if ( fields == NULL ) + goto err_free; + + message = mailmime_new_message_data( NULL ); + if ( message == NULL ) + goto err_free_fields; + + mailmime_set_imf_fields( message, fields ); + + txtPart = buildTxtPart( mail->getMessage() ); + + if ( txtPart == NULL ) + goto err_free_message; + + err = mailmime_smart_add_part( message, txtPart ); + if ( err != MAILIMF_NO_ERROR ) + goto err_free_txtPart; + + addFileParts( message, mail->getAttachments() ); + + return message; // Success :) + +err_free_txtPart: + mailmime_free( txtPart ); +err_free_message: + mailmime_free( message ); +err_free_fields: + mailimf_fields_free( fields ); +err_free: + ; + + return NULL; // Error :( +} + +clist *Generatemail::createRcptList( mailimf_fields *fields ) { + clist *rcptList; + mailimf_field *field; + + rcptList = esmtp_address_list_new(); + + field = getField( fields, MAILIMF_FIELD_TO ); + if ( field && (field->fld_type == MAILIMF_FIELD_TO) + && field->fld_data.fld_to->to_addr_list ) { + addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); + } + + field = getField( fields, MAILIMF_FIELD_CC ); + if ( field && (field->fld_type == MAILIMF_FIELD_CC) + && field->fld_data.fld_cc->cc_addr_list ) { + addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); + } + + field = getField( fields, MAILIMF_FIELD_BCC ); + if ( field && (field->fld_type == MAILIMF_FIELD_BCC) + && field->fld_data.fld_bcc->bcc_addr_list ) { + addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); + } + + return rcptList; +} diff --git a/kmicromail/libmailwrapper/generatemail.h b/kmicromail/libmailwrapper/generatemail.h new file mode 100644 index 0000000..a767b61 --- a/dev/null +++ b/kmicromail/libmailwrapper/generatemail.h @@ -0,0 +1,46 @@ +#ifndef __GENERATE_MAIL_H +#define __GENERATE_MAIL_H + +#include + +#include +#include + +#include + +class Mail; +class RecMail; +class Attachment; +struct mailimf_fields; +struct mailimf_field; +struct mailimf_mailbox; +struct mailmime; +struct mailimf_address_list; +class progressMailSend; +struct mailsmtp; + +class Generatemail : public QObject +{ + Q_OBJECT +public: + Generatemail(); + virtual ~Generatemail(); + +protected: + static void addRcpts( clist *list, mailimf_address_list *addr_list ); + static char *getFrom( mailmime *mail ); + static char *getFrom( mailimf_field *ffrom); + static mailimf_field *getField( mailimf_fields *fields, int type ); + mailimf_address_list *parseAddresses(const QString&addr ); + void addFileParts( mailmime *message,const QList&files ); + mailmime *buildFilePart(const QString&filename,const QString&mimetype,const QString&content); + mailmime *buildTxtPart(const QString&str ); + mailimf_mailbox *newMailbox(const QString&name,const QString&mail ); + mailimf_fields *createImfFields(const Opie::Core::OSmartPointer &mail ); + mailmime *createMimeMail(const Opie::Core::OSmartPointer&mail ); + clist *createRcptList( mailimf_fields *fields ); + + static const char* USER_AGENT; +}; + +#endif diff --git a/kmicromail/libmailwrapper/genericwrapper.cpp b/kmicromail/libmailwrapper/genericwrapper.cpp new file mode 100644 index 0000000..f804e44 --- a/dev/null +++ b/kmicromail/libmailwrapper/genericwrapper.cpp @@ -0,0 +1,480 @@ +#include "genericwrapper.h" +#include +#include "mailtypes.h" + + + +using namespace Opie::Core; +Genericwrapper::Genericwrapper() + : AbstractMail() +{ + bodyCache.clear(); + m_storage = 0; + m_folder = 0; +} + +Genericwrapper::~Genericwrapper() +{ + if (m_folder) { + mailfolder_free(m_folder); + } + if (m_storage) { + mailstorage_free(m_storage); + } + cleanMimeCache(); +} + +void Genericwrapper::fillSingleBody(RecPartP&target,mailmessage*,mailmime*mime) +{ + if (!mime) { + return; + } + mailmime_field*field = 0; + mailmime_single_fields fields; + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime->mm_mime_fields != NULL) { + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + } + + mailmime_content*type = fields.fld_content; + clistcell*current; + if (!type) { + target->setType("text"); + target->setSubtype("plain"); + } else { + target->setSubtype(type->ct_subtype); + switch(type->ct_type->tp_data.tp_discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + target->setType("text"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + target->setType("image"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + target->setType("audio"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + target->setType("video"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + target->setType("application"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + default: + if (type->ct_type->tp_data.tp_discrete_type->dt_extension) { + target->setType(type->ct_type->tp_data.tp_discrete_type->dt_extension); + } + break; + } + if (type->ct_parameters) { + fillParameters(target,type->ct_parameters); + } + } + if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) { + for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) { + field = (mailmime_field*)current->data; + switch(field->fld_type) { + case MAILMIME_FIELD_TRANSFER_ENCODING: + target->setEncoding(getencoding(field->fld_data.fld_encoding)); + break; + case MAILMIME_FIELD_ID: + target->setIdentifier(field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + target->setDescription(field->fld_data.fld_description); + break; + default: + break; + } + } + } +} + +void Genericwrapper::fillParameters(RecPartP&target,clist*parameters) +{ + if (!parameters) {return;} + clistcell*current=0; + mailmime_parameter*param; + for (current=clist_begin(parameters);current!=0;current=clist_next(current)) { + param = (mailmime_parameter*)current->data; + if (param) { + target->addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); + } + } +} + +QString Genericwrapper::getencoding(mailmime_mechanism*aEnc) +{ + QString enc="7bit"; + if (!aEnc) return enc; + switch(aEnc->enc_type) { + case MAILMIME_MECHANISM_7BIT: + enc = "7bit"; + break; + case MAILMIME_MECHANISM_8BIT: + enc = "8bit"; + break; + case MAILMIME_MECHANISM_BINARY: + enc = "binary"; + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + enc = "quoted-printable"; + break; + case MAILMIME_MECHANISM_BASE64: + enc = "base64"; + break; + case MAILMIME_MECHANISM_TOKEN: + default: + if (aEnc->enc_token) { + enc = QString(aEnc->enc_token); + } + break; + } + return enc; +} + +void Genericwrapper::traverseBody(RecBodyP&target,mailmessage*message,mailmime*mime,QValueListrecList,unsigned int current_rec,int current_count) +{ + if (current_rec >= 10) { + ; // odebug << "too deep recursion!" << oendl; + } + if (!message || !mime) { + return; + } + int r; + char*data = 0; + size_t len; + clistiter * cur = 0; + QString b; + RecPartP part = new RecPart(); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + { + QValueListcountlist = recList; + countlist.append(current_count); + r = mailmessage_fetch_section(message,mime,&data,&len); + part->setSize(len); + part->setPositionlist(countlist); + b = gen_attachment_id(); + part->setIdentifier(b); + fillSingleBody(part,message,mime); + if (part->Type()=="text" && target->Bodytext().isNull()) { + encodedString*rs = new encodedString(); + rs->setContent(data,len); + encodedString*res = decode_String(rs,part->Encoding()); + if (countlist.count()>2) { + bodyCache[b]=rs; + target->addPart(part); + } else { + delete rs; + } + b = QString(res->Content()); + delete res; + target->setBodytext(b); + target->setDescription(part); + } else { + bodyCache[b]=new encodedString(data,len); + target->addPart(part); + } + } + break; + case MAILMIME_MULTIPLE: + { + unsigned int ccount = 1; + mailmime*cbody=0; + QValueListcountlist = recList; + for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) { + cbody = (mailmime*)clist_content(cur); + if (cbody->mm_type==MAILMIME_MULTIPLE) { + RecPartP targetPart = new RecPart(); + targetPart->setType("multipart"); + countlist.append(current_count); + targetPart->setPositionlist(countlist); + target->addPart(targetPart); + } + traverseBody(target,message, cbody,countlist,current_rec+1,ccount); + if (cbody->mm_type==MAILMIME_MULTIPLE) { + countlist = recList; + } + ++ccount; + } + } + break; + case MAILMIME_MESSAGE: + { + QValueListcountlist = recList; + countlist.append(current_count); + /* the own header is always at recursion 0 - we don't need that */ + if (current_rec > 0) { + part->setPositionlist(countlist); + r = mailmessage_fetch_section(message,mime,&data,&len); + part->setSize(len); + part->setPositionlist(countlist); + b = gen_attachment_id(); + part->setIdentifier(b); + part->setType("message"); + part->setSubtype("rfc822"); + bodyCache[b]=new encodedString(data,len); + target->addPart(part); + } + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,countlist,current_rec+1); + } + } + break; + } +} + +RecBodyP Genericwrapper::parseMail( mailmessage * msg ) +{ + int err = MAILIMF_NO_ERROR; + mailmime_single_fields fields; + /* is bound to msg and will be freed there */ + mailmime * mime=0; + RecBodyP body = new RecBody(); + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + err = mailmessage_get_bodystructure(msg,&mime); + QValueListrecList; + traverseBody(body,msg,mime,recList); + return body; +} + +QString Genericwrapper::parseDateTime( mailimf_date_time *date ) +{ + char tmp[23]; + + // snprintf( tmp, 23, "%02i.%02i.%04i %02i:%02i:%02i %+05i", + // date->dt_day, date->dt_month, date->dt_year, date->dt_hour, date->dt_min, date->dt_sec, date->dt_zone ); + snprintf( tmp, 23, "%04i-%02i-%02i %02i:%02i:%02i %+05i", + date->dt_year,date->dt_month, date->dt_day, date->dt_hour, date->dt_min, date->dt_sec, date->dt_zone ); + + return QString( tmp ); +} + +QString Genericwrapper::parseAddressList( mailimf_address_list *list ) +{ + QString result( "" ); + + bool first = true; + if (list == 0) return result; + for ( clistiter *current = clist_begin( list->ad_list ); current != NULL; current = current->next ) { + mailimf_address *addr = (mailimf_address *) current->data; + + if ( !first ) { + result.append( "," ); + } else { + first = false; + } + + switch ( addr->ad_type ) { + case MAILIMF_ADDRESS_MAILBOX: + result.append( parseMailbox( addr->ad_data.ad_mailbox ) ); + break; + case MAILIMF_ADDRESS_GROUP: + result.append( parseGroup( addr->ad_data.ad_group ) ); + break; + default: + ; // odebug << "Generic: unkown mailimf address type" << oendl; + break; + } + } + + return result; +} + +QString Genericwrapper::parseGroup( mailimf_group *group ) +{ + QString result( "" ); + + result.append( group->grp_display_name ); + result.append( ": " ); + + if ( group->grp_mb_list != NULL ) { + result.append( parseMailboxList( group->grp_mb_list ) ); + } + + result.append( ";" ); + + return result; +} + +QString Genericwrapper::parseMailbox( mailimf_mailbox *box ) +{ + QString result( "" ); + + if ( box->mb_display_name == NULL ) { + result.append( box->mb_addr_spec ); + } else { + result.append( convert_String(box->mb_display_name).latin1() ); + result.append( " <" ); + result.append( box->mb_addr_spec ); + result.append( ">" ); + } + + return result; +} + +QString Genericwrapper::parseMailboxList( mailimf_mailbox_list *list ) +{ + QString result( "" ); + + bool first = true; + for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) { + mailimf_mailbox *box = (mailimf_mailbox *) current->data; + + if ( !first ) { + result.append( "," ); + } else { + first = false; + } + + result.append( parseMailbox( box ) ); + } + + return result; +} + +encodedString* Genericwrapper::fetchDecodedPart(const RecMailP&,const RecPartP&part) +{ + QMap::ConstIterator it = bodyCache.find(part->Identifier()); + if (it==bodyCache.end()) return new encodedString(); + encodedString*t = decode_String(it.data(),part->Encoding()); + return t; +} + +encodedString* Genericwrapper::fetchRawPart(const RecMailP&,const RecPartP&part) +{ + QMap::ConstIterator it = bodyCache.find(part->Identifier()); + if (it==bodyCache.end()) return new encodedString(); + encodedString*t = it.data(); + return t; +} + +QString Genericwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part) +{ + encodedString*t = fetchDecodedPart(mail,part); + QString text=t->Content(); + delete t; + return text; +} + +void Genericwrapper::cleanMimeCache() +{ + QMap::Iterator it = bodyCache.begin(); + for (;it!=bodyCache.end();++it) { + encodedString*t = it.data(); + //it.setValue(0); + if (t) delete t; + } + bodyCache.clear(); + ; // odebug << "Genericwrapper: cache cleaned" << oendl; +} + +QStringList Genericwrapper::parseInreplies(mailimf_in_reply_to * in_replies) +{ + QStringList res; + if (!in_replies || !in_replies->mid_list) return res; + clistiter * current = 0; + for ( current = clist_begin( in_replies->mid_list ); current != NULL; current = current->next ) { + QString h((char*)current->data); + while (h.length()>0 && h[0]=='<') { + h.remove(0,1); + } + while (h.length()>0 && h[h.length()-1]=='>') { + h.remove(h.length()-1,1); + } + if (h.length()>0) { + res.append(h); + } + } + return res; +} + +void Genericwrapper::parseList(QValueList > &target,mailsession*session,const QString&mailbox,bool mbox_as_to) +{ + int r; + mailmessage_list * env_list = 0; + r = mailsession_get_messages_list(session,&env_list); + if (r != MAIL_NO_ERROR) { + ; // odebug << "Error message list" << oendl; + return; + } + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + ; // odebug << "Error filling message list" << oendl; + if (env_list) { + mailmessage_list_free(env_list); + } + return; + } + mailimf_references * refs = 0; + mailimf_in_reply_to * in_replies = 0; + uint32_t i = 0; + for(; i < carray_count(env_list->msg_tab) ; ++i) { + mailmessage * msg; + QBitArray mFlags(7); + msg = (mailmessage*)carray_get(env_list->msg_tab, i); + if (msg->msg_fields == NULL) { + //; // odebug << "could not fetch envelope of message " << i << "" << oendl; + continue; + } + RecMailP mail = new RecMail(); + mail->setWrapper(this); + mail_flags * flag_result = 0; + r = mailmessage_get_flags(msg,&flag_result); + if (r == MAIL_ERROR_NOT_IMPLEMENTED) { + mFlags.setBit(FLAG_SEEN); + } + mailimf_single_fields single_fields; + mailimf_single_fields_init(&single_fields, msg->msg_fields); + mail->setMsgsize(msg->msg_size); + mail->setFlags(mFlags); + mail->setMbox(mailbox); + mail->setNumber(msg->msg_index); + if (single_fields.fld_subject) + mail->setSubject( convert_String(single_fields.fld_subject->sbj_value)); + if (single_fields.fld_from) + mail->setFrom(parseMailboxList(single_fields.fld_from->frm_mb_list)); + if (!mbox_as_to) { + if (single_fields.fld_to) + mail->setTo( parseAddressList( single_fields.fld_to->to_addr_list ) ); + } else { + mail->setTo(mailbox); + } + if (single_fields.fld_cc) + mail->setCC( parseAddressList( single_fields.fld_cc->cc_addr_list ) ); + if (single_fields.fld_bcc) + mail->setBcc( parseAddressList( single_fields.fld_bcc->bcc_addr_list ) ); + if (single_fields.fld_orig_date) + mail->setDate( parseDateTime( single_fields.fld_orig_date->dt_date_time ) ); + // crashes when accessing pop3 account? + if (single_fields.fld_message_id->mid_value) { + mail->setMsgid(QString(single_fields.fld_message_id->mid_value)); + ; // odebug << "Msgid == " << mail->Msgid().latin1() << "" << oendl; + } + + if (single_fields.fld_reply_to) { + QStringList t = parseAddressList(single_fields.fld_reply_to->rt_addr_list); + if (t.count()>0) { + mail->setReplyto(t[0]); + } + } +#if 0 + refs = single_fields.fld_references; + if (refs && refs->mid_list && clist_count(refs->mid_list)) { + char * text = (char*)refs->mid_list->first->data; + mail->setReplyto(QString(text)); + } +#endif + if (single_fields.fld_in_reply_to && single_fields.fld_in_reply_to->mid_list && + clist_count(single_fields.fld_in_reply_to->mid_list)) { + mail->setInreply(parseInreplies(single_fields.fld_in_reply_to)); + } + target.append(mail); + } + if (env_list) { + mailmessage_list_free(env_list); + } +} diff --git a/kmicromail/libmailwrapper/genericwrapper.h b/kmicromail/libmailwrapper/genericwrapper.h new file mode 100644 index 0000000..8be9212 --- a/dev/null +++ b/kmicromail/libmailwrapper/genericwrapper.h @@ -0,0 +1,67 @@ +#ifndef __GENERIC_WRAPPER_H +#define __GENERIC_WRAPPER_H + +#include "abstractmail.h" +#include +#include +#include + +class RecMail; +class RecBody; +class encodedString; +struct mailpop3; +struct mailmessage; +struct mailmime; +struct mailmime_mechanism; +struct mailimf_mailbox_list; +struct mailimf_mailbox; +struct mailimf_date_time; +struct mailimf_group; +struct mailimf_address_list; +struct mailsession; +struct mailstorage; +struct mailfolder; +struct mailimf_in_reply_to; + +/* this class hold just the funs shared between + * mbox and pop3 (later mh, too) mail access. + * it is not desigend to make a instance of it! + */ +class Genericwrapper : public AbstractMail +{ + Q_OBJECT +public: + Genericwrapper(); + virtual ~Genericwrapper(); + + virtual encodedString* fetchDecodedPart(const RecMailP&mail,const RecPartP&part); + virtual encodedString* fetchRawPart(const RecMailP&mail,const RecPartP&part); + virtual QString fetchTextPart(const RecMailP&mail,const RecPartP&part); + virtual void cleanMimeCache(); + virtual int deleteMbox(const Opie::Core::OSmartPointer&){return 1;} + virtual void logout(){}; + virtual void storeMessage(const char*msg,size_t length, const QString&folder){}; + +protected: + RecBodyP parseMail( mailmessage * msg ); + QString parseMailboxList( mailimf_mailbox_list *list ); + QString parseMailbox( mailimf_mailbox *box ); + QString parseGroup( mailimf_group *group ); + QString parseAddressList( mailimf_address_list *list ); + QString parseDateTime( mailimf_date_time *date ); + + void traverseBody(RecBodyP&target,mailmessage*message,mailmime*mime,QValueListrecList,unsigned int current_rek=0,int current_count=1); + static void fillSingleBody(RecPartP&target,mailmessage*message,mailmime*mime); + static void fillParameters(RecPartP&target,clist*parameters); + static QString getencoding(mailmime_mechanism*aEnc); + virtual void parseList(QValueList > &target,mailsession*session,const QString&mailbox,bool mbox_as_to=false); + QStringList parseInreplies(mailimf_in_reply_to * in_replies); + + QString msgTempName; + unsigned int last_msg_id; + QMap bodyCache; + mailstorage * m_storage; + mailfolder*m_folder; +}; + +#endif diff --git a/kmicromail/libmailwrapper/imapwrapper.cpp b/kmicromail/libmailwrapper/imapwrapper.cpp new file mode 100644 index 0000000..e0fb6f9 --- a/dev/null +++ b/kmicromail/libmailwrapper/imapwrapper.cpp @@ -0,0 +1,1182 @@ +#include +#include +#include +#include +#include "imapwrapper.h" +#include "mailtypes.h" +#include "logindialog.h" + +using namespace Opie::Core; +IMAPwrapper::IMAPwrapper( IMAPaccount *a ) + : AbstractMail() +{ + account = a; + m_imap = 0; + m_Lastmbox = ""; +} + +IMAPwrapper::~IMAPwrapper() +{ + logout(); +} + +/* to avoid to often select statements in loops etc. + we trust that we are logged in and connection is established!*/ +int IMAPwrapper::selectMbox(const QString&mbox) +{ + if (mbox == m_Lastmbox) { + return MAILIMAP_NO_ERROR; + } + int err = mailimap_select( m_imap, (char*)mbox.latin1()); + if ( err != MAILIMAP_NO_ERROR ) { + m_Lastmbox = ""; + return err; + } + m_Lastmbox = mbox; + return err; +} + +void IMAPwrapper::imap_progress( size_t current, size_t maximum ) +{ + qApp->processEvents(); + qDebug("imap progress %d of %d ",current,maximum ); +} + +bool IMAPwrapper::start_tls(bool force_tls) +{ + int err; + bool try_tls; + mailimap_capability_data * cap_data = 0; + + err = mailimap_capability(m_imap,&cap_data); + if (err != MAILIMAP_NO_ERROR) { + Global::statusMessage("error getting capabilities!"); + return false; + } + clistiter * cur; + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL;cur = clist_next(cur)) { + struct mailimap_capability * cap; + cap = (struct mailimap_capability *)clist_content(cur); + if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) { + if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { + try_tls = true; + break; + } + } + } + if (cap_data) { + mailimap_capability_data_free(cap_data); + } + if (try_tls) { + err = mailimap_starttls(m_imap); + if (err != MAILIMAP_NO_ERROR && force_tls) { + Global::statusMessage(tr("Server has no TLS support!")); + try_tls = false; + } else { + mailstream_low * low; + mailstream_low * new_low; + low = mailstream_get_low(m_imap->imap_stream); + if (!low) { + try_tls = false; + } else { + int fd = mailstream_low_get_fd(low); + if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) { + mailstream_low_free(low); + mailstream_set_low(m_imap->imap_stream, new_low); + } else { + try_tls = false; + } + } + } + } + return try_tls; +} + +void IMAPwrapper::login() +{ + const char *server, *user, *pass; + uint16_t port; + int err = MAILIMAP_NO_ERROR; + + if (account->getOffline()) return; + /* we are connected this moment */ + /* TODO: setup a timer holding the line or if connection closed - delete the value */ + if (m_imap) { + err = mailimap_noop(m_imap); + if (err!=MAILIMAP_NO_ERROR) { + logout(); + } else { + mailstream_flush(m_imap->imap_stream); + return; + } + } + server = account->getServer().latin1(); + port = account->getPort().toUInt(); + if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) { + LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true ); + login.show(); + if ( QDialog::Accepted == login.exec() ) { + // ok + user = login.getUser().latin1(); + pass = login.getPassword().latin1(); + } else { + // cancel + return; + } + } else { + user = account->getUser().latin1(); + pass = account->getPassword().latin1(); + } + + m_imap = mailimap_new( 20, &imap_progress ); + + /* connect */ + bool ssl = false; + bool try_tls = false; + bool force_tls = false; + + if ( account->ConnectionType() == 2 ) { + ssl = true; + } + if (account->ConnectionType()==1) { + force_tls = true; + } + + if ( ssl ) { + qDebug("using ssl "); + err = mailimap_ssl_connect( m_imap, (char*)server, port ); + } else { + err = mailimap_socket_connect( m_imap, (char*)server, port ); + } + + if ( err != MAILIMAP_NO_ERROR && + err != MAILIMAP_NO_ERROR_AUTHENTICATED && + err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) { + QString failure = ""; + if (err == MAILIMAP_ERROR_CONNECTION_REFUSED) { + failure="Connection refused"; + } else { + failure="Unknown failure"; + } + Global::statusMessage(tr("error connecting imap server: %1").arg(failure)); + mailimap_free( m_imap ); + m_imap = 0; + return; + } + + if (!ssl) { + try_tls = start_tls(force_tls); + } + + bool ok = true; + if (force_tls && !try_tls) { + Global::statusMessage(tr("Server has no TLS support!")); + ok = false; + } + + + /* login */ + + if (ok) { + err = mailimap_login_simple( m_imap, (char*)user, (char*)pass ); + if ( err != MAILIMAP_NO_ERROR ) { + Global::statusMessage(tr("error logging in imap server: %1").arg(m_imap->imap_response)); + ok = false; + } + } + if (!ok) { + err = mailimap_close( m_imap ); + mailimap_free( m_imap ); + m_imap = 0; + } +} + +void IMAPwrapper::logout() +{ + int err = MAILIMAP_NO_ERROR; + if (!m_imap) return; + err = mailimap_logout( m_imap ); + err = mailimap_close( m_imap ); + mailimap_free( m_imap ); + m_imap = 0; + m_Lastmbox = ""; +} + +void IMAPwrapper::listMessages(const QString&mailbox,QValueList > &target ) +{ + int err = MAILIMAP_NO_ERROR; + clist *result = 0; + clistcell *current; + mailimap_fetch_type *fetchType = 0; + mailimap_set *set = 0; + + login(); + if (!m_imap) { + return; + } + /* select mailbox READONLY for operations */ + err = selectMbox(mailbox); + if ( err != MAILIMAP_NO_ERROR ) { + return; + } + + int last = m_imap->imap_selection_info->sel_exists; + + if (last == 0) { + Global::statusMessage(tr("Mailbox has no mails")); + return; + } else { + } + + /* the range has to start at 1!!! not with 0!!!! */ + set = mailimap_set_new_interval( 1, last ); + fetchType = mailimap_fetch_type_new_fetch_att_list_empty(); + mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope()); + mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags()); + mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate()); + mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size()); + + err = mailimap_fetch( m_imap, set, fetchType, &result ); + mailimap_set_free( set ); + mailimap_fetch_type_free( fetchType ); + + QString date,subject,from; + + if ( err == MAILIMAP_NO_ERROR ) { + mailimap_msg_att * msg_att; + int i = 0; + for (current = clist_begin(result); current != 0; current=clist_next(current)) { + ++i; + msg_att = (mailimap_msg_att*)current->data; + RecMail*m = parse_list_result(msg_att); + if (m) { + m->setNumber(i); + m->setMbox(mailbox); + m->setWrapper(this); + target.append(m); + } + } + Global::statusMessage(tr("Mailbox has %1 mails").arg(target.count())); + } else { + Global::statusMessage(tr("Error fetching headers: %1").arg(m_imap->imap_response)); + } + if (result) mailimap_fetch_list_free(result); +} + +QValueList >* IMAPwrapper::listFolders() +{ + const char *path, *mask; + int err = MAILIMAP_NO_ERROR; + clist *result = 0; + clistcell *current = 0; + clistcell*cur_flag = 0; + mailimap_mbx_list_flags*bflags = 0; + + QValueList* folders = new QValueList(); + login(); + if (!m_imap) { + return folders; + } + +/* + * First we have to check for INBOX 'cause it sometimes it's not inside the path. + * We must not forget to filter them out in next loop! + * it seems like ugly code. and yes - it is ugly code. but the best way. + */ + QString temp; + mask = "INBOX" ; + mailimap_mailbox_list *list; + err = mailimap_list( m_imap, (char*)"", (char*)mask, &result ); + QString del; + bool selectable = true; + bool no_inferiors = false; + if ( err == MAILIMAP_NO_ERROR ) { + current = result->first; + for ( int i = result->count; i > 0; i-- ) { + list = (mailimap_mailbox_list *) current->data; + // it is better use the deep copy mechanism of qt itself + // instead of using strdup! + temp = list->mb_name; + del = list->mb_delimiter; + current = current->next; + if ( (bflags = list->mb_flag) ) { + selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& + bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); + for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) { + if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) { + no_inferiors = true; + } + } + } + folders->append( new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix())); + } + } else { + qDebug("error fetching folders: "); + + } + mailimap_list_result_free( result ); + +/* + * second stage - get the other then inbox folders + */ + mask = "*" ; + path = account->getPrefix().latin1(); + if (!path) path = ""; + err = mailimap_list( m_imap, (char*)path, (char*)mask, &result ); + if ( err == MAILIMAP_NO_ERROR ) { + current = result->first; + for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) { + no_inferiors = false; + list = (mailimap_mailbox_list *) current->data; + // it is better use the deep copy mechanism of qt itself + // instead of using strdup! + temp = list->mb_name; + if (temp.lower()=="inbox") + continue; + if (temp.lower()==account->getPrefix().lower()) + continue; + if ( (bflags = list->mb_flag) ) { + selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& + bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); + for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) { + if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) { + no_inferiors = true; + } + } + } + del = list->mb_delimiter; + folders->append(new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix())); + } + } else { + qDebug("error fetching folders "); + + } + if (result) mailimap_list_result_free( result ); + return folders; +} + +RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att) +{ + RecMail * m = 0; + mailimap_msg_att_item *item=0; + clistcell *current,*c,*cf; + mailimap_msg_att_dynamic*flist; + mailimap_flag_fetch*cflag; + int size; + QBitArray mFlags(7); + QStringList addresslist; + + if (!m_att) { + return m; + } + m = new RecMail(); + for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) { + current = c; + size = 0; + item = (mailimap_msg_att_item*)current->data; + if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) { + flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn; + if (!flist->att_list) { + continue; + } + cf = flist->att_list->first; + for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) { + cflag = (mailimap_flag_fetch*)cf->data; + if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) { + switch (cflag->fl_flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: /* \Answered flag */ + mFlags.setBit(FLAG_ANSWERED); + break; + case MAILIMAP_FLAG_FLAGGED: /* \Flagged flag */ + mFlags.setBit(FLAG_FLAGGED); + break; + case MAILIMAP_FLAG_DELETED: /* \Deleted flag */ + mFlags.setBit(FLAG_DELETED); + break; + case MAILIMAP_FLAG_SEEN: /* \Seen flag */ + mFlags.setBit(FLAG_SEEN); + break; + case MAILIMAP_FLAG_DRAFT: /* \Draft flag */ + mFlags.setBit(FLAG_DRAFT); + break; + case MAILIMAP_FLAG_KEYWORD: /* keyword flag */ + break; + case MAILIMAP_FLAG_EXTENSION: /* \extension flag */ + break; + default: + break; + } + } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) { + mFlags.setBit(FLAG_RECENT); + } + } + continue; + } + if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_ENVELOPE) { + mailimap_envelope * head = item->att_data.att_static->att_data.att_env; + m->setDate(head->env_date); + m->setSubject(convert_String((const char*)head->env_subject)); + //m->setSubject(head->env_subject); + if (head->env_from!=NULL) { + addresslist = address_list_to_stringlist(head->env_from->frm_list); + if (addresslist.count()) { + m->setFrom(addresslist.first()); + } + } + if (head->env_to!=NULL) { + addresslist = address_list_to_stringlist(head->env_to->to_list); + m->setTo(addresslist); + } + if (head->env_cc!=NULL) { + addresslist = address_list_to_stringlist(head->env_cc->cc_list); + m->setCC(addresslist); + } + if (head->env_bcc!=NULL) { + addresslist = address_list_to_stringlist(head->env_bcc->bcc_list); + m->setBcc(addresslist); + } + /* reply to address, eg. email. */ + if (head->env_reply_to!=NULL) { + addresslist = address_list_to_stringlist(head->env_reply_to->rt_list); + if (addresslist.count()) { + m->setReplyto(addresslist.first()); + } + } + if (head->env_in_reply_to!=NULL) { + QString h(head->env_in_reply_to); + while (h.length()>0 && h[0]=='<') { + h.remove(0,1); + } + while (h.length()>0 && h[h.length()-1]=='>') { + h.remove(h.length()-1,1); + } + if (h.length()>0) { + m->setInreply(QStringList(h)); + } + } + if (head->env_message_id) { + m->setMsgid(QString(head->env_message_id)); + } + } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_INTERNALDATE) { +#if 0 + mailimap_date_time*d = item->att_data.att_static->att_data.att_internal_date; + QDateTime da(QDate(d->dt_year,d->dt_month,d->dt_day),QTime(d->dt_hour,d->dt_min,d->dt_sec)); + //odebug << "" << d->dt_year << " " << d->dt_month << " " << d->dt_day << " - " << d->dt_hour << " " << d->dt_min << " " << d->dt_sec << "" << oendl; + //odebug << da.toString() << oendl; +#endif + } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) { + size = item->att_data.att_static->att_data.att_rfc822_size; + } + } + /* msg is already deleted */ + if (mFlags.testBit(FLAG_DELETED) && m) { + delete m; + m = 0; + } + if (m) { + m->setFlags(mFlags); + m->setMsgsize(size); + } + return m; +} + +RecBodyP IMAPwrapper::fetchBody(const RecMailP&mail) +{ + RecBodyP body = new RecBody(); + const char *mb; + int err = MAILIMAP_NO_ERROR; + clist *result = 0; + clistcell *current; + mailimap_fetch_att *fetchAtt = 0; + mailimap_fetch_type *fetchType = 0; + mailimap_set *set = 0; + mailimap_body*body_desc = 0; + + mb = mail->getMbox().latin1(); + + login(); + if (!m_imap) { + return body; + } + err = selectMbox(mail->getMbox()); + if ( err != MAILIMAP_NO_ERROR ) { + return body; + } + + /* the range has to start at 1!!! not with 0!!!! */ + set = mailimap_set_new_interval( mail->getNumber(),mail->getNumber() ); + fetchAtt = mailimap_fetch_att_new_bodystructure(); + fetchType = mailimap_fetch_type_new_fetch_att(fetchAtt); + err = mailimap_fetch( m_imap, set, fetchType, &result ); + mailimap_set_free( set ); + mailimap_fetch_type_free( fetchType ); + + if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { + mailimap_msg_att * msg_att; + msg_att = (mailimap_msg_att*)current->data; + mailimap_msg_att_item*item = (mailimap_msg_att_item*)msg_att->att_list->first->data; + QValueList path; + body_desc = item->att_data.att_static->att_data.att_body; + traverseBody(mail,body_desc,body,0,path); + } else { + //odebug << "error fetching body: " << m_imap->imap_response << "" << oendl; + } + if (result) mailimap_fetch_list_free(result); + return body; +} + +QStringList IMAPwrapper::address_list_to_stringlist(clist*list) +{ + QStringList l; + QString from; + bool named_from; + clistcell *current = NULL; + mailimap_address * current_address=NULL; + if (!list) { + return l; + } + unsigned int count = 0; + for (current=clist_begin(list);current!= NULL;current=clist_next(current)) { + from = ""; + named_from = false; + current_address=(mailimap_address*)current->data; + if (current_address->ad_personal_name){ + from+=convert_String((const char*)current_address->ad_personal_name); + from+=" "; + named_from = true; + } + if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { + from+="<"; + } + if (current_address->ad_mailbox_name) { + from+=QString(current_address->ad_mailbox_name); + from+="@"; + } + if (current_address->ad_host_name) { + from+=QString(current_address->ad_host_name); + } + if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) { + from+=">"; + } + l.append(QString(from)); + if (++count > 99) { + break; + } + } + return l; +} + +encodedString*IMAPwrapper::fetchRawPart(const RecMailP&mail,const QValueList&path,bool internal_call) +{ + encodedString*res=new encodedString; + int err; + mailimap_fetch_type *fetchType; + mailimap_set *set; + clistcell*current,*cur; + mailimap_section_part * section_part = 0; + mailimap_section_spec * section_spec = 0; + mailimap_section * section = 0; + mailimap_fetch_att * fetch_att = 0; + + login(); + if (!m_imap) { + return res; + } + if (!internal_call) { + err = selectMbox(mail->getMbox()); + if ( err != MAILIMAP_NO_ERROR ) { + return res; + } + } + set = mailimap_set_new_single(mail->getNumber()); + + clist*id_list = 0; + + /* if path == empty then its a request for the whole rfc822 mail and generates + a "fetch (body[])" statement on imap server */ + if (path.count()>0 ) { + id_list = clist_new(); + for (unsigned j=0; j < path.count();++j) { + uint32_t * p_id = (uint32_t *)malloc(sizeof(*p_id)); + *p_id = path[j]; + clist_append(id_list,p_id); + } + section_part = mailimap_section_part_new(id_list); + section_spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, NULL, section_part, NULL); + } + + section = mailimap_section_new(section_spec); + fetch_att = mailimap_fetch_att_new_body_section(section); + fetchType = mailimap_fetch_type_new_fetch_att(fetch_att); + + clist*result = 0; + + err = mailimap_fetch( m_imap, set, fetchType, &result ); + mailimap_set_free( set ); + mailimap_fetch_type_free( fetchType ); + + if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) { + mailimap_msg_att * msg_att; + msg_att = (mailimap_msg_att*)current->data; + mailimap_msg_att_item*msg_att_item; + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { + msg_att_item = (mailimap_msg_att_item*)clist_content(cur); + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + if (msg_att_item->att_data.att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) { + char*text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + /* detach - we take over the content */ + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = 0L; + res->setContent(text,msg_att_item->att_data.att_static->att_data.att_body_section->sec_length); + } + } + } + } else { + ;//odebug << "error fetching text: " << m_imap->imap_response << "" << oendl; + } + if (result) mailimap_fetch_list_free(result); + return res; +} + +/* current_recursion is for recursive calls. + current_count means the position inside the internal loop! */ +void IMAPwrapper::traverseBody(const RecMailP&mail,mailimap_body*body,RecBodyP&target_body, + int current_recursion,QValueListrecList,int current_count) +{ + if (!body || current_recursion>=10) { + return; + } + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + { + QValueListcountlist = recList; + countlist.append(current_count); + RecPartP currentPart = new RecPart(); + mailimap_body_type_1part*part1 = body->bd_data.bd_body_1part; + QString id(""); + currentPart->setPositionlist(countlist); + for (unsigned int j = 0; j < countlist.count();++j) { + id+=(j>0?" ":""); + id+=QString("%1").arg(countlist[j]); + } + //odebug << "ID = " << id.latin1() << "" << oendl; + currentPart->setIdentifier(id); + fillSinglePart(currentPart,part1); + /* important: Check for is NULL 'cause a body can be empty! + And we put it only into the mail if it is the FIRST part */ + if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_TEXT && target_body->Bodytext().isNull() && countlist[0]==1) { + QString body_text = fetchTextPart(mail,countlist,true,currentPart->Encoding()); + target_body->setDescription(currentPart); + target_body->setBodytext(body_text); + if (countlist.count()>1) { + target_body->addPart(currentPart); + } + } else { + target_body->addPart(currentPart); + } + if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_MSG) { + traverseBody(mail,part1->bd_data.bd_type_msg->bd_body,target_body,current_recursion+1,countlist); + } + } + break; + case MAILIMAP_BODY_MPART: + { + QValueListcountlist = recList; + clistcell*current=0; + mailimap_body*current_body=0; + unsigned int ccount = 1; + mailimap_body_type_mpart*mailDescription = body->bd_data.bd_body_mpart; + for (current=clist_begin(mailDescription->bd_list);current!=0;current=clist_next(current)) { + current_body = (mailimap_body*)current->data; + if (current_body->bd_type==MAILIMAP_BODY_MPART) { + RecPartP targetPart = new RecPart(); + targetPart->setType("multipart"); + fillMultiPart(targetPart,mailDescription); + countlist.append(current_count); + targetPart->setPositionlist(countlist); + target_body->addPart(targetPart); + QString id(""); + for (unsigned int j = 0; j < countlist.count();++j) { + id+=(j>0?" ":""); + id+=QString("%1").arg(countlist[j]); + } + // odebug << "ID(mpart) = " << id.latin1() << "" << oendl; + } + traverseBody(mail,current_body,target_body,current_recursion+1,countlist,ccount); + if (current_body->bd_type==MAILIMAP_BODY_MPART) { + countlist = recList; + } + ++ccount; + } + } + break; + default: + break; + } +} + +void IMAPwrapper::fillSinglePart(RecPartP&target_part,mailimap_body_type_1part*Description) +{ + if (!Description) { + return; + } + switch (Description->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_TEXT: + target_part->setType("text"); + fillSingleTextPart(target_part,Description->bd_data.bd_type_text); + break; + case MAILIMAP_BODY_TYPE_1PART_BASIC: + fillSingleBasicPart(target_part,Description->bd_data.bd_type_basic); + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + target_part->setType("message"); + fillSingleMsgPart(target_part,Description->bd_data.bd_type_msg); + break; + default: + break; + } +} + +void IMAPwrapper::fillSingleTextPart(RecPartP&target_part,mailimap_body_type_text*which) +{ + if (!which) { + return; + } + QString sub; + sub = which->bd_media_text; + //odebug << "Type= text/" << which->bd_media_text << "" << oendl; + target_part->setSubtype(sub.lower()); + target_part->setLines(which->bd_lines); + fillBodyFields(target_part,which->bd_fields); +} + +void IMAPwrapper::fillSingleMsgPart(RecPartP&target_part,mailimap_body_type_msg*which) +{ + if (!which) { + return; + } + target_part->setSubtype("rfc822"); + //odebug << "Message part" << oendl; + /* we set this type to text/plain */ + target_part->setLines(which->bd_lines); + fillBodyFields(target_part,which->bd_fields); +} + +void IMAPwrapper::fillMultiPart(RecPartP&target_part,mailimap_body_type_mpart*which) +{ + if (!which) return; + QString sub = which->bd_media_subtype; + target_part->setSubtype(sub.lower()); + if (which->bd_ext_mpart && which->bd_ext_mpart->bd_parameter && which->bd_ext_mpart->bd_parameter->pa_list) { + clistcell*cur = 0; + mailimap_single_body_fld_param*param=0; + for (cur = clist_begin(which->bd_ext_mpart->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) { + param = (mailimap_single_body_fld_param*)cur->data; + if (param) { + target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); + } + } + } +} + +void IMAPwrapper::fillSingleBasicPart(RecPartP&target_part,mailimap_body_type_basic*which) +{ + if (!which) { + return; + } + QString type,sub; + switch (which->bd_media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + type = "application"; + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + type = "audio"; + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + type = "image"; + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + type = "message"; + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + type = "video"; + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + default: + if (which->bd_media_basic->med_basic_type) { + type = which->bd_media_basic->med_basic_type; + } else { + type = ""; + } + break; + } + if (which->bd_media_basic->med_subtype) { + sub = which->bd_media_basic->med_subtype; + } else { + sub = ""; + } + // odebug << "Type = " << type.latin1() << "/" << sub.latin1() << "" << oendl; + target_part->setType(type.lower()); + target_part->setSubtype(sub.lower()); + fillBodyFields(target_part,which->bd_fields); +} + +void IMAPwrapper::fillBodyFields(RecPartP&target_part,mailimap_body_fields*which) +{ + if (!which) return; + if (which->bd_parameter && which->bd_parameter->pa_list && which->bd_parameter->pa_list->count>0) { + clistcell*cur; + mailimap_single_body_fld_param*param=0; + for (cur = clist_begin(which->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) { + param = (mailimap_single_body_fld_param*)cur->data; + if (param) { + target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); + } + } + } + mailimap_body_fld_enc*enc = which->bd_encoding; + QString encoding(""); + switch (enc->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + encoding = "7bit"; + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + encoding = "8bit"; + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + encoding="binary"; + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + encoding="base64"; + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + encoding="quoted-printable"; + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + default: + if (enc->enc_value) { + char*t=enc->enc_value; + encoding=QString(enc->enc_value); + enc->enc_value=0L; + free(t); + } + } + if (which->bd_description) { + target_part->setDescription(QString(which->bd_description)); + } + target_part->setEncoding(encoding); + target_part->setSize(which->bd_size); +} + +void IMAPwrapper::deleteMail(const RecMailP&mail) +{ + mailimap_flag_list*flist; + mailimap_set *set; + mailimap_store_att_flags * store_flags; + int err; + login(); + if (!m_imap) { + return; + } + err = selectMbox(mail->getMbox()); + if ( err != MAILIMAP_NO_ERROR ) { + return; + } + flist = mailimap_flag_list_new_empty(); + mailimap_flag_list_add(flist,mailimap_flag_new_deleted()); + store_flags = mailimap_store_att_flags_new_set_flags(flist); + set = mailimap_set_new_single(mail->getNumber()); + err = mailimap_store(m_imap,set,store_flags); + mailimap_set_free( set ); + mailimap_store_att_flags_free(store_flags); + + if (err != MAILIMAP_NO_ERROR) { + // odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl; + return; + } + // odebug << "deleting mail: " << m_imap->imap_response << "" << oendl; + /* should we realy do that at this moment? */ + err = mailimap_expunge(m_imap); + if (err != MAILIMAP_NO_ERROR) { + // odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl; + } + // odebug << "Delete successfull " << m_imap->imap_response << "" << oendl; +} + +void IMAPwrapper::answeredMail(const RecMailP&mail) +{ + mailimap_flag_list*flist; + mailimap_set *set; + mailimap_store_att_flags * store_flags; + int err; + login(); + if (!m_imap) { + return; + } + err = selectMbox(mail->getMbox()); + if ( err != MAILIMAP_NO_ERROR ) { + return; + } + flist = mailimap_flag_list_new_empty(); + mailimap_flag_list_add(flist,mailimap_flag_new_answered()); + store_flags = mailimap_store_att_flags_new_add_flags(flist); + set = mailimap_set_new_single(mail->getNumber()); + err = mailimap_store(m_imap,set,store_flags); + mailimap_set_free( set ); + mailimap_store_att_flags_free(store_flags); + + if (err != MAILIMAP_NO_ERROR) { + // odebug << "error marking mail: " << m_imap->imap_response << "" << oendl; + return; + } +} + +QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const QValueList&path,bool internal_call,const QString&enc) +{ + QString body(""); + encodedString*res = fetchRawPart(mail,path,internal_call); + encodedString*r = decode_String(res,enc); + delete res; + if (r) { + if (r->Length()>0) { + body = r->Content(); + } + delete r; + } + return body; +} + +QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part) +{ + return fetchTextPart(mail,part->Positionlist(),false,part->Encoding()); +} + +encodedString* IMAPwrapper::fetchDecodedPart(const RecMailP&mail,const RecPartP&part) +{ + encodedString*res = fetchRawPart(mail,part->Positionlist(),false); + encodedString*r = decode_String(res,part->Encoding()); + delete res; + return r; +} + +encodedString* IMAPwrapper::fetchRawPart(const RecMailP&mail,const RecPartP&part) +{ + return fetchRawPart(mail,part->Positionlist(),false); +} + +int IMAPwrapper::deleteAllMail(const FolderP&folder) +{ + login(); + if (!m_imap) { + return 0; + } + mailimap_flag_list*flist; + mailimap_set *set; + mailimap_store_att_flags * store_flags; + int err = selectMbox(folder->getName()); + if ( err != MAILIMAP_NO_ERROR ) { + return 0; + } + + int last = m_imap->imap_selection_info->sel_exists; + if (last == 0) { + Global::statusMessage(tr("Mailbox has no mails!")); + return 0; + } + flist = mailimap_flag_list_new_empty(); + mailimap_flag_list_add(flist,mailimap_flag_new_deleted()); + store_flags = mailimap_store_att_flags_new_set_flags(flist); + set = mailimap_set_new_interval( 1, last ); + err = mailimap_store(m_imap,set,store_flags); + mailimap_set_free( set ); + mailimap_store_att_flags_free(store_flags); + if (err != MAILIMAP_NO_ERROR) { + Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response)); + return 0; + } + // odebug << "deleting mail: " << m_imap->imap_response << "" << oendl; + /* should we realy do that at this moment? */ + err = mailimap_expunge(m_imap); + if (err != MAILIMAP_NO_ERROR) { + Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response)); + return 0; + } + // odebug << "Delete successfull " << m_imap->imap_response << "" << oendl; + return 1; +} + +int IMAPwrapper::createMbox(const QString&folder,const FolderP&parentfolder,const QString& delemiter,bool getsubfolder) +{ + if (folder.length()==0) return 0; + login(); + if (!m_imap) {return 0;} + QString pre = account->getPrefix(); + if (delemiter.length()>0 && pre.findRev(delemiter)!=pre.length()-1) { + pre+=delemiter; + } + if (parentfolder) { + pre += parentfolder->getDisplayName()+delemiter; + } + pre+=folder; + if (getsubfolder) { + if (delemiter.length()>0) { + pre+=delemiter; + } else { + Global::statusMessage(tr("Cannot create folder %1 for holding subfolders").arg(pre)); + return 0; + } + } + // odebug << "Creating " << pre.latin1() << "" << oendl; + int res = mailimap_create(m_imap,pre.latin1()); + if (res != MAILIMAP_NO_ERROR) { + Global::statusMessage(tr("%1").arg(m_imap->imap_response)); + return 0; + } + return 1; +} + +int IMAPwrapper::deleteMbox(const FolderP&folder) +{ + if (!folder) return 0; + login(); + if (!m_imap) {return 0;} + int res = mailimap_delete(m_imap,folder->getName()); + if (res != MAILIMAP_NO_ERROR) { + Global::statusMessage(tr("%1").arg(m_imap->imap_response)); + return 0; + } + return 1; +} + +void IMAPwrapper::statusFolder(folderStat&target_stat,const QString & mailbox) +{ + mailimap_status_att_list * att_list =0; + mailimap_mailbox_data_status * status=0; + clistiter * cur = 0; + int r = 0; + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + login(); + if (!m_imap) { + return; + } + att_list = mailimap_status_att_list_new_empty(); + if (!att_list) return; + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES); + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT); + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN); + r = mailimap_status(m_imap, mailbox.latin1(), att_list, &status); + if (r==MAILIMAP_NO_ERROR&&status->st_info_list!=0) { + for (cur = clist_begin(status->st_info_list); + cur != NULL ; cur = clist_next(cur)) { + mailimap_status_info * status_info; + status_info = (mailimap_status_info *)clist_content(cur); + switch (status_info->st_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + target_stat.message_count = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + target_stat.message_recent = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + target_stat.message_unseen = status_info->st_value; + break; + } + } + } else { + // odebug << "Error retrieving status" << oendl; + } + if (status) mailimap_mailbox_data_status_free(status); + if (att_list) mailimap_status_att_list_free(att_list); +} + +void IMAPwrapper::storeMessage(const char*msg,size_t length, const QString&folder) +{ + login(); + if (!m_imap) return; + if (!msg) return; + int r = mailimap_append(m_imap,(char*)folder.latin1(),0,0,msg,length); + if (r != MAILIMAP_NO_ERROR) { + Global::statusMessage("Error storing mail!"); + } +} + +MAILLIB::ATYPE IMAPwrapper::getType()const +{ + return account->getType(); +} + +const QString&IMAPwrapper::getName()const +{ + // odebug << "Get name: " << account->getAccountName().latin1() << "" << oendl; + return account->getAccountName(); +} + +encodedString* IMAPwrapper::fetchRawBody(const RecMailP&mail) +{ + // dummy + QValueList path; + return fetchRawPart(mail,path,false); +} + +void IMAPwrapper::mvcpAllMails(const FolderP&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + if (targetWrapper != this) { + AbstractMail::mvcpAllMails(fromFolder,targetFolder,targetWrapper,moveit); + // odebug << "Using generic" << oendl; + return; + } + mailimap_set *set = 0; + login(); + if (!m_imap) { + return; + } + int err = selectMbox(fromFolder->getName()); + if ( err != MAILIMAP_NO_ERROR ) { + return; + } + int last = m_imap->imap_selection_info->sel_exists; + set = mailimap_set_new_interval( 1, last ); + err = mailimap_copy(m_imap,set,targetFolder.latin1()); + mailimap_set_free( set ); + if ( err != MAILIMAP_NO_ERROR ) { + QString error_msg = tr("error copy mails: %1").arg(m_imap->imap_response); + Global::statusMessage(error_msg); + // odebug << error_msg << oendl; + return; + } + if (moveit) { + deleteAllMail(fromFolder); + } +} + +void IMAPwrapper::mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + if (targetWrapper != this) { + // odebug << "Using generic" << oendl; + AbstractMail::mvcpMail(mail,targetFolder,targetWrapper,moveit); + return; + } + mailimap_set *set = 0; + login(); + if (!m_imap) { + return; + } + int err = selectMbox(mail->getMbox()); + if ( err != MAILIMAP_NO_ERROR ) { + return; + } + set = mailimap_set_new_single(mail->getNumber()); + err = mailimap_copy(m_imap,set,targetFolder.latin1()); + mailimap_set_free( set ); + if ( err != MAILIMAP_NO_ERROR ) { + QString error_msg = tr("error copy mail: %1").arg(m_imap->imap_response); + Global::statusMessage(error_msg); + // odebug << error_msg << oendl; + return; + } + if (moveit) { + deleteMail(mail); + } +} diff --git a/kmicromail/libmailwrapper/imapwrapper.h b/kmicromail/libmailwrapper/imapwrapper.h new file mode 100644 index 0000000..e56605a --- a/dev/null +++ b/kmicromail/libmailwrapper/imapwrapper.h @@ -0,0 +1,80 @@ +#ifndef __IMAPWRAPPER +#define __IMAPWRAPPER + +#include +#include "mailwrapper.h" +#include "abstractmail.h" +#include + +struct mailimap; +struct mailimap_body; +struct mailimap_body_type_1part; +struct mailimap_body_type_text; +struct mailimap_body_type_basic; +struct mailimap_body_type_msg; +struct mailimap_body_type_mpart; +struct mailimap_body_fields; +struct mailimap_msg_att; +class encodedString; + +class IMAPwrapper : public AbstractMail +{ + Q_OBJECT +public: + IMAPwrapper( IMAPaccount *a ); + virtual ~IMAPwrapper(); + virtual QValueList >* listFolders(); + virtual void listMessages(const QString & mailbox,QValueList >&target ); + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + + virtual void deleteMail(const RecMailP&mail); + virtual void answeredMail(const RecMailP&mail); + virtual int deleteAllMail(const Opie::Core::OSmartPointer&folder); + virtual void storeMessage(const char*msg,size_t length, const QString&folder); + virtual void mvcpAllMails(const Opie::Core::OSmartPointer&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + virtual void mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + + virtual RecBodyP fetchBody(const RecMailP&mail); + virtual QString fetchTextPart(const RecMailP&mail,const RecPartP&part); + virtual encodedString* fetchDecodedPart(const RecMailP&mail,const RecPartP&part); + virtual encodedString* fetchRawPart(const RecMailP&mail,const RecPartP&part); + virtual encodedString* fetchRawBody(const RecMailP&mail); + + virtual int createMbox(const QString&,const Opie::Core::OSmartPointer&parentfolder=0, + const QString& delemiter="/",bool getsubfolder=false); + virtual int deleteMbox(const Opie::Core::OSmartPointer&folder); + + static void imap_progress( size_t current, size_t maximum ); + + virtual void logout(); + virtual MAILLIB::ATYPE getType()const; + virtual const QString&getName()const; + +protected: + RecMail*parse_list_result(mailimap_msg_att*); + void login(); + bool start_tls(bool force=true); + + virtual QString fetchTextPart(const RecMailP&mail,const QValueList&path,bool internal_call=false,const QString&enc=""); + virtual encodedString*fetchRawPart(const RecMailP&mail,const QValueList&path,bool internal_call); + int selectMbox(const QString&mbox); + + void fillSinglePart(RecPartP&target_part,mailimap_body_type_1part*Description); + void fillSingleTextPart(RecPartP&target_part,mailimap_body_type_text*which); + void fillSingleBasicPart(RecPartP&target_part,mailimap_body_type_basic*which); + void fillSingleMsgPart(RecPartP&target_part,mailimap_body_type_msg*which); + void fillMultiPart(RecPartP&target_part,mailimap_body_type_mpart*which); + void traverseBody(const RecMailP&mail,mailimap_body*body,RecBodyP&target_body,int current_recursion,QValueListrecList,int current_count=1); + + /* just helpers */ + static void fillBodyFields(RecPartP&target_part,mailimap_body_fields*which); + static QStringList address_list_to_stringlist(clist*list); + + + IMAPaccount *account; + mailimap *m_imap; + QString m_Lastmbox; +}; + +#endif diff --git a/kmicromail/libmailwrapper/libmailwrapper.control b/kmicromail/libmailwrapper/libmailwrapper.control new file mode 100644 index 0000000..ec55bb3 --- a/dev/null +++ b/kmicromail/libmailwrapper/libmailwrapper.control @@ -0,0 +1,10 @@ +Package: libmailwrapper +Files: lib/libmailwrapper.so* +Priority: optional +Section: libs +Maintainer: Rajko Albrecht , Juergen Graf , Maximilian Reiß +Architecture: arm +Version: 0.6-$SUB_VERSION +Depends: task-opie-minimal, libopiecore2, libopieui2, libetpan (>= 0.33pre) +Description: wrapper lib needed by Opie's mailer +License: LGPL diff --git a/kmicromail/libmailwrapper/libmailwrapperE.pro b/kmicromail/libmailwrapper/libmailwrapperE.pro new file mode 100644 index 0000000..a53b022 --- a/dev/null +++ b/kmicromail/libmailwrapper/libmailwrapperE.pro @@ -0,0 +1,49 @@ +TEMPLATE = lib +CONFIG += qt warn_on + +HEADERS = mailwrapper.h \ + imapwrapper.h \ + mailtypes.h \ + pop3wrapper.h \ + abstractmail.h \ + smtpwrapper.h \ + genericwrapper.h \ + mboxwrapper.h \ + settings.h \ + logindialog.h \ + sendmailprogress.h \ + statusmail.h \ + mhwrapper.h \ + nntpwrapper.h \ + generatemail.h \ + storemail.h + +SOURCES = imapwrapper.cpp \ + mailwrapper.cpp \ + mailtypes.cpp \ + pop3wrapper.cpp \ + abstractmail.cpp \ + smtpwrapper.cpp \ + genericwrapper.cpp \ + mboxwrapper.cpp \ + settings.cpp \ + logindialog.cpp \ + sendmailprogress.cpp \ + statusmail.cpp \ + mhwrapper.cpp \ + nntpwrapper.cpp \ + generatemail.cpp \ + storemail.cpp + +INTERFACES = logindialogui.ui \ + sendmailprogressui.ui + +INCLUDEPATH += ../../microkde ../../microkde/kdecore ../libetpan/include $(QPEDIR)/include +LIBS += -lssl -lcrypto + +#-lqpe -letpan + +DESTDIR = $(QPEDIR)/lib +OBJECTS_DIR = obj/$(PLATFORM) +MOC_DIR = moc/$(PLATFORM) +TARGET = kmicromailwrapper diff --git a/kmicromail/libmailwrapper/logindialog.cpp b/kmicromail/libmailwrapper/logindialog.cpp new file mode 100644 index 0000000..31b75d0 --- a/dev/null +++ b/kmicromail/libmailwrapper/logindialog.cpp @@ -0,0 +1,33 @@ +#include + +#include "logindialog.h" + + + +//using namespace Opie::Core; + +LoginDialog::LoginDialog(const QString&user,const QString&pass, QWidget *parent, const char *name, bool modal, WFlags flags ) + : LoginDialogUI( parent, name, modal, flags ) +{ + userLine->setText( (user.isEmpty()?QString(""):user) ); + passLine->setText( (pass.isEmpty()?QString(""):pass) ); + _user = user; + _pass = pass; + + if ( user.isEmpty() ) { + userLine->setFocus(); + } else { + passLine->setFocus(); + } +} + +void LoginDialog::accept() +{ + //_user.replace( 0, _user.length(), userLine->text() ); + //_pass.replace( 0, _pass.length(), passLine->text() ); + _user = userLine->text(); + _pass = passLine->text(); + + //odebug << "User im accept: |" << _user.latin1() << "|" << oendl; + QDialog::accept(); +} diff --git a/kmicromail/libmailwrapper/logindialog.h b/kmicromail/libmailwrapper/logindialog.h new file mode 100644 index 0000000..f406f2c --- a/dev/null +++ b/kmicromail/libmailwrapper/logindialog.h @@ -0,0 +1,23 @@ +#ifndef LOGINDIALOG_H +#define LOGINDIALOG_H + +#include "logindialogui.h" + +class LoginDialog : public LoginDialogUI +{ + Q_OBJECT + +public: + LoginDialog(const QString&user,const QString&pass, QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags flags = 0 ); + QString getUser() { return _user; } + QString getPassword() { return _pass; } + +protected slots: + void accept(); + +private: + QString _user, _pass; + +}; + +#endif diff --git a/kmicromail/libmailwrapper/logindialogui.ui b/kmicromail/libmailwrapper/logindialogui.ui new file mode 100644 index 0000000..565f777 --- a/dev/null +++ b/kmicromail/libmailwrapper/logindialogui.ui @@ -0,0 +1,83 @@ + +LoginDialogUI + + QDialog + + name + LoginDialogUI + + + geometry + + 0 + 0 + 196 + 110 + + + + caption + Login + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 3 + + + QLabel + + name + userLabel + + + text + User + + + + QLineEdit + + name + userLine + + + + QLineEdit + + name + passLine + + + echoMode + Password + + + + QLabel + + name + passLabel + + + text + Password + + + + + + userLine + passLine + + diff --git a/kmicromail/libmailwrapper/maildefines.h b/kmicromail/libmailwrapper/maildefines.h new file mode 100644 index 0000000..431f9ea --- a/dev/null +++ b/kmicromail/libmailwrapper/maildefines.h @@ -0,0 +1,16 @@ +#ifndef __MAILDEFINES_H +#define __MAILDEFINES_H + +namespace MAILLIB { + enum ATYPE { + A_UNDEFINED, + A_IMAP, + A_POP3, + A_SMTP, + A_MH, + A_MBOX, + A_NNTP, + }; +} + +#endif diff --git a/kmicromail/libmailwrapper/mailtypes.cpp b/kmicromail/libmailwrapper/mailtypes.cpp new file mode 100644 index 0000000..d43bdc6 --- a/dev/null +++ b/kmicromail/libmailwrapper/mailtypes.cpp @@ -0,0 +1,399 @@ +#include "mailtypes.h" + +//#include + +#include + +using namespace Opie::Core; +RecMail::RecMail() + :Opie::Core::ORefCount(),subject(""),date(""),from(""),mbox(""),msg_id(""),msg_number(0),msg_size(0),msg_flags(7) +{ + init(); +} + +RecMail::RecMail(const RecMail&old) + :Opie::Core::ORefCount(),subject(""),date(""),from(""),mbox(""),msg_id(""),msg_number(0),msg_flags(7) +{ + init(); + copy_old(old); + // odebug << "Copy constructor RecMail" << oendl; +} + +RecMail::~RecMail() +{ + wrapper = 0; +} + +void RecMail::copy_old(const RecMail&old) +{ + subject = old.subject; + date = old.date; + mbox = old.mbox; + msg_id = old.msg_id; + msg_size = old.msg_size; + msg_number = old.msg_number; + from = old.from; + msg_flags = old.msg_flags; + to = old.to; + cc = old.cc; + bcc = old.bcc; + wrapper = old.wrapper; + in_reply_to = old.in_reply_to; + references = old.references; + replyto = old.replyto; +} + +void RecMail::init() +{ + to.clear(); + cc.clear(); + bcc.clear(); + in_reply_to.clear(); + references.clear(); + wrapper = 0; +} + +void RecMail::setWrapper(AbstractMail*awrapper) +{ + wrapper = awrapper; +} + +AbstractMail* RecMail::Wrapper() +{ + return wrapper; +} + +void RecMail::setTo(const QStringList&list) +{ + to = list; +} + +const QStringList&RecMail::To()const +{ + return to; +} + +void RecMail::setCC(const QStringList&list) +{ + cc = list; +} + +const QStringList&RecMail::CC()const +{ + return cc; +} + +void RecMail::setBcc(const QStringList&list) +{ + bcc = list; +} + +const QStringList& RecMail::Bcc()const +{ + return bcc; +} + +void RecMail::setInreply(const QStringList&list) +{ + in_reply_to = list; +} + +const QStringList& RecMail::Inreply()const +{ + return in_reply_to; +} + +void RecMail::setReferences(const QStringList&list) +{ + references = list; +} + +const QStringList& RecMail::References()const +{ + return references; +} + +RecPart::RecPart() + : Opie::Core::ORefCount(), + m_type(""),m_subtype(""),m_identifier(""),m_encoding(""),m_description(""),m_lines(0),m_size(0) +{ + m_Parameters.clear(); + m_poslist.clear(); +} + +RecPart::RecPart(const RecPart&old) + : Opie::Core::ORefCount(), + m_type(""),m_subtype(""),m_identifier(""),m_encoding(""),m_description(""),m_lines(0),m_size(0) +{ + m_type = old.m_type; + m_subtype = old.m_subtype; + m_identifier = old.m_identifier; + m_encoding = old.m_encoding; + m_description = old.m_description; + m_lines = old.m_lines; + m_size = old.m_size; + m_Parameters = old.m_Parameters; + m_poslist = old.m_poslist; + // odebug << "RecPart copy constructor" << oendl; +} + +RecPart::~RecPart() +{ +} + +void RecPart::setSize(unsigned int size) +{ + m_size = size; +} + +const unsigned int RecPart::Size()const +{ + return m_size; +} + +void RecPart::setLines(unsigned int lines) +{ + m_lines = lines; +} + +const unsigned int RecPart::Lines()const +{ + return m_lines; +} + +const QString& RecPart::Type()const +{ + return m_type; +} + +void RecPart::setType(const QString&type) +{ + m_type = type; +} + +const QString& RecPart::Subtype()const +{ + return m_subtype; +} + +void RecPart::setSubtype(const QString&subtype) +{ + m_subtype = subtype; +} + +const QString& RecPart::Identifier()const +{ + return m_identifier; +} + +void RecPart::setIdentifier(const QString&identifier) +{ + m_identifier = identifier; +} + +const QString& RecPart::Encoding()const +{ + return m_encoding; +} + +void RecPart::setEncoding(const QString&encoding) +{ + m_encoding = encoding; +} + +const QString& RecPart::Description()const +{ + return m_description; +} + +void RecPart::setDescription(const QString&desc) +{ + m_description = desc; +} + +void RecPart::setParameters(const part_plist_t&list) +{ + m_Parameters = list; +} + +const part_plist_t& RecPart::Parameters()const +{ + return m_Parameters; +} + +void RecPart::addParameter(const QString&key,const QString&value) +{ + m_Parameters[key]=value; +} + +const QString RecPart::searchParamter(const QString&key)const +{ + QString value(""); + part_plist_t::ConstIterator it = m_Parameters.find(key); + if (it != m_Parameters.end()) { + value = it.data(); + } + return value; +} + +void RecPart::setPositionlist(const QValueList&poslist) +{ + m_poslist = poslist; +} + +const QValueList& RecPart::Positionlist()const +{ + return m_poslist; +} + +RecBody::RecBody() + : Opie::Core::ORefCount(),m_BodyText(),m_description(new RecPart()) +{ + m_PartsList.clear(); +} + +RecBody::RecBody(const RecBody&old) + :Opie::Core::ORefCount(),m_BodyText(),m_PartsList(),m_description(new RecPart()) +{ + m_BodyText = old.m_BodyText; + m_PartsList = old.m_PartsList; + m_description = old.m_description; + // odebug << "Recbody copy constructor" << oendl; +} + +RecBody::~RecBody() +{ +} + +void RecBody::setBodytext(const QString&bodyText) +{ + m_BodyText = bodyText; +} + +const QString& RecBody::Bodytext()const +{ + return m_BodyText; +} + +void RecBody::setParts(const QValueList&parts) +{ + m_PartsList.clear(); + m_PartsList = parts; +} + +const QValueList& RecBody::Parts()const +{ + return m_PartsList; +} + +void RecBody::addPart(const RecPartP& part) +{ + m_PartsList.append(part); +} + +void RecBody::setDescription(const RecPartP&des) +{ + m_description = des; +} + +const RecPartP& RecBody::Description()const +{ + return m_description; +} + +/* handling encoded content */ +encodedString::encodedString() +{ + init(); +} + +encodedString::encodedString(const char*nContent,unsigned int nSize) +{ + init(); + setContent(nContent,nSize); +} + +encodedString::encodedString(char*nContent,unsigned int nSize) +{ + init(); + setContent(nContent,nSize); +} + +encodedString::encodedString(const encodedString&old) +{ + init(); + copy_old(old); + // odebug << "encodedeString: copy constructor!" << oendl; +} + +encodedString& encodedString::operator=(const encodedString&old) +{ + init(); + copy_old(old); + // odebug << "encodedString: assign operator!" << oendl; + return *this; +} + +encodedString::~encodedString() +{ + clean(); +} + +void encodedString::init() +{ + content = 0; + size = 0; +} + +void encodedString::clean() +{ + if (content) { + free(content); + } + content = 0; + size = 0; +} + +void encodedString::copy_old(const encodedString&old) +{ + clean(); + if (old.size>0 && old.content) { + content = (char*)malloc(old.size*sizeof(char)); + memcpy(content,old.content,size); + size = old.size; + } +} + +const char*encodedString::Content()const +{ + return content; +} + +const int encodedString::Length()const +{ + return size; +} + +void encodedString::setContent(const char*nContent,int nSize) +{ + if (nSize>0 && nContent) { + content = (char*)malloc(nSize*sizeof(char)); + memcpy(content,nContent,nSize); + size = nSize; + } +} + +void encodedString::setContent(char*nContent,int nSize) +{ + content = nContent; + size = nSize; +} + +folderStat&folderStat::operator=(const folderStat&old) +{ + message_count = old.message_count; + message_unseen = old.message_unseen; + message_recent = old.message_recent; + return *this; +} + diff --git a/kmicromail/libmailwrapper/mailtypes.h b/kmicromail/libmailwrapper/mailtypes.h new file mode 100644 index 0000000..c317880 --- a/dev/null +++ b/kmicromail/libmailwrapper/mailtypes.h @@ -0,0 +1,206 @@ +#ifndef __MAIL_TYPES_H +#define __MAIL_TYPES_H + +#define FLAG_ANSWERED 0 +#define FLAG_FLAGGED 1 +#define FLAG_DELETED 2 +#define FLAG_SEEN 3 +#define FLAG_DRAFT 4 +#define FLAG_RECENT 5 + +#include + +#include +#include +#include +#include +#include + +class AbstractMail; +/* a class to describe mails in a mailbox */ +/* Attention! + From programmers point of view it would make sense to + store the mail body into this class, too. + But: not from the point of view of the device. + Mailbodies can be real large. So we request them when + needed from the mail-wrapper class direct from the server itself + (imap) or from a file-based cache (pop3?) + So there is no interface "const QString&body()" but you should + make a request to the mailwrapper with this class as parameter to + get the body. Same words for the attachments. +*/ +class RecMail:public Opie::Core::ORefCount +{ +public: + RecMail(); + RecMail(const RecMail&old); + virtual ~RecMail(); + + const unsigned int getNumber()const{return msg_number;} + void setNumber(unsigned int number){msg_number=number;} + const QString&getDate()const{ return date; } + void setDate( const QString&a ) { date = a; } + const QString&getFrom()const{ return from; } + void setFrom( const QString&a ) { from = a; } + const QString&getSubject()const { return subject; } + void setSubject( const QString&s ) { subject = s; } + const QString&getMbox()const{return mbox;} + void setMbox(const QString&box){mbox = box;} + void setMsgid(const QString&id){msg_id=id;} + const QString&Msgid()const{return msg_id;} + void setReplyto(const QString&reply){replyto=reply;} + const QString&Replyto()const{return replyto;} + void setMsgsize(unsigned int size){msg_size = size;} + const unsigned int Msgsize()const{return msg_size;} + + + void setTo(const QStringList&list); + const QStringList&To()const; + void setCC(const QStringList&list); + const QStringList&CC()const; + void setBcc(const QStringList&list); + const QStringList&Bcc()const; + void setInreply(const QStringList&list); + const QStringList&Inreply()const; + void setReferences(const QStringList&list); + const QStringList&References()const; + + const QBitArray&getFlags()const{return msg_flags;} + void setFlags(const QBitArray&flags){msg_flags = flags;} + + void setWrapper(AbstractMail*wrapper); + AbstractMail* Wrapper(); + +protected: + QString subject,date,from,mbox,msg_id,replyto; + unsigned int msg_number,msg_size; + QBitArray msg_flags; + QStringList to,cc,bcc,in_reply_to,references; + AbstractMail*wrapper; + void init(); + void copy_old(const RecMail&old); +}; + +typedef Opie::Core::OSmartPointer RecMailP; +typedef QMap part_plist_t; + +class RecPart:public Opie::Core::ORefCount +{ +protected: + QString m_type,m_subtype,m_identifier,m_encoding,m_description; + unsigned int m_lines,m_size; + part_plist_t m_Parameters; + /* describes the position in the mail */ + QValueList m_poslist; + +public: + RecPart(); + RecPart(const RecPart&); + virtual ~RecPart(); + + const QString&Type()const; + void setType(const QString&type); + const QString&Subtype()const; + void setSubtype(const QString&subtype); + const QString&Identifier()const; + void setIdentifier(const QString&identifier); + const QString&Encoding()const; + void setEncoding(const QString&encoding); + const QString&Description()const; + void setDescription(const QString&desc); + void setLines(unsigned int lines); + const unsigned int Lines()const; + void setSize(unsigned int size); + const unsigned int Size()const; + + + void setParameters(const part_plist_t&list); + const part_plist_t&Parameters()const; + void addParameter(const QString&key,const QString&value); + const QString searchParamter(const QString&key)const; + void setPositionlist(const QValueList&poslist); + const QValueList& Positionlist()const; +}; + +typedef Opie::Core::OSmartPointer RecPartP; + +class RecBody:public Opie::Core::ORefCount +{ +protected: + QString m_BodyText; + QValueList m_PartsList; + RecPartP m_description; + +public: + RecBody(); + RecBody(const RecBody&old); + virtual ~RecBody(); + void setBodytext(const QString&); + const QString& Bodytext()const; + + void setDescription(const RecPartP&des); + const RecPartP& Description()const; + + void setParts(const QValueList&parts); + const QValueList& Parts()const; + void addPart(const RecPartP&part); +}; + +typedef Opie::Core::OSmartPointer RecBodyP; + +class encodedString +{ +public: + encodedString(); + /* + creates an new content string. + it makes a deep copy of it! + */ + encodedString(const char*nContent,unsigned int length); + /* + Take over the nContent. Means: it will just copy the pointer, not the content. + so make sure: No one else frees the string, the string has allocated with + malloc for compatibility with c-based libs + */ + encodedString(char*nContent,unsigned int nSize); + /* copy construkor - makes ALWAYS a deep copy!!!! */ + encodedString(const encodedString&old); + /* assign operator - makes ALWAYS a deep copy!!!! */ + encodedString& operator=(const encodedString&old); + /* destructor - cleans the content */ + virtual ~encodedString(); + + /* returns a pointer to the content - do not delete yoursel! */ + const char*Content()const; + /* returns the lengths of the content 'cause it must not be a null-terminated string! */ + const int Length()const; + + /* + makes a deep copy of nContent! + */ + void setContent(const char*nContent,int nSize); + /* + Take over the nContent. Means: it will just copy the pointer, not the content. + so make sure: No one else frees the string, the string has allocated with + malloc for compatibility with c-based libs + */ + void setContent(char*nContent,int nSize); + +protected: + char * content; + unsigned int size; + + void init(); + void copy_old(const encodedString&old); + void clean(); +}; + +struct folderStat +{ + unsigned int message_count; + unsigned int message_unseen; + unsigned int message_recent; + folderStat&operator=(const folderStat&old); +}; + +#endif diff --git a/kmicromail/libmailwrapper/mailwrapper.cpp b/kmicromail/libmailwrapper/mailwrapper.cpp new file mode 100644 index 0000000..9400649 --- a/dev/null +++ b/kmicromail/libmailwrapper/mailwrapper.cpp @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "mailwrapper.h" +//#include "logindialog.h" +//#include "defines.h" + +#define UNDEFINED 64 +#define MAXLINE 76 +#define UTF16MASK 0x03FFUL +#define UTF16SHIFT 10 +#define UTF16BASE 0x10000UL +#define UTF16HIGHSTART 0xD800UL +#define UTF16HIGHEND 0xDBFFUL +#define UTF16LOSTART 0xDC00UL +#define UTF16LOEND 0xDFFFUL + + +using namespace Opie::Core; +Attachment::Attachment( QString lnk ) +{ + doc = lnk; + size = QFileInfo( doc ).size(); + mPix = SmallIcon( "files" ); +} + +Folder::Folder(const QString&tmp_name, const QString&sep ) +{ + name = tmp_name; + nameDisplay = name; + separator = sep; + prefix = ""; +} + +Folder::~Folder() +{ +} + +const QString& Folder::Separator()const +{ + return separator; +} + +IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,bool no_inf, const QString&aprefix ) + : Folder( name,sep ),m_MaySelect(select),m_NoInferior(no_inf) +{ + // Decode IMAP foldername + nameDisplay = IMAPFolder::decodeFolderName( name ); + /* + odebug << "folder " + name + " - displayed as " + nameDisplay << oendl; + */ + prefix = aprefix; + + if (prefix.length()>0) { + if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { + nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); + } + } +} + +IMAPFolder::~IMAPFolder() +{ +} + +static unsigned char base64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + +/** + * Decodes base64 encoded parts of the imapfolder name + * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc + */ +QString IMAPFolder::decodeFolderName( const QString &name ) +{ + unsigned char c, i, bitcount; + unsigned long ucs4, utf16, bitbuf; + unsigned char base64[256], utf8[6]; + unsigned long srcPtr = 0; + QCString dst = ""; + QCString src = name.ascii(); + + /* initialize modified base64 decoding table */ + memset(base64, UNDEFINED, sizeof(base64)); + for (i = 0; i < sizeof(base64chars); ++i) { + base64[(int)base64chars[i]] = i; + } + + /* loop until end of string */ + while (srcPtr < src.length ()) { + c = src[srcPtr++]; + /* deal with literal characters and &- */ + if (c != '&' || src[srcPtr] == '-') { + /* encode literally */ + dst += c; + /* skip over the '-' if this is an &- sequence */ + if (c == '&') + srcPtr++; + } else { + /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */ + bitbuf = 0; + bitcount = 0; + ucs4 = 0; + while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) { + ++srcPtr; + bitbuf = (bitbuf << 6) | c; + bitcount += 6; + /* enough bits for a UTF-16 character? */ + if (bitcount >= 16) { + bitcount -= 16; + utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff; + /* convert UTF16 to UCS4 */ + if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) { + ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT; + continue; + } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) { + ucs4 += utf16 - UTF16LOSTART + UTF16BASE; + } else { + ucs4 = utf16; + } + /* convert UTF-16 range of UCS4 to UTF-8 */ + if (ucs4 <= 0x7fUL) { + utf8[0] = ucs4; + i = 1; + } else if (ucs4 <= 0x7ffUL) { + utf8[0] = 0xc0 | (ucs4 >> 6); + utf8[1] = 0x80 | (ucs4 & 0x3f); + i = 2; + } else if (ucs4 <= 0xffffUL) { + utf8[0] = 0xe0 | (ucs4 >> 12); + utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[2] = 0x80 | (ucs4 & 0x3f); + i = 3; + } else { + utf8[0] = 0xf0 | (ucs4 >> 18); + utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f); + utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[3] = 0x80 | (ucs4 & 0x3f); + i = 4; + } + /* copy it */ + for (c = 0; c < i; ++c) { + dst += utf8[c]; + } + } + } + /* skip over trailing '-' in modified UTF-7 encoding */ + if (src[srcPtr] == '-') + ++srcPtr; + } + } + + return QString::fromUtf8( dst.data() ); +} + +Mail::Mail() + :Opie::Core::ORefCount(),name(""), mail(""), to(""), cc(""), bcc(""), reply(""), subject(""), message("") +{ +} + +MHFolder::MHFolder(const QString&disp_name,const QString&mbox) + : Folder( disp_name,"/" ) +{ + separator = "/"; + name = mbox; + if (!disp_name.startsWith("/") && disp_name.length()>0) + name+="/"; + name+=disp_name; + if (disp_name.length()==0) { + nameDisplay = separator; + } + prefix = mbox; +} + +MHFolder::~MHFolder() +{ +} diff --git a/kmicromail/libmailwrapper/mailwrapper.h b/kmicromail/libmailwrapper/mailwrapper.h new file mode 100644 index 0000000..adfac6a --- a/dev/null +++ b/kmicromail/libmailwrapper/mailwrapper.h @@ -0,0 +1,128 @@ +#ifndef MAILWRAPPER_H +#define MAILWRAPPER_H + +#include + +#include +#include +#include +#include + +#include "settings.h" + +#include +/* +class Attachment +{ +public: + Attachment( DocLnk lnk ); + virtual ~Attachment(){} + const QString getFileName()const{ return doc.file(); } + const QString getName()const{ return doc.name(); } + const QString getMimeType()const{ return doc.type(); } + const QPixmap getPixmap()const{ return doc.pixmap(); } + const int getSize()const { return size; } + DocLnk getDocLnk() { return doc; } + +protected: + DocLnk doc; + int size; + +}; +*/ + +class Attachment +{ +public: + Attachment( QString lnk ); + virtual ~Attachment(){} + const QString getFileName()const{ return QFileInfo( doc ).fileName (); } + const QString getName()const{ return QFileInfo( doc ).baseName (); } + const QString getMimeType()const{ return QFileInfo( doc ).extension(false); } + const QPixmap getPixmap()const{ return mPix; } + const int getSize()const { return size; } + QString getDocLnk() { return doc; } + +protected: + QPixmap mPix; + QString doc; + int size; + +}; + +class Mail:public Opie::Core::ORefCount +{ +public: + Mail(); + /* Possible that this destructor must not be declared virtual + * 'cause it seems that it will never have some child classes. + * in this case this object will not get a virtual table -> memory and + * speed will be a little bit better? + */ + virtual ~Mail(){} + void addAttachment( Attachment *att ) { attList.append( att ); } + const QList& getAttachments()const { return attList; } + void removeAttachment( Attachment *att ) { attList.remove( att ); } + const QString&getName()const { return name; } + void setName( QString s ) { name = s; } + const QString&getMail()const{ return mail; } + void setMail( const QString&s ) { mail = s; } + const QString&getTo()const{ return to; } + void setTo( const QString&s ) { to = s; } + const QString&getCC()const{ return cc; } + void setCC( const QString&s ) { cc = s; } + const QString&getBCC()const { return bcc; } + void setBCC( const QString&s ) { bcc = s; } + const QString&getMessage()const { return message; } + void setMessage( const QString&s ) { message = s; } + const QString&getSubject()const { return subject; } + void setSubject( const QString&s ) { subject = s; } + const QString&getReply()const{ return reply; } + void setReply( const QString&a ) { reply = a; } + void setInreply(const QStringList&list){m_in_reply_to = list;} + const QStringList&Inreply()const{return m_in_reply_to;} + +private: + QList attList; + QString name, mail, to, cc, bcc, reply, subject, message; + QStringList m_in_reply_to; +}; + +class Folder:public Opie::Core::ORefCount +{ +public: + Folder( const QString&init_name,const QString&sep ); + virtual ~Folder(); + const QString&getDisplayName()const { return nameDisplay; } + const QString&getName()const { return name; } + const QString&getPrefix()const{return prefix; } + virtual bool may_select()const{return true;} + virtual bool no_inferior()const{return true;} + const QString&Separator()const; + +protected: + QString nameDisplay, name, separator,prefix; +}; + +typedef Opie::Core::OSmartPointer FolderP; + +class MHFolder : public Folder +{ +public: + MHFolder(const QString&disp_name,const QString&mbox); + virtual ~MHFolder(); +}; + +class IMAPFolder : public Folder +{ + public: + IMAPFolder(const QString&name, const QString&sep, bool select=true,bool noinf=false,const QString&prefix="" ); + virtual ~IMAPFolder(); + virtual bool may_select()const{return m_MaySelect;} + virtual bool no_inferior()const{return m_NoInferior;} + private: + static QString decodeFolderName( const QString &name ); + bool m_MaySelect,m_NoInferior; +}; + +#endif diff --git a/kmicromail/libmailwrapper/mboxwrapper.cpp b/kmicromail/libmailwrapper/mboxwrapper.cpp new file mode 100644 index 0000000..39dd156 --- a/dev/null +++ b/kmicromail/libmailwrapper/mboxwrapper.cpp @@ -0,0 +1,338 @@ +#include "mboxwrapper.h" +#include "mailtypes.h" +#include "mailwrapper.h" +#include +#include +#include + + +#include + +using namespace Opie::Core; +MBOXwrapper::MBOXwrapper(const QString & mbox_dir,const QString&mbox_name) + : Genericwrapper(),MBOXPath(mbox_dir),MBOXName(mbox_name) +{ + QDir dir(MBOXPath); + if (!dir.exists()) { + dir.mkdir(MBOXPath); + } +} + +MBOXwrapper::~MBOXwrapper() +{ +} + +void MBOXwrapper::listMessages(const QString & mailbox, QValueList &target ) +{ + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mailbox; + + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + //odebug << "Error initializing mbox" << oendl; + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + + parseList(target,folder->fld_session,mailbox); + + mailfolder_disconnect(folder); + mailfolder_free(folder); + mailstorage_free(storage); + Global::statusMessage(tr("Mailbox has %1 mail(s)").arg(target.count())); +} + +QValueList >* MBOXwrapper::listFolders() +{ + QValueList >* folders = new QValueList >(); + QDir dir(MBOXPath); + if (!dir.exists()) return folders; + dir.setFilter(QDir::Files|QDir::Writable|QDir::Readable); + QStringList entries = dir.entryList(); + QStringList::ConstIterator it = entries.begin(); + for (;it!=entries.end();++it) { + FolderP inb=new Folder(*it,"/"); + folders->append(inb); + } + return folders; +} + +void MBOXwrapper::deleteMail(const RecMailP & mail) +{ + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mail->getMbox(); + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + ; // << "Error initializing mbox" << oendl; + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + r = mailsession_remove_message(folder->fld_session,mail->getNumber()); + if (r != MAIL_NO_ERROR) { + ; // << "error deleting mail" << oendl; + } + mailfolder_free(folder); + mailstorage_free(storage); +} + +void MBOXwrapper::answeredMail(const RecMailP&) +{ +} + +RecBodyP MBOXwrapper::fetchBody( const RecMailP &mail ) +{ + RecBodyP body = new RecBody(); + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mail->getMbox(); + mailmessage * msg; + char*data=0; + size_t size; + + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + ; // << "Error initializing mbox" << oendl; + mailfolder_free(folder); + mailstorage_free(storage); + return body; + } + r = mailsession_get_message(folder->fld_session, mail->getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + ; // << "Error fetching mail " << mail->getNumber() << "" << oendl; + mailfolder_free(folder); + mailstorage_free(storage); + return body; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + ; // << "Error fetching mail " << mail->getNumber() << "" << oendl; + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); + return body; + } + body = parseMail(msg); + mailmessage_fetch_result_free(msg,data); + mailfolder_free(folder); + mailstorage_free(storage); + + return body; +} + +void MBOXwrapper::mbox_progress( size_t current, size_t maximum ) +{ + ; // << "MBOX " << current << " von " << maximum << "" << oendl; +} + +int MBOXwrapper::createMbox(const QString&folder,const FolderP&,const QString&,bool ) +{ + QString p = MBOXPath+"/"; + p+=folder; + QFileInfo fi(p); + if (fi.exists()) { + Global::statusMessage(tr("Mailbox exists.")); + return 0; + } + mailmbox_folder*f = 0; + if (mailmbox_init(p.latin1(),0,1,0,&f) != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error init folder")); + return 0; + } + if (f) mailmbox_done(f); + return 1; +} + +void MBOXwrapper::storeMessage(const char*msg,size_t length, const QString&folder) +{ + QString p = MBOXPath+"/"; + p+=folder; + mailmbox_folder*f = 0; + int r = mailmbox_init(p.latin1(),0,1,0,&f); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error init folder")); + return; + } + r = mailmbox_append_message(f,msg,length); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error writing to message folder")); + } + mailmbox_done(f); +} + +encodedString* MBOXwrapper::fetchRawBody(const RecMailP&mail) +{ + RecBody body; + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mail->getMbox(); + mailmessage * msg; + char*data=0; + size_t size; + + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error initializing mbox")); + mailfolder_free(folder); + mailstorage_free(storage); + return 0; + } + r = mailsession_get_message(folder->fld_session, mail->getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail->getNumber())); + mailfolder_free(folder); + mailstorage_free(storage); + return 0; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail->getNumber())); + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); + return 0; + } + encodedString*result = new encodedString(data,size); + + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); + return result; +} + +void MBOXwrapper::deleteMails(const QString & mailbox,const QValueList &target) +{ + QString p = MBOXPath+"/"; + p+=mailbox; + mailmbox_folder*f = 0; + int r = mailmbox_init(p.latin1(),0,1,0,&f); + if (r != MAIL_NO_ERROR) { + ; // << "Error init folder" << oendl; + return; + } + deleteMails(f,target); + mailmbox_done(f); +} + +void MBOXwrapper::deleteMails(mailmbox_folder*f,const QValueList &target) +{ + if (!f) return; + int r; + QValueList::ConstIterator it; + for (it=target.begin(); it != target.end();++it) { + r = mailmbox_delete_msg(f,(*it)->getNumber()); + if (r!=MAILMBOX_NO_ERROR) { + ; // << "error delete mail" << oendl; + } + } + r = mailmbox_expunge(f); + if (r != MAILMBOX_NO_ERROR) { + ; // << "error expunge mailbox" << oendl; + } +} + +int MBOXwrapper::deleteAllMail(const FolderP&tfolder) +{ + if (!tfolder) return 0; + QString p = MBOXPath+"/"+tfolder->getDisplayName(); + int res = 1; + + mailfolder*folder = 0; + mailmessage_list*l=0; + mailstorage*storage = mailstorage_new(NULL); + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error initializing mbox")); + res = 0; + } + if (res) { + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error initializing mbox")); + res = 0; + } + } + if (res) { + r = mailsession_get_messages_list(folder->fld_session,&l); + if (r != MAIL_NO_ERROR) { + ; // << "Error message list" << oendl; + res=0; + } + } + for(unsigned int i = 0 ; l!= 0 && res==1 && i < carray_count(l->msg_tab) ; ++i) { + r = mailsession_remove_message(folder->fld_session,i+1); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error deleting mail %1").arg(i+1)); + res = 0; + break; + } + } + if (l) mailmessage_list_free(l); + if (folder) mailfolder_free(folder); + if (storage) mailstorage_free(storage); + return res; +} + +int MBOXwrapper::deleteMbox(const FolderP&tfolder) +{ + if (!tfolder) return 0; + QString p = MBOXPath+"/"+tfolder->getDisplayName(); + QFile fi(p); + if (!fi.exists()) { + Global::statusMessage(tr("Mailbox doesn't exist.")); + return 0; + } + if (!fi.remove()) { + Global::statusMessage(tr("Error deleting Mailbox.")); + return 0; + } + return 1; +} + +void MBOXwrapper::statusFolder(folderStat&target_stat,const QString & mailbox) +{ + mailfolder*folder = 0; + mailstorage*storage = mailstorage_new(NULL); + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + QString p = MBOXPath+"/"+mailbox; + QFile fi(p); + if (!fi.exists()) { + Global::statusMessage(tr("Mailbox doesn't exist.")); + return; + } + int r = mbox_mailstorage_init(storage,(char*)p.latin1(),0,0,0); + folder = mailfolder_new( storage,(char*)p.latin1(),NULL); + r = mailfolder_connect(folder); + r = mailsession_status_folder(folder->fld_session,(char*)mailbox.latin1(),&target_stat.message_count, + &target_stat.message_recent,&target_stat.message_unseen); + if (folder) mailfolder_free(folder); + if (storage) mailstorage_free(storage); +} + +MAILLIB::ATYPE MBOXwrapper::getType()const +{ + return MAILLIB::A_MBOX; +} + +const QString&MBOXwrapper::getName()const +{ + return MBOXName; +} diff --git a/kmicromail/libmailwrapper/mboxwrapper.h b/kmicromail/libmailwrapper/mboxwrapper.h new file mode 100644 index 0000000..9731b85 --- a/dev/null +++ b/kmicromail/libmailwrapper/mboxwrapper.h @@ -0,0 +1,46 @@ +#ifndef __MBOX_WRAPPER_H +#define __MBOX_WRAPPER_H + +#include "genericwrapper.h" +#include + +class encodedString; +struct mailmbox_folder; + +class MBOXwrapper : public Genericwrapper +{ + Q_OBJECT + +public: + MBOXwrapper(const QString & dir,const QString&name); + virtual ~MBOXwrapper(); + + virtual void listMessages(const QString & mailbox, QValueList&target ); + virtual QValueList >* listFolders(); + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + + virtual void deleteMail(const RecMailP&mail); + virtual void answeredMail(const RecMailP&mail); + + virtual int createMbox(const QString&folder,const Opie::Core::OSmartPointer&f=0, + const QString&d="",bool s=false); + virtual int deleteMbox(const Opie::Core::OSmartPointer&); + + virtual void storeMessage(const char*msg,size_t length, const QString&folder); + + virtual RecBodyP fetchBody( const RecMailP &mail ); + static void mbox_progress( size_t current, size_t maximum ); + + virtual encodedString* fetchRawBody(const RecMailP&mail); + virtual void deleteMails(const QString & FolderName,const QValueList &target); + virtual int deleteAllMail(const Opie::Core::OSmartPointer&); + virtual MAILLIB::ATYPE getType()const; + virtual const QString&getName()const; + +protected: + static void deleteMails(mailmbox_folder*f,const QValueList &target); + QString MBOXPath; + QString MBOXName; +}; + +#endif diff --git a/kmicromail/libmailwrapper/mhwrapper.cpp b/kmicromail/libmailwrapper/mhwrapper.cpp new file mode 100644 index 0000000..7ef9b32 --- a/dev/null +++ b/kmicromail/libmailwrapper/mhwrapper.cpp @@ -0,0 +1,446 @@ +#include "mhwrapper.h" +#include "mailtypes.h" +#include "mailwrapper.h" +#include +#include +#include +#include +#include +#include +//#include + +using namespace Opie::Core; +MHwrapper::MHwrapper(const QString & mbox_dir,const QString&mbox_name) + : Genericwrapper(),MHPath(mbox_dir),MHName(mbox_name) +{ + if (MHPath.length()>0) { + if (MHPath[MHPath.length()-1]=='/') { + MHPath=MHPath.left(MHPath.length()-1); + } + //odebug << MHPath << oendl; + QDir dir(MHPath); + if (!dir.exists()) { + dir.mkdir(MHPath); + } + init_storage(); + } +} + +void MHwrapper::init_storage() +{ + int r; + QString pre = MHPath; + if (!m_storage) { + m_storage = mailstorage_new(NULL); + r = mh_mailstorage_init(m_storage,(char*)pre.latin1(),0,0,0); + if (r != MAIL_NO_ERROR) { + qDebug(" error init storage "); + mailstorage_free(m_storage); + m_storage = 0; + return; + } + } + r = mailstorage_connect(m_storage); + if (r!=MAIL_NO_ERROR) { + qDebug("error connecting storage "); + mailstorage_free(m_storage); + m_storage = 0; + } +} + +void MHwrapper::clean_storage() +{ + if (m_storage) { + mailstorage_disconnect(m_storage); + mailstorage_free(m_storage); + m_storage = 0; + } +} + +MHwrapper::~MHwrapper() +{ + clean_storage(); +} + +void MHwrapper::listMessages(const QString & mailbox, QValueList > &target ) +{ + init_storage(); + if (!m_storage) { + return; + } + QString f = buildPath(mailbox); + int r = mailsession_select_folder(m_storage->sto_session,(char*)f.latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("listMessages: error selecting folder! "); + return; + } + parseList(target,m_storage->sto_session,f); + Global::statusMessage(tr("Mailbox has %1 mail(s)").arg(target.count())); +} + +QValueList >* MHwrapper::listFolders() +{ + QValueList >* folders = new QValueList >(); + /* this is needed! */ + if (m_storage) mailstorage_disconnect(m_storage); + init_storage(); + if (!m_storage) { + return folders; + } + mail_list*flist = 0; + clistcell*current=0; + int r = mailsession_list_folders(m_storage->sto_session,NULL,&flist); + if (r != MAIL_NO_ERROR || !flist) { + qDebug("error getting folder list "); + return folders; + } + for (current=clist_begin(flist->mb_list);current!=0;current=clist_next(current)) { + QString t = (char*)current->data; + t.replace(0,MHPath.length(),""); + folders->append(new MHFolder(t,MHPath)); + } + mail_list_free(flist); + return folders; +} + +void MHwrapper::deleteMail(const RecMailP&mail) +{ + init_storage(); + if (!m_storage) { + return; + } + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail->getMbox().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder! "); + return; + } + r = mailsession_remove_message(m_storage->sto_session,mail->getNumber()); + if (r != MAIL_NO_ERROR) { + qDebug("error deleting mail "); + } +} + +void MHwrapper::answeredMail(const RecMailP&) +{ +} + +RecBodyP MHwrapper::fetchBody( const RecMailP &mail ) +{ + RecBodyP body = new RecBody(); + init_storage(); + if (!m_storage) { + return body; + } + mailmessage * msg; + char*data=0; + + /* mail should hold the complete path! */ + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail->getMbox().latin1()); + if (r != MAIL_NO_ERROR) { + return body; + } + r = mailsession_get_message(m_storage->sto_session, mail->getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail "); + + return body; + } + body = parseMail(msg); + mailmessage_fetch_result_free(msg,data); + return body; +} + +void MHwrapper::mbox_progress( size_t current, size_t maximum ) +{ + qDebug("MBox Progress %d of %d",current,maximum ); + //odebug << "MH " << current << " von " << maximum << "" << oendl; +} + +QString MHwrapper::buildPath(const QString&p) +{ + QString f=""; + if (p.length()==0||p=="/") + return MHPath; + if (!p.startsWith(MHPath)) { + f+=MHPath; + } + if (!p.startsWith("/")) { + f+="/"; + } + f+=p; + return f; +} + +int MHwrapper::createMbox(const QString&folder,const FolderP&pfolder,const QString&,bool ) +{ + init_storage(); + if (!m_storage) { + return 0; + } + QString f; + if (!pfolder) { + // toplevel folder + f = buildPath(folder); + } else { + f = pfolder->getName(); + f+="/"; + f+=folder; + } + + int r = mailsession_create_folder(m_storage->sto_session,(char*)f.latin1()); + if (r != MAIL_NO_ERROR) { + qDebug("error creating folder "); + return 0; + } + qDebug("Folder created "); + return 1; +} + +void MHwrapper::storeMessage(const char*msg,size_t length, const QString&Folder) +{ + init_storage(); + if (!m_storage) { + return; + } + QString f = buildPath(Folder); + int r = mailsession_select_folder(m_storage->sto_session,(char*)f.latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder! "); + return; + } + r = mailsession_append_message(m_storage->sto_session,(char*)msg,length); + if (r!=MAIL_NO_ERROR) { + qDebug("error storing mail "); + } + return; +} + +encodedString* MHwrapper::fetchRawBody(const RecMailP&mail) +{ + encodedString*result = 0; + init_storage(); + if (!m_storage) { + return result; + } + mailmessage * msg = 0; + char*data=0; + size_t size; + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail->getMbox().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder! "); + return result; + } + r = mailsession_get_message(m_storage->sto_session, mail->getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail->getNumber())); + return 0; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail->getNumber())); + if (msg) mailmessage_free(msg); + return 0; + } + result = new encodedString(data,size); + if (msg) mailmessage_free(msg); + return result; +} + +void MHwrapper::deleteMails(const QString & mailbox,const QValueList &target) +{ + QString f = buildPath(mailbox); + int r = mailsession_select_folder(m_storage->sto_session,(char*)f.latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("deleteMails: error selecting folder! "); + return; + } + QValueList::ConstIterator it; + for (it=target.begin(); it!=target.end();++it) { + r = mailsession_remove_message(m_storage->sto_session,(*it)->getNumber()); + if (r != MAIL_NO_ERROR) { + qDebug("error deleting mail "); + break; + } + } +} + +int MHwrapper::deleteAllMail(const FolderP&tfolder) +{ + init_storage(); + if (!m_storage) { + return 0; + } + int res = 1; + if (!tfolder) return 0; + int r = mailsession_select_folder(m_storage->sto_session,(char*)tfolder->getName().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder! "); + return 0; + } + mailmessage_list*l=0; + r = mailsession_get_messages_list(m_storage->sto_session,&l); + if (r != MAIL_NO_ERROR) { + qDebug("Error message list "); + res = 0; + } + unsigned j = 0; + for(unsigned int i = 0 ; l!= 0 && res==1 && i < carray_count(l->msg_tab) ; ++i) { + mailmessage * msg; + msg = (mailmessage*)carray_get(l->msg_tab, i); + j = msg->msg_index; + r = mailsession_remove_message(m_storage->sto_session,j); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error deleting mail %1").arg(i+1)); + res = 0; + break; + } + } + if (l) mailmessage_list_free(l); + return res; +} + +int MHwrapper::deleteMbox(const FolderP&tfolder) +{ + init_storage(); + if (!m_storage) { + return 0; + } + if (!tfolder) return 0; + if (tfolder->getName()=="/" || tfolder->getName().isEmpty()) return 0; + + int r = mailsession_delete_folder(m_storage->sto_session,(char*)tfolder->getName().latin1()); + + if (r != MAIL_NO_ERROR) { + qDebug("error deleting mail box "); + return 0; + } + QString cmd = "rm -rf "+tfolder->getName(); + QStringList command; + command << "/bin/sh"; + command << "-c"; + command << cmd.latin1(); + OProcess *process = new OProcess(); + + connect(process, SIGNAL(processExited(Opie::Core::OProcess*)), + this, SLOT( processEnded(Opie::Core::OProcess*))); + connect(process, SIGNAL( receivedStderr(Opie::Core::OProcess*,char*,int)), + this, SLOT( oprocessStderr(Opie::Core::OProcess*,char*,int))); + + *process << command; + removeMboxfailed = false; + if(!process->start(OProcess::Block, OProcess::All) ) { + qDebug("could not start process "); + return 0; + } + qDebug("mail box deleted "); + return 1; +} + +void MHwrapper::processEnded(OProcess *p) +{ + if (p) delete p; +} + +void MHwrapper::oprocessStderr(OProcess*, char *buffer, int ) +{ + QString lineStr = buffer; + QMessageBox::warning( 0, tr("Error"), lineStr ,tr("Ok") ); + removeMboxfailed = true; +} + +void MHwrapper::statusFolder(folderStat&target_stat,const QString & mailbox) +{ + init_storage(); + if (!m_storage) { + return; + } + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + QString f = buildPath(mailbox); + int r = mailsession_status_folder(m_storage->sto_session,(char*)f.latin1(),&target_stat.message_count, + &target_stat.message_recent,&target_stat.message_unseen); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error retrieving status")); + } +} + +MAILLIB::ATYPE MHwrapper::getType()const +{ + return MAILLIB::A_MH; +} + +const QString&MHwrapper::getName()const +{ + return MHName; +} +void MHwrapper::mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + init_storage(); + if (!m_storage) { + return; + } + if (targetWrapper != this) { + qDebug("Using generic "); + Genericwrapper::mvcpMail(mail,targetFolder,targetWrapper,moveit); + return; + } + qDebug("Using internal routines for move/copy "); + QString tf = buildPath(targetFolder); + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail->getMbox().latin1()); + if (r != MAIL_NO_ERROR) { + qDebug("Error selecting source mailbox "); + return; + } + if (moveit) { + r = mailsession_move_message(m_storage->sto_session,mail->getNumber(),(char*)tf.latin1()); + } else { + r = mailsession_copy_message(m_storage->sto_session,mail->getNumber(),(char*)tf.latin1()); + } + if (r != MAIL_NO_ERROR) { + qDebug("Error copy/moving mail internal "); + } +} + +void MHwrapper::mvcpAllMails(const FolderP&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) +{ + init_storage(); + if (!m_storage) { + return; + } + if (targetWrapper != this) { + qDebug("Using generic "); + Genericwrapper::mvcpAllMails(fromFolder,targetFolder,targetWrapper,moveit); + return; + } + if (!fromFolder) return; + int r = mailsession_select_folder(m_storage->sto_session,(char*)fromFolder->getName().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting source folder! "); + return; + } + QString tf = buildPath(targetFolder); + mailmessage_list*l=0; + r = mailsession_get_messages_list(m_storage->sto_session,&l); + if (r != MAIL_NO_ERROR) { + qDebug("Error message list "); + } + unsigned j = 0; + for(unsigned int i = 0 ; l!= 0 && i < carray_count(l->msg_tab) ; ++i) { + mailmessage * msg; + msg = (mailmessage*)carray_get(l->msg_tab, i); + j = msg->msg_index; + if (moveit) { + r = mailsession_move_message(m_storage->sto_session,j,(char*)tf.latin1()); + } else { + r = mailsession_copy_message(m_storage->sto_session,j,(char*)tf.latin1()); + } + if (r != MAIL_NO_ERROR) { + qDebug("Error copy/moving mail interna "); + + break; + } + } + if (l) mailmessage_list_free(l); +} diff --git a/kmicromail/libmailwrapper/mhwrapper.h b/kmicromail/libmailwrapper/mhwrapper.h new file mode 100644 index 0000000..4310c84 --- a/dev/null +++ b/kmicromail/libmailwrapper/mhwrapper.h @@ -0,0 +1,60 @@ +#ifndef __MH_WRAPPER_H +#define __MH_WRAPPER_H + +#include "maildefines.h" + +#include "genericwrapper.h" +#include + +class encodedString; +struct mailmbox_folder; +namespace Opie {namespace Core {class OProcess;}} + +class MHwrapper : public Genericwrapper +{ + Q_OBJECT +public: + MHwrapper(const QString & dir,const QString&name); + virtual ~MHwrapper(); + + virtual void listMessages(const QString & mailbox, QValueList > &target ); + virtual QValueList >* listFolders(); + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + + virtual void deleteMail(const RecMailP&mail); + virtual void answeredMail(const RecMailP&mail); + virtual void mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + virtual void mvcpAllMails(const Opie::Core::OSmartPointer&fromFolder, + const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); + + virtual int createMbox(const QString&folder,const Opie::Core::OSmartPointer&f=0, + const QString&d="",bool s=false); + virtual int deleteMbox(const Opie::Core::OSmartPointer&); + + virtual void storeMessage(const char*msg,size_t length, const QString&folder); + + virtual RecBodyP fetchBody( const RecMailP &mail ); + static void mbox_progress( size_t current, size_t maximum ); + + virtual encodedString* fetchRawBody(const RecMailP&mail); + virtual void deleteMails(const QString & FolderName,const QValueList > &target); + virtual int deleteAllMail(const Opie::Core::OSmartPointer&); + virtual MAILLIB::ATYPE getType()const; + virtual const QString&getName()const; + +public slots: + /* for deleting maildirs we are using a system call */ + virtual void oprocessStderr(Opie::Core::OProcess*, char *buffer, int ); + virtual void processEnded(Opie::Core::OProcess *); +protected: + QString buildPath(const QString&p); + QString MHPath; + QString MHName; + + void init_storage(); + void clean_storage(); + + bool removeMboxfailed; +}; + +#endif diff --git a/kmicromail/libmailwrapper/nntpwrapper.cpp b/kmicromail/libmailwrapper/nntpwrapper.cpp new file mode 100644 index 0000000..daa128e --- a/dev/null +++ b/kmicromail/libmailwrapper/nntpwrapper.cpp @@ -0,0 +1,289 @@ +#include "nntpwrapper.h" +#include "logindialog.h" +#include "mailtypes.h" + +#include + +#include + +#include + + + +#define HARD_MSG_SIZE_LIMIT 5242880 + +using namespace Opie::Core; +NNTPwrapper::NNTPwrapper( NNTPaccount *a ) +: Genericwrapper() { + account = a; + m_nntp = NULL; + msgTempName = a->getFileName()+"_msg_cache"; + last_msg_id = 0; +} + +NNTPwrapper::~NNTPwrapper() { + logout(); + QFile msg_cache(msgTempName); + if (msg_cache.exists()) { + msg_cache.remove(); + } +} + +void NNTPwrapper::nntp_progress( size_t current, size_t maximum ) { + ; // << "NNTP: " << current << " of " << maximum << "" << oendl; +} + + +RecBodyP NNTPwrapper::fetchBody( const RecMailP &mail ) { + int err = NEWSNNTP_NO_ERROR; + char *message = 0; + size_t length = 0; + + RecBodyP body = new RecBody(); + login(); + if ( !m_nntp ) { + return body; + } + + mailmessage * mailmsg; + if (mail->Msgsize()>HARD_MSG_SIZE_LIMIT) { + ; // << "Message to large: " << mail->Msgsize() << "" << oendl; + return body; + } + + QFile msg_cache(msgTempName); + + cleanMimeCache(); + + if (mail->getNumber()!=last_msg_id) { + if (msg_cache.exists()) { + msg_cache.remove(); + } + msg_cache.open(IO_ReadWrite|IO_Truncate); + last_msg_id = mail->getNumber(); + err = mailsession_get_message(m_nntp->sto_session, mail->getNumber(), &mailmsg); + err = mailmessage_fetch(mailmsg,&message,&length); + msg_cache.writeBlock(message,length); + } else { + QString msg=""; + msg_cache.open(IO_ReadOnly); + message = new char[4096]; + memset(message,0,4096); + while (msg_cache.readBlock(message,4095)>0) { + msg+=message; + memset(message,0,4096); + } + delete message; + message = (char*)malloc(msg.length()+1*sizeof(char)); + memset(message,0,msg.length()+1); + memcpy(message,msg.latin1(),msg.length()); + /* transform to libetpan stuff */ + mailmsg = mailmessage_new(); + mailmessage_init(mailmsg, NULL, data_message_driver, 0, strlen(message)); + generic_message_t * msg_data; + msg_data = (generic_message_t *)mailmsg->msg_data; + msg_data->msg_fetched = 1; + msg_data->msg_message = message; + msg_data->msg_length = strlen(message); + } + body = parseMail(mailmsg); + + /* clean up */ + if (mailmsg) + mailmessage_free(mailmsg); + if (message) + free(message); + + return body; +} + + +void NNTPwrapper::listMessages(const QString & which, QValueList > &target ) +{ + login(); + if (!m_nntp) + return; + uint32_t res_messages,res_recent,res_unseen; + mailsession_status_folder(m_nntp->sto_session,(char*)which.latin1(),&res_messages,&res_recent,&res_unseen); + parseList(target,m_nntp->sto_session,which,true); +} + +void NNTPwrapper::login() +{ + if (account->getOffline()) + return; + /* we'll hold the line */ + if ( m_nntp != NULL ) + return; + + const char *server, *user, *pass; + QString User,Pass; + uint16_t port; + int err = NEWSNNTP_NO_ERROR; + + server = account->getServer().latin1(); + port = account->getPort().toUInt(); + + user = pass = 0; + + if ( ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) && account->getLogin() ) { + LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true ); + login.show(); + if ( QDialog::Accepted == login.exec() ) { + // ok + User = login.getUser().latin1(); + Pass = login.getPassword().latin1(); + } else { + // cancel + ; // << "NNTP: Login canceled" << oendl; + return; + } + } else { + User = account->getUser().latin1(); + Pass = account->getPassword().latin1(); + } + + if (User.isEmpty()) { + user=0; + pass = 0; + } else { + user=User.latin1(); + pass=Pass.latin1(); + } + // bool ssl = account->getSSL(); + + m_nntp=mailstorage_new(NULL); + + int conntypeset = account->ConnectionType(); + int conntype = 0; + if ( conntypeset == 3 ) { + conntype = CONNECTION_TYPE_COMMAND; + } else if ( conntypeset == 2 ) { + conntype = CONNECTION_TYPE_TLS; + } else if ( conntypeset == 1 ) { + conntype = CONNECTION_TYPE_STARTTLS; + } else if ( conntypeset == 0 ) { + conntype = CONNECTION_TYPE_TRY_STARTTLS; + } + + nntp_mailstorage_init(m_nntp,(char*)server, port, NULL, CONNECTION_TYPE_PLAIN, NNTP_AUTH_TYPE_PLAIN, + (char*)user,(char*)pass,0,0,0); + + err = mailstorage_connect( m_nntp ); + + if (err != NEWSNNTP_NO_ERROR) { + ; // << QString( "FEHLERNUMMER %1" ).arg( err ) << oendl; + // Global::statusMessage(tr("Error initializing folder")); + mailstorage_free(m_nntp); + m_nntp = 0; + + } else { + mailsession * session = m_nntp->sto_session; + newsnntp * news = ( ( nntp_session_state_data * )session->sess_data )->nntp_session; + news->nntp_progr_fun = &nntp_progress; + } + +} + +void NNTPwrapper::logout() +{ + int err = NEWSNNTP_NO_ERROR; + if ( m_nntp == NULL ) + return; + mailstorage_free(m_nntp); + m_nntp = 0; +} + +QValueList >* NNTPwrapper::listFolders() { + + QValueList >* folders = new QValueList >(); + QStringList groups; + if (account) { + groups = account->getGroups(); + } + for ( QStringList::Iterator it = groups.begin(); it != groups.end(); ++it ) { + folders->append(new Folder((*it),".")); + } + return folders; +} + +/* we made this method in raw nntp access of etpan and not via generic interface + * 'cause in that case there will be doubled copy operations. eg. the etpan would + * copy that stuff into its own structures and we must copy it into useable c++ + * structures for our frontend. this would not make sense, so it is better to reimplement + * the stuff from generic interface of etpan but copy it direct to qt classes. + */ +QStringList NNTPwrapper::listAllNewsgroups(const QString&mask) { + login(); + QStringList res; + clist *result = 0; + clistcell *current = 0; + newsnntp_group_description *group; + + if ( m_nntp ) { + mailsession * session = m_nntp->sto_session; + newsnntp * news = ( ( nntp_session_state_data * )session->sess_data )->nntp_session; + int err = NEWSNNTP_NO_ERROR; + if (mask.isEmpty()) { + err = newsnntp_list(news, &result); + } else { + /* taken from generic wrapper of etpan */ + QString nmask = mask+".*"; + err = newsnntp_list_active(news, nmask.latin1(), &result); + } + if ( err == NEWSNNTP_NO_ERROR && result) { + for ( current=clist_begin(result);current!=NULL;current=clist_next(current) ) { + group = ( newsnntp_group_description* ) current->data; + if (!group||!group->grp_name||strlen(group->grp_name)==0) continue; + res.append(group->grp_name); + } + } + } + if (result) { + newsnntp_list_free(result); + } + return res; +} + +void NNTPwrapper::answeredMail(const RecMailP&) {} + +void NNTPwrapper::statusFolder(folderStat&target_stat,const QString&) { + login(); + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + if (!m_nntp) + return; + int r = mailsession_status_folder(m_nntp->sto_session,0,&target_stat.message_count, + &target_stat.message_recent,&target_stat.message_unseen); +} + + +encodedString* NNTPwrapper::fetchRawBody(const RecMailP&mail) { + char*target=0; + size_t length=0; + encodedString*res = 0; + mailmessage * mailmsg = 0; + int err = mailsession_get_message(m_nntp->sto_session, mail->getNumber(), &mailmsg); + err = mailmessage_fetch(mailmsg,&target,&length); + if (mailmsg) + mailmessage_free(mailmsg); + if (target) { + res = new encodedString(target,length); + } + return res; +} + +MAILLIB::ATYPE NNTPwrapper::getType()const { + return account->getType(); +} + +const QString&NNTPwrapper::getName()const{ + return account->getAccountName(); +} + +void NNTPwrapper::deleteMail(const RecMailP&) { +} + +int NNTPwrapper::deleteAllMail(const FolderP&) { +} diff --git a/kmicromail/libmailwrapper/nntpwrapper.h b/kmicromail/libmailwrapper/nntpwrapper.h new file mode 100644 index 0000000..2fb82f2 --- a/dev/null +++ b/kmicromail/libmailwrapper/nntpwrapper.h @@ -0,0 +1,48 @@ +#ifndef __NNTPWRAPPER +#define __NNTPWRAPPER + +#include "mailwrapper.h" +#include "genericwrapper.h" +#include +#include + +class encodedString; +struct mailstorage; +struct mailfolder; + +class NNTPwrapper : public Genericwrapper +{ + + Q_OBJECT + +public: + NNTPwrapper( NNTPaccount *a ); + virtual ~NNTPwrapper(); + + /* mailbox will be ignored */ + virtual void listMessages(const QString & mailbox, QValueList > &target ); + /* should only get the subscribed one */ + virtual QValueList >* listFolders(); + /* mailbox will be ignored */ + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + QStringList listAllNewsgroups(const QString&mask = QString::null); + virtual void deleteMail(const RecMailP&mail); + virtual void answeredMail(const RecMailP&mail); + virtual int deleteAllMail(const Opie::Core::OSmartPointer&); + + virtual RecBodyP fetchBody( const RecMailP &mail ); + virtual encodedString* fetchRawBody(const RecMailP&mail); + virtual void logout(); + virtual MAILLIB::ATYPE getType()const; + virtual const QString&getName()const; + static void nntp_progress( size_t current, size_t maximum ); + +protected: + void login(); + NNTPaccount *account; + mailstorage* m_nntp; + + +}; + +#endif diff --git a/kmicromail/libmailwrapper/pop3wrapper.cpp b/kmicromail/libmailwrapper/pop3wrapper.cpp new file mode 100644 index 0000000..e5d083a --- a/dev/null +++ b/kmicromail/libmailwrapper/pop3wrapper.cpp @@ -0,0 +1,265 @@ +#include +#include "pop3wrapper.h" +#include "mailtypes.h" +#include "logindialog.h" +#include + + +#include +#include + +/* we don't fetch messages larger than 5 MB */ +#define HARD_MSG_SIZE_LIMIT 5242880 + +using namespace Opie::Core; +POP3wrapper::POP3wrapper( POP3account *a ) +: Genericwrapper() { + account = a; + m_pop3 = NULL; + msgTempName = a->getFileName()+"_msg_cache"; + last_msg_id = 0; +} + +POP3wrapper::~POP3wrapper() { + logout(); + QFile msg_cache(msgTempName); + if (msg_cache.exists()) { + msg_cache.remove(); + } +} + +void POP3wrapper::pop3_progress( size_t current, size_t maximum ) { + ; // odebug << "POP3: " << current << " of " << maximum << "" << oendl; +} + +RecBodyP POP3wrapper::fetchBody( const RecMailP &mail ) { + int err = MAILPOP3_NO_ERROR; + char *message = 0; + size_t length = 0; + + RecBodyP body = new RecBody(); + + login(); + if ( !m_pop3 ) { + return body; + } + + mailmessage * mailmsg; + if (mail->Msgsize()>HARD_MSG_SIZE_LIMIT) { + ; // odebug << "Message to large: " << mail->Msgsize() << "" << oendl; + return body; + } + + QFile msg_cache(msgTempName); + + cleanMimeCache(); + + if (mail->getNumber()!=last_msg_id) { + if (msg_cache.exists()) { + msg_cache.remove(); + } + msg_cache.open(IO_ReadWrite|IO_Truncate); + last_msg_id = mail->getNumber(); + err = mailsession_get_message(m_pop3->sto_session, mail->getNumber(), &mailmsg); + err = mailmessage_fetch(mailmsg,&message,&length); + msg_cache.writeBlock(message,length); + } else { + QString msg=""; + msg_cache.open(IO_ReadOnly); + message = new char[4096]; + memset(message,0,4096); + while (msg_cache.readBlock(message,4095)>0) { + msg+=message; + memset(message,0,4096); + } + delete message; + message = (char*)malloc(msg.length()+1*sizeof(char)); + memset(message,0,msg.length()+1); + memcpy(message,msg.latin1(),msg.length()); + /* transform to libetpan stuff */ + mailmsg = mailmessage_new(); + mailmessage_init(mailmsg, NULL, data_message_driver, 0, strlen(message)); + generic_message_t * msg_data; + msg_data = (generic_message_t *)mailmsg->msg_data; + msg_data->msg_fetched = 1; + msg_data->msg_message = message; + msg_data->msg_length = strlen(message); + } + body = parseMail(mailmsg); + + /* clean up */ + if (mailmsg) + mailmessage_free(mailmsg); + if (message) + free(message); + + return body; +} + +void POP3wrapper::listMessages(const QString &, QValueList > &target ) +{ + login(); + if (!m_pop3) + return; + uint32_t res_messages,res_recent,res_unseen; + mailsession_status_folder(m_pop3->sto_session,"INBOX",&res_messages,&res_recent,&res_unseen); + parseList(target,m_pop3->sto_session,"INBOX"); + Global::statusMessage( tr("Mailbox contains %1 mail(s)").arg(res_messages)); +} + +void POP3wrapper::login() +{ + if (account->getOffline()) + return; + /* we'll hold the line */ + if ( m_pop3 != NULL ) + return; + + const char *server, *user, *pass; + uint16_t port; + int err = MAILPOP3_NO_ERROR; + + server = account->getServer().latin1(); + port = account->getPort().toUInt(); + + if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) { + LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true ); + login.show(); + if ( QDialog::Accepted == login.exec() ) { + // ok + user = login.getUser().latin1(); + pass = login.getPassword().latin1(); + } else { + // cancel + ; // odebug << "POP3: Login canceled" << oendl; + return; + } + } else { + user = account->getUser().latin1(); + pass = account->getPassword().latin1(); + } + + // bool ssl = account->getSSL(); + + m_pop3=mailstorage_new(NULL); + + int conntypeset = account->ConnectionType(); + int conntype = 0; + if ( conntypeset == 3 ) { + conntype = CONNECTION_TYPE_COMMAND; + } else if ( conntypeset == 2 ) { + conntype = CONNECTION_TYPE_TLS; + } else if ( conntypeset == 1 ) { + conntype = CONNECTION_TYPE_STARTTLS; + } else if ( conntypeset == 0 ) { + conntype = CONNECTION_TYPE_TRY_STARTTLS; + } + + //(ssl?CONNECTION_TYPE_TLS:CONNECTION_TYPE_PLAIN); + + pop3_mailstorage_init(m_pop3,(char*)server, port, NULL, conntype, POP3_AUTH_TYPE_PLAIN, + (char*)user,(char*)pass,0,0,0); + + + err = mailstorage_connect(m_pop3); + if (err != MAIL_NO_ERROR) { + ; // odebug << QString( "FEHLERNUMMER %1" ).arg( err ) << oendl; + Global::statusMessage(tr("Error initializing folder")); + mailstorage_free(m_pop3); + m_pop3 = 0; + } else { + mailsession * session = m_pop3->sto_session; + mailpop3 * mail = ( ( pop3_session_state_data * )session->sess_data )->pop3_session; + if (mail) { + mail->pop3_progr_fun = &pop3_progress; + } + } +} + +void POP3wrapper::logout() +{ + if ( m_pop3 == NULL ) + return; + mailstorage_free(m_pop3); + m_pop3 = 0; +} + + +QValueList >* POP3wrapper::listFolders() { + QValueList >* folders = new QValueList(); + FolderP inb=new Folder("INBOX","/"); + folders->append(inb); + return folders; +} + +void POP3wrapper::deleteMail(const RecMailP&mail) { + login(); + if (!m_pop3) + return; + int err = mailsession_remove_message(m_pop3->sto_session,mail->getNumber()); + if (err != MAIL_NO_ERROR) { + Global::statusMessage(tr("error deleting mail")); + } +} + +void POP3wrapper::answeredMail(const RecMailP&) {} + +int POP3wrapper::deleteAllMail(const FolderP&) { + login(); + if (!m_pop3) + return 0; + int res = 1; + + uint32_t result = 0; + int err = mailsession_messages_number(m_pop3->sto_session,NULL,&result); + if (err != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error getting folder info")); + return 0; + } + for (unsigned int i = 0; i < result; ++i) { + err = mailsession_remove_message(m_pop3->sto_session,i+1); + if (err != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error deleting mail %1").arg(i+1)); + res=0; + } + break; + } + return res; +} + +void POP3wrapper::statusFolder(folderStat&target_stat,const QString&) { + login(); + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + if (!m_pop3) + return; + int r = mailsession_status_folder(m_pop3->sto_session,0,&target_stat.message_count, + &target_stat.message_recent,&target_stat.message_unseen); + if (r != MAIL_NO_ERROR) { + ; // odebug << "error getting folter status." << oendl; + } +} + +encodedString* POP3wrapper::fetchRawBody(const RecMailP&mail) { + char*target=0; + size_t length=0; + encodedString*res = 0; + mailmessage * mailmsg = 0; + int err = mailsession_get_message(m_pop3->sto_session, mail->getNumber(), &mailmsg); + err = mailmessage_fetch(mailmsg,&target,&length); + if (mailmsg) + mailmessage_free(mailmsg); + if (target) { + res = new encodedString(target,length); + } + return res; +} + +MAILLIB::ATYPE POP3wrapper::getType()const { + return account->getType(); +} + +const QString&POP3wrapper::getName()const{ + return account->getAccountName(); +} diff --git a/kmicromail/libmailwrapper/pop3wrapper.h b/kmicromail/libmailwrapper/pop3wrapper.h new file mode 100644 index 0000000..5101fa5 --- a/dev/null +++ b/kmicromail/libmailwrapper/pop3wrapper.h @@ -0,0 +1,42 @@ +#ifndef __POP3WRAPPER +#define __POP3WRAPPER + +#include "mailwrapper.h" +#include "genericwrapper.h" +#include + +class encodedString; +struct mailstorage; +struct mailfolder; + +class POP3wrapper : public Genericwrapper +{ + Q_OBJECT + +public: + POP3wrapper( POP3account *a ); + virtual ~POP3wrapper(); + /* mailbox will be ignored */ + virtual void listMessages(const QString & mailbox, QValueList > &target ); + virtual QValueList >* listFolders(); + /* mailbox will be ignored */ + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + + virtual void deleteMail(const RecMailP&mail); + virtual void answeredMail(const RecMailP&mail); + virtual int deleteAllMail(const Opie::Core::OSmartPointer&); + + virtual RecBodyP fetchBody( const RecMailP &mail ); + virtual encodedString* fetchRawBody(const RecMailP&mail); + virtual void logout(); + virtual MAILLIB::ATYPE getType()const; + virtual const QString&getName()const; + static void pop3_progress( size_t current, size_t maximum ); + +protected: + void login(); + POP3account *account; + mailstorage*m_pop3; +}; + +#endif diff --git a/kmicromail/libmailwrapper/sendmailprogress.cpp b/kmicromail/libmailwrapper/sendmailprogress.cpp new file mode 100644 index 0000000..dc0c75a --- a/dev/null +++ b/kmicromail/libmailwrapper/sendmailprogress.cpp @@ -0,0 +1,47 @@ +#include "sendmailprogress.h" +#include +#include + +progressMailSend::progressMailSend(QWidget*parent, const char * name) + :progressMailSendUI(parent,name,true),m_current_mail(0),m_current_single(0),m_max_mail(0),m_max_single(0) +{ +} + +progressMailSend::~progressMailSend() +{ +} + +void progressMailSend::setMaxMails(unsigned int aMaxMails) +{ + m_max_mail = aMaxMails; + allMailProgressBar->setTotalSteps(aMaxMails); + setMails(); +} + +void progressMailSend::setCurrentMails(unsigned int aCurrent) +{ + m_current_mail = aCurrent; + allMailProgressBar->setProgress(aCurrent); + setMails(); +} + +void progressMailSend::setSingleMail(unsigned int aCurrent,unsigned int aMax) +{ + m_current_single = aCurrent; + m_max_single = aMax; + setSingle(); +} + +void progressMailSend::setSingle() +{ + QString text = QString(tr("%1 of %2 bytes send")).arg(m_current_single).arg(m_max_single); + singleMailLabel->setText(text); + singleMailProgressBar->setTotalSteps(m_max_single); + singleMailProgressBar->setProgress(m_current_single); +} + +void progressMailSend::setMails() +{ + QString text = QString(tr("Sending mail %1 of %2")).arg(m_current_mail+1).arg(m_max_mail); + allMailLabel->setText(text); +} diff --git a/kmicromail/libmailwrapper/sendmailprogress.h b/kmicromail/libmailwrapper/sendmailprogress.h new file mode 100644 index 0000000..5b7d33b --- a/dev/null +++ b/kmicromail/libmailwrapper/sendmailprogress.h @@ -0,0 +1,19 @@ +#include "sendmailprogressui.h" + +class progressMailSend:public progressMailSendUI +{ + Q_OBJECT +public: + progressMailSend(QWidget*parent = 0, const char * name = 0); + ~progressMailSend(); + + void setMaxMails(unsigned int aMaxMails); + void setCurrentMails(unsigned int aCurrent); + + void setSingleMail(unsigned int aCurrent,unsigned int aMax); + +protected: + unsigned m_current_mail,m_current_single,m_max_mail,m_max_single; + void setSingle(); + void setMails(); +}; diff --git a/kmicromail/libmailwrapper/sendmailprogressui.ui b/kmicromail/libmailwrapper/sendmailprogressui.ui new file mode 100644 index 0000000..287ab5e --- a/dev/null +++ b/kmicromail/libmailwrapper/sendmailprogressui.ui @@ -0,0 +1,110 @@ + +progressMailSendUI + + QDialog + + name + progressMailSendUI + + + geometry + + 0 + 0 + 221 + 127 + + + + caption + Sending mail + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 2 + + + QLabel + + name + singleMailLabel + + + text + Progress of mail + + + alignment + AlignCenter + + + hAlign + + + + QProgressBar + + name + singleMailProgressBar + + + + QLabel + + name + allMailLabel + + + text + Sending mail + + + alignment + AlignCenter + + + hAlign + + + + QProgressBar + + name + allMailProgressBar + + + + + name + Spacer6 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + diff --git a/kmicromail/libmailwrapper/settings.cpp b/kmicromail/libmailwrapper/settings.cpp new file mode 100644 index 0000000..bdb2a25 --- a/dev/null +++ b/kmicromail/libmailwrapper/settings.cpp @@ -0,0 +1,440 @@ +#include +#include + +//#include +#include + +#include +#include "settings.h" +//#include "defines.h" + +#define IMAP_PORT "143" +#define IMAP_SSL_PORT "993" +#define SMTP_PORT "25" +#define SMTP_SSL_PORT "465" +#define POP3_PORT "110" +#define POP3_SSL_PORT "995" +#define NNTP_PORT "119" +#define NNTP_SSL_PORT "563" + + +Settings::Settings() + : QObject() +{ + updateAccounts(); +} + +void Settings::checkDirectory() +{ + qDebug("Settings::checkDirectory() "); + return; + locateLocal("data", "kmicromail" ); + /* + if ( !QDir( (QString) getenv( "HOME" ) + "/Applications/opiemail/" ).exists() ) { + system( "mkdir -p $HOME/Applications/opiemail" ); + qDebug("$HOME/Applications/opiemail created "); + } + */ +} + +QList Settings::getAccounts() +{ + return accounts; +} + +void Settings::addAccount( Account *account ) +{ + accounts.append( account ); +} + +void Settings::delAccount( Account *account ) +{ + accounts.remove( account ); + account->remove(); +} + +void Settings::updateAccounts() +{ + accounts.clear(); + QDir dir( locateLocal("data", "kmicromail" ) ); + QStringList::Iterator it; + + QStringList imap = dir.entryList( "imap-*" ); + for ( it = imap.begin(); it != imap.end(); it++ ) { + IMAPaccount *account = new IMAPaccount( (*it).replace(0, 5, "") ); + accounts.append( account ); + } + + QStringList pop3 = dir.entryList( "pop3-*" ); + for ( it = pop3.begin(); it != pop3.end(); it++ ) { + POP3account *account = new POP3account( (*it).replace(0, 5, "") ); + accounts.append( account ); + } + + QStringList smtp = dir.entryList( "smtp-*" ); + for ( it = smtp.begin(); it != smtp.end(); it++ ) { + SMTPaccount *account = new SMTPaccount( (*it).replace(0, 5, "") ); + accounts.append( account ); + } + + QStringList nntp = dir.entryList( "nntp-*" ); + for ( it = nntp.begin(); it != nntp.end(); it++ ) { + NNTPaccount *account = new NNTPaccount( (*it).replace(0, 5, "") ); + accounts.append( account ); + } + + readAccounts(); +} + +void Settings::saveAccounts() +{ + checkDirectory(); + Account *it; + + for ( it = accounts.first(); it; it = accounts.next() ) { + it->save(); + } +} + +void Settings::readAccounts() +{ + checkDirectory(); + Account *it; + + for ( it = accounts.first(); it; it = accounts.next() ) { + it->read(); + } +} + +Account::Account() +{ + accountName = "changeMe"; + type = MAILLIB::A_UNDEFINED; + ssl = false; + connectionType = 1; + offline = false; +} + +void Account::remove() +{ + QFile file( getFileName() ); + file.remove(); +} + +IMAPaccount::IMAPaccount() + : Account() +{ + file = IMAPaccount::getUniqueFileName(); + accountName = "New IMAP Account"; + ssl = false; + connectionType = 1; + type = MAILLIB::A_IMAP; + port = IMAP_PORT; +} + +IMAPaccount::IMAPaccount( QString filename ) + : Account() +{ + file = filename; + accountName = "New IMAP Account"; + ssl = false; + connectionType = 1; + type = MAILLIB::A_IMAP; + port = IMAP_PORT; +} + +QString IMAPaccount::getUniqueFileName() +{ + int num = 0; + QString unique; + + QDir dir( locateLocal("data", "kmicromail" ) ); + + QStringList imap = dir.entryList( "imap-*" ); + do { + unique.setNum( num++ ); + } while ( imap.contains( "imap-" + unique ) > 0 ); + + return unique; +} + +void IMAPaccount::read() +{ + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "IMAP Account" ); + accountName = conf->readEntry( "Account","" ); + if (accountName.isNull()) accountName = ""; + server = conf->readEntry( "Server","" ); + if (server.isNull()) server=""; + port = conf->readEntry( "Port","" ); + if (port.isNull()) port="143"; + connectionType = conf->readNumEntry( "ConnectionType" ); + ssl = conf->readBoolEntry( "SSL",false ); + user = conf->readEntry( "User","" ); + if (user.isNull()) user = ""; + password = conf->readEntryCrypt( "Password","" ); + if (password.isNull()) password = ""; + prefix = conf->readEntry("MailPrefix",""); + if (prefix.isNull()) prefix = ""; + offline = conf->readBoolEntry("Offline",false); + delete conf; +} + +void IMAPaccount::save() +{ + qDebug("saving %s ",getFileName().latin1() ); + Settings::checkDirectory(); + + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "IMAP Account" ); + conf->writeEntry( "Account", accountName ); + conf->writeEntry( "Server", server ); + conf->writeEntry( "Port", port ); + conf->writeEntry( "SSL", ssl ); + conf->writeEntry( "ConnectionType", connectionType ); + conf->writeEntry( "User", user ); + conf->writeEntryCrypt( "Password", password ); + conf->writeEntry( "MailPrefix",prefix); + conf->writeEntry( "Offline",offline); + conf->write(); + delete conf; +} + + +QString IMAPaccount::getFileName() +{ + return locateLocal("data", "kmicromail" ) +"/imap-" + file; +} + +POP3account::POP3account() + : Account() +{ + file = POP3account::getUniqueFileName(); + accountName = "New POP3 Account"; + ssl = false; + connectionType = 1; + type = MAILLIB::A_POP3; + port = POP3_PORT; +} + +POP3account::POP3account( QString filename ) + : Account() +{ + file = filename; + accountName = "New POP3 Account"; + ssl = false; + connectionType = 1; + type = MAILLIB::A_POP3; + port = POP3_PORT; +} + +QString POP3account::getUniqueFileName() +{ + int num = 0; + QString unique; + + QDir dir( locateLocal("data", "kmicromail" ) ); + + QStringList imap = dir.entryList( "pop3-*" ); + do { + unique.setNum( num++ ); + } while ( imap.contains( "pop3-" + unique ) > 0 ); + + return unique; +} + +void POP3account::read() +{ + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "POP3 Account" ); + accountName = conf->readEntry( "Account" ); + server = conf->readEntry( "Server" ); + port = conf->readEntry( "Port" ); + ssl = conf->readBoolEntry( "SSL" ); + connectionType = conf->readNumEntry( "ConnectionType" ); + user = conf->readEntry( "User" ); + password = conf->readEntryCrypt( "Password" ); + offline = conf->readBoolEntry("Offline",false); + delete conf; +} + +void POP3account::save() +{ + Settings::checkDirectory(); + + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "POP3 Account" ); + conf->writeEntry( "Account", accountName ); + conf->writeEntry( "Server", server ); + conf->writeEntry( "Port", port ); + conf->writeEntry( "SSL", ssl ); + conf->writeEntry( "ConnectionType", connectionType ); + conf->writeEntry( "User", user ); + conf->writeEntryCrypt( "Password", password ); + conf->writeEntry( "Offline",offline); + conf->write(); + delete conf; +} + + +QString POP3account::getFileName() +{ + return locateLocal("data", "kmicromail" ) +"/pop3-" + file; +} + +SMTPaccount::SMTPaccount() + : Account() +{ + file = SMTPaccount::getUniqueFileName(); + accountName = "New SMTP Account"; + ssl = false; + connectionType = 1; + login = false; + useCC = false; + useBCC = false; + useReply = false; + type = MAILLIB::A_SMTP; + port = SMTP_PORT; +} + +SMTPaccount::SMTPaccount( QString filename ) + : Account() +{ + file = filename; + accountName = "New SMTP Account"; + ssl = false; + connectionType = 1; + login = false; + type = MAILLIB::A_SMTP; + port = SMTP_PORT; +} + +QString SMTPaccount::getUniqueFileName() +{ + int num = 0; + QString unique; + + QDir dir( locateLocal("data", "kmicromail" ) ); + + QStringList imap = dir.entryList( "smtp-*" ); + do { + unique.setNum( num++ ); + } while ( imap.contains( "smtp-" + unique ) > 0 ); + + return unique; +} + +void SMTPaccount::read() +{ + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "SMTP Account" ); + accountName = conf->readEntry( "Account" ); + server = conf->readEntry( "Server" ); + port = conf->readEntry( "Port" ); + ssl = conf->readBoolEntry( "SSL" ); + connectionType = conf->readNumEntry( "ConnectionType" ); + login = conf->readBoolEntry( "Login" ); + user = conf->readEntry( "User" ); + password = conf->readEntryCrypt( "Password" ); + delete conf; +} + +void SMTPaccount::save() +{ + Settings::checkDirectory(); + + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "SMTP Account" ); + conf->writeEntry( "Account", accountName ); + conf->writeEntry( "Server", server ); + conf->writeEntry( "Port", port ); + conf->writeEntry( "SSL", ssl ); + conf->writeEntry( "ConnectionType", connectionType ); + conf->writeEntry( "Login", login ); + conf->writeEntry( "User", user ); + conf->writeEntryCrypt( "Password", password ); + conf->write(); + delete conf; +} + + +QString SMTPaccount::getFileName() +{ + return locateLocal("data", "kmicromail" ) +"/smtp-" + file; +} + +NNTPaccount::NNTPaccount() + : Account() +{ + file = NNTPaccount::getUniqueFileName(); + accountName = "New NNTP Account"; + ssl = false; + login = false; + type = MAILLIB::A_NNTP; + port = NNTP_PORT; +} + +NNTPaccount::NNTPaccount( QString filename ) + : Account() +{ + file = filename; + accountName = "New NNTP Account"; + ssl = false; + login = false; + type = MAILLIB::A_NNTP; + port = NNTP_PORT; +} + +QString NNTPaccount::getUniqueFileName() +{ + int num = 0; + QString unique; + + QDir dir( locateLocal("data", "kmicromail" ) ); + + QStringList imap = dir.entryList( "nntp-*" ); + do { + unique.setNum( num++ ); + } while ( imap.contains( "nntp-" + unique ) > 0 ); + + return unique; +} + +void NNTPaccount::read() +{ + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "NNTP Account" ); + accountName = conf->readEntry( "Account" ); + server = conf->readEntry( "Server" ); + port = conf->readEntry( "Port" ); + ssl = conf->readBoolEntry( "SSL" ); + login = conf->readBoolEntry( "Login" ); + user = conf->readEntry( "User" ); + password = conf->readEntryCrypt( "Password" ); + subscribedGroups = conf->readListEntry( "Subscribed", ',' ); + delete conf; +} + +void NNTPaccount::save() +{ + Settings::checkDirectory(); + + Config *conf = new Config( getFileName(), Config::File ); + conf->setGroup( "NNTP Account" ); + conf->writeEntry( "Account", accountName ); + conf->writeEntry( "Server", server ); + conf->writeEntry( "Port", port ); + conf->writeEntry( "SSL", ssl ); + conf->writeEntry( "Login", login ); + conf->writeEntry( "User", user ); + conf->writeEntryCrypt( "Password", password ); + conf->writeEntry( "Subscribed" , subscribedGroups, ',' ); + conf->write(); + delete conf; +} + + +QString NNTPaccount::getFileName() +{ + return locateLocal("data", "kmicromail" ) +"/nntp-" + file; +} diff --git a/kmicromail/libmailwrapper/settings.h b/kmicromail/libmailwrapper/settings.h new file mode 100644 index 0000000..ba3ec89 --- a/dev/null +++ b/kmicromail/libmailwrapper/settings.h @@ -0,0 +1,164 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "maildefines.h" + +/* OPIE */ + +/* QT */ +#include +#include + +class Account +{ + +public: + Account(); + virtual ~Account() {} + + void remove(); + void setAccountName( QString name ) { accountName = name; } + const QString&getAccountName()const{ return accountName; } + MAILLIB::ATYPE getType()const{ return type; } + + void setServer(const QString&str){ server = str; } + const QString&getServer()const{ return server; } + + void setPort(const QString&str) { port = str; } + const QString&getPort()const{ return port; } + + void setUser(const QString&str){ user = str; } + const QString&getUser()const{ return user; } + + void setPassword(const QString&str) { password = str; } + const QString&getPassword()const { return password; } + + void setSSL( bool b ) { ssl = b; } + bool getSSL() { return ssl; } + + void setConnectionType( int x ) { connectionType = x; } + int ConnectionType() { return connectionType; } + + + void setOffline(bool b) {offline = b;} + bool getOffline()const{return offline;} + + virtual QString getFileName() { return accountName; } + virtual void read() { ; } + virtual void save() { ; } + +protected: + QString accountName, server, port, user, password; + bool ssl; + int connectionType; + bool offline; + MAILLIB::ATYPE type; +}; + +class IMAPaccount : public Account +{ + +public: + IMAPaccount(); + IMAPaccount( QString filename ); + + static QString getUniqueFileName(); + + virtual void read(); + virtual void save(); + virtual QString getFileName(); + + void setPrefix(const QString&str) {prefix=str;} + const QString&getPrefix()const{return prefix;} + +private: + QString file,prefix; + +}; + +class POP3account : public Account +{ + +public: + POP3account(); + POP3account( QString filename ); + + static QString getUniqueFileName(); + + virtual void read(); + virtual void save(); + virtual QString getFileName(); + +private: + QString file; + +}; + +class SMTPaccount : public Account +{ + +public: + SMTPaccount(); + SMTPaccount( QString filename ); + + static QString getUniqueFileName(); + + virtual void read(); + virtual void save(); + virtual QString getFileName(); + + void setLogin( bool b ) { login = b; } + bool getLogin() { return login; } + +private: + QString file, name, mail, org, cc, bcc, reply, signature; + bool useCC, useBCC, useReply, login; + +}; + +class NNTPaccount : public Account +{ + +public: + NNTPaccount(); + NNTPaccount( QString filename ); + + static QString getUniqueFileName(); + + virtual void read(); + virtual void save(); + virtual QString getFileName(); + + void setLogin( bool b ) { login = b; } + bool getLogin() { return login; } + + void setGroups( QStringList list ) { subscribedGroups = list; } + QStringList getGroups() { return subscribedGroups; } + +private: + QString file; + bool login; + QStringList subscribedGroups; + +}; + +class Settings : public QObject +{ + Q_OBJECT + +public: + Settings(); + QList getAccounts(); + void addAccount(Account *account); + void delAccount(Account *account); + void saveAccounts(); + void readAccounts(); + static void checkDirectory(); + +private: + void updateAccounts(); + QList accounts; + +}; + +#endif diff --git a/kmicromail/libmailwrapper/smtpwrapper.cpp b/kmicromail/libmailwrapper/smtpwrapper.cpp new file mode 100644 index 0000000..04a21ea --- a/dev/null +++ b/kmicromail/libmailwrapper/smtpwrapper.cpp @@ -0,0 +1,458 @@ +#include "smtpwrapper.h" +#include "mailwrapper.h" +#include "abstractmail.h" +#include "logindialog.h" +#include "mailtypes.h" +#include "sendmailprogress.h" + +//#include +//#include +#include +#include +#include +#include +#include + +#include + + +using namespace Opie::Core; +progressMailSend*SMTPwrapper::sendProgress = 0; + +SMTPwrapper::SMTPwrapper(SMTPaccount * aSmtp ) + : Generatemail() +{ + m_SmtpAccount = aSmtp; + Config cfg( "mail" ); + cfg.setGroup( "Status" ); + m_queuedMail = cfg.readNumEntry( "outgoing", 0 ); + emit queuedMails( m_queuedMail ); + connect( this, SIGNAL( queuedMails(int) ), this, SLOT( emitQCop(int) ) ); + m_smtp = 0; +} + +SMTPwrapper::~SMTPwrapper() +{ + disc_server(); +} + +void SMTPwrapper::emitQCop( int queued ) { + QCopEnvelope env( "QPE/Pim", "outgoingMails(int)" ); + env << queued; +} + +QString SMTPwrapper::mailsmtpError( int errnum ) { + switch ( errnum ) { + case MAILSMTP_NO_ERROR: + return tr( "No error" ); + case MAILSMTP_ERROR_UNEXPECTED_CODE: + return tr( "Unexpected error code" ); + case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: + return tr( "Service not available" ); + case MAILSMTP_ERROR_STREAM: + return tr( "Stream error" ); + case MAILSMTP_ERROR_HOSTNAME: + return tr( "gethostname() failed" ); + case MAILSMTP_ERROR_NOT_IMPLEMENTED: + return tr( "Not implemented" ); + case MAILSMTP_ERROR_ACTION_NOT_TAKEN: + return tr( "Error, action not taken" ); + case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: + return tr( "Data exceeds storage allocation" ); + case MAILSMTP_ERROR_IN_PROCESSING: + return tr( "Error in processing" ); + case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: + return tr( "Starttls not supported" ); + // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: + // return tr( "Insufficient system storage" ); + case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: + return tr( "Mailbox unavailable" ); + case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: + return tr( "Mailbox name not allowed" ); + case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: + return tr( "Bad command sequence" ); + case MAILSMTP_ERROR_USER_NOT_LOCAL: + return tr( "User not local" ); + case MAILSMTP_ERROR_TRANSACTION_FAILED: + return tr( "Transaction failed" ); + case MAILSMTP_ERROR_MEMORY: + return tr( "Memory error" ); + case MAILSMTP_ERROR_CONNECTION_REFUSED: + return tr( "Connection refused" ); + default: + return tr( "Unknown error code" ); + } +} + + +void SMTPwrapper::progress( size_t current, size_t maximum ) { + if (SMTPwrapper::sendProgress) { + SMTPwrapper::sendProgress->setSingleMail(current, maximum ); + qApp->processEvents(); + } +} + +void SMTPwrapper::storeMail(const char*mail, size_t length, const QString&box) { + if (!mail) + return; + QString localfolders = AbstractMail::defaultLocalfolder(); + AbstractMail*wrap = AbstractMail::getWrapper(localfolders); + wrap->createMbox(box); + wrap->storeMessage(mail,length,box); + delete wrap; +} + +void SMTPwrapper::smtpSend( mailmime *mail,bool later) { + clist *rcpts = 0; + char *from, *data; + size_t size; + + from = data = 0; + + mailmessage * msg = 0; + msg = mime_message_init(mail); + mime_message_set_tmpdir(msg,getenv( "HOME" )); + int r = mailmessage_fetch(msg,&data,&size); + mime_message_detach_mime(msg); + mailmessage_free(msg); + if (r != MAIL_NO_ERROR || !data) { + if (data) + free(data); + ; // odebug << "Error fetching mime..." << oendl; + return; + } + msg = 0; + if (later) { + storeMail(data,size,"Outgoing"); + if (data) + free( data ); + Config cfg( "mail" ); + cfg.setGroup( "Status" ); + cfg.writeEntry( "outgoing", ++m_queuedMail ); + emit queuedMails( m_queuedMail ); + return; + } + from = getFrom( mail ); + rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); + smtpSend(from,rcpts,data,size); + if (data) { + free(data); + } + if (from) { + free(from); + } + if (rcpts) + smtp_address_list_free( rcpts ); +} + +void SMTPwrapper::storeFailedMail(const char*data,unsigned int size, const char*failuremessage) +{ + if (data) { + storeMail(data,size,"Sendfailed"); + } + if (failuremessage) { + QMessageBox::critical(0,tr("Error sending mail"), + tr("
%1
").arg(failuremessage)); + } +} + +int SMTPwrapper::start_smtp_tls() +{ + if (!m_smtp) { + return MAILSMTP_ERROR_IN_PROCESSING; + } + int err = mailesmtp_starttls(m_smtp); + if (err != MAILSMTP_NO_ERROR) return err; + mailstream_low * low; + mailstream_low * new_low; + low = mailstream_get_low(m_smtp->stream); + if (!low) { + return MAILSMTP_ERROR_IN_PROCESSING; + } + int fd = mailstream_low_get_fd(low); + if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) { + mailstream_low_free(low); + mailstream_set_low(m_smtp->stream, new_low); + } else { + return MAILSMTP_ERROR_IN_PROCESSING; + } + return err; +} + +void SMTPwrapper::connect_server() +{ + const char *server, *user, *pass; + bool ssl; + uint16_t port; + ssl = false; + bool try_tls = true; + bool force_tls=false; + server = user = pass = 0; + QString failuretext = ""; + + if (m_smtp || !m_SmtpAccount) { + return; + } + server = m_SmtpAccount->getServer().latin1(); + if ( m_SmtpAccount->ConnectionType() == 2 ) { + ssl = true; + try_tls = false; + } else if (m_SmtpAccount->ConnectionType() == 1) { + force_tls = true; + } + int result = 1; + port = m_SmtpAccount->getPort().toUInt(); + + m_smtp = mailsmtp_new( 20, &progress ); + if ( m_smtp == NULL ) { + /* no failure message cause this happens when problems with memory - than we + we can not display any messagebox */ + return; + } + + int err = MAILSMTP_NO_ERROR; + ; // odebug << "Servername " << server << " at port " << port << "" << oendl; + if ( ssl ) { + ; // odebug << "SSL session" << oendl; + err = mailsmtp_ssl_connect( m_smtp, server, port ); + } else { + ; // odebug << "No SSL session" << oendl; + err = mailsmtp_socket_connect( m_smtp, server, port ); + } + if ( err != MAILSMTP_NO_ERROR ) { + ; // odebug << "Error init connection" << oendl; + failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); + result = 0; + } + + /* switch to tls after init 'cause there it will send the ehlo */ + if (result) { + err = mailsmtp_init( m_smtp ); + if (err != MAILSMTP_NO_ERROR) { + result = 0; + failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); + } + } + + if (try_tls) { + err = start_smtp_tls(); + if (err != MAILSMTP_NO_ERROR) { + try_tls = false; + } else { + err = mailesmtp_ehlo(m_smtp); + } + } + + if (!try_tls && force_tls) { + result = 0; + failuretext = tr("Error init SMTP tls: %1").arg(mailsmtpError(err)); + } + + if (result==1 && m_SmtpAccount->getLogin() ) { + ; // odebug << "smtp with auth" << oendl; + if ( m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty() ) { + // get'em + LoginDialog login( m_SmtpAccount->getUser(), + m_SmtpAccount->getPassword(), NULL, 0, true ); + login.show(); + if ( QDialog::Accepted == login.exec() ) { + // ok + user = login.getUser().latin1(); + pass = login.getPassword().latin1(); + } else { + result = 0; + failuretext=tr("Login aborted - storing mail to localfolder"); + } + } else { + user = m_SmtpAccount->getUser().latin1(); + pass = m_SmtpAccount->getPassword().latin1(); + } + ; // odebug << "session->auth: " << m_smtp->auth << "" << oendl; + if (result) { + err = mailsmtp_auth( m_smtp, (char*)user, (char*)pass ); + if ( err == MAILSMTP_NO_ERROR ) { + ; // odebug << "auth ok" << oendl; + } else { + failuretext = tr("Authentification failed"); + result = 0; + } + } + } +} + +void SMTPwrapper::disc_server() +{ + if (m_smtp) { + mailsmtp_quit( m_smtp ); + mailsmtp_free( m_smtp ); + m_smtp = 0; + } +} + +int SMTPwrapper::smtpSend(char*from,clist*rcpts,const char*data,size_t size ) +{ + int err,result; + QString failuretext = ""; + + connect_server(); + + result = 1; + if (m_smtp) { + err = mailsmtp_send( m_smtp, from, rcpts, data, size ); + if ( err != MAILSMTP_NO_ERROR ) { + failuretext=tr("Error sending mail: %1").arg(mailsmtpError(err)); + result = 0; + } + } else { + result = 0; + } + + if (!result) { + storeFailedMail(data,size,failuretext); + } else { + ; // odebug << "Mail sent." << oendl; + storeMail(data,size,"Sent"); + } + return result; +} + +void SMTPwrapper::sendMail(const Opie::Core::OSmartPointer&mail,bool later ) +{ + mailmime * mimeMail; + + mimeMail = createMimeMail(mail ); + if ( mimeMail == NULL ) { + ; // odebug << "sendMail: error creating mime mail" << oendl; + } else { + sendProgress = new progressMailSend(); + sendProgress->show(); + sendProgress->setMaxMails(1); + smtpSend( mimeMail,later); + ; // odebug << "Clean up done" << oendl; + sendProgress->hide(); + delete sendProgress; + sendProgress = 0; + mailmime_free( mimeMail ); + } +} + +int SMTPwrapper::sendQueuedMail(AbstractMail*wrap,const RecMailP&which) { + size_t curTok = 0; + mailimf_fields *fields = 0; + mailimf_field*ffrom = 0; + clist *rcpts = 0; + char*from = 0; + int res = 0; + + encodedString * data = wrap->fetchRawBody(which); + if (!data) + return 0; + int err = mailimf_fields_parse( data->Content(), data->Length(), &curTok, &fields ); + if (err != MAILIMF_NO_ERROR) { + delete data; + delete wrap; + return 0; + } + + rcpts = createRcptList( fields ); + ffrom = getField(fields, MAILIMF_FIELD_FROM ); + from = getFrom(ffrom); + + if (rcpts && from) { + res = smtpSend(from,rcpts,data->Content(),data->Length()); + } + if (fields) { + mailimf_fields_free(fields); + fields = 0; + } + if (data) { + delete data; + } + if (from) { + free(from); + } + if (rcpts) { + smtp_address_list_free( rcpts ); + } + return res; +} + +/* this is a special fun */ +bool SMTPwrapper::flushOutbox() { + bool returnValue = true; + + ; // odebug << "Sending the queue" << oendl; + if (!m_SmtpAccount) { + ; // odebug << "No smtp account given" << oendl; + return false; + } + + bool reset_user_value = false; + QString localfolders = AbstractMail::defaultLocalfolder(); + AbstractMail*wrap = AbstractMail::getWrapper(localfolders); + if (!wrap) { + ; // odebug << "memory error" << oendl; + return false; + } + QString oldPw, oldUser; + QValueList mailsToSend; + QValueList mailsToRemove; + QString mbox("Outgoing"); + wrap->listMessages(mbox,mailsToSend); + if (mailsToSend.count()==0) { + delete wrap; + ; // odebug << "No mails to send" << oendl; + return false; + } + + oldPw = m_SmtpAccount->getPassword(); + oldUser = m_SmtpAccount->getUser(); + if (m_SmtpAccount->getLogin() && (m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty()) ) { + // get'em + QString user,pass; + LoginDialog login( m_SmtpAccount->getUser(), m_SmtpAccount->getPassword(), NULL, 0, true ); + login.show(); + if ( QDialog::Accepted == login.exec() ) { + // ok + user = login.getUser().latin1(); + pass = login.getPassword().latin1(); + reset_user_value = true; + m_SmtpAccount->setUser(user); + m_SmtpAccount->setPassword(pass); + } else { + return true; + } + } + + + sendProgress = new progressMailSend(); + sendProgress->show(); + sendProgress->setMaxMails(mailsToSend.count()); + + while (mailsToSend.count()>0) { + if (sendQueuedMail(wrap, (*mailsToSend.begin()))==0) { + QMessageBox::critical(0,tr("Error sending mail"), + tr("Error sending queued mail - breaking")); + returnValue = false; + break; + } + mailsToRemove.append((*mailsToSend.begin())); + mailsToSend.remove(mailsToSend.begin()); + sendProgress->setCurrentMails(mailsToRemove.count()); + } + if (reset_user_value) { + m_SmtpAccount->setUser(oldUser); + m_SmtpAccount->setPassword(oldPw); + } + Config cfg( "mail" ); + cfg.setGroup( "Status" ); + m_queuedMail = 0; + cfg.writeEntry( "outgoing", m_queuedMail ); + emit queuedMails( m_queuedMail ); + sendProgress->hide(); + delete sendProgress; + sendProgress = 0; + wrap->deleteMails(mbox,mailsToRemove); + delete wrap; + return returnValue; +} diff --git a/kmicromail/libmailwrapper/smtpwrapper.h b/kmicromail/libmailwrapper/smtpwrapper.h new file mode 100644 index 0000000..6c5bbe8 --- a/dev/null +++ b/kmicromail/libmailwrapper/smtpwrapper.h @@ -0,0 +1,63 @@ +// -*- Mode: C++; -*- +#ifndef SMTPwrapper_H +#define SMTPwrapper_H + +#include + +#include +#include +#include + +#include "settings.h" +#include "generatemail.h" + +#include + +class SMTPaccount; +class AbstractMail; + +class SMTPwrapper : public Generatemail +{ + Q_OBJECT + +public: + SMTPwrapper(SMTPaccount * aSmtp); + virtual ~SMTPwrapper(); + void sendMail(const Opie::Core::OSmartPointer& mail,bool later=false ); + bool flushOutbox(); + + static progressMailSend*sendProgress; + +signals: + void queuedMails( int ); + +protected: + mailsmtp *m_smtp; + SMTPaccount * m_SmtpAccount; + + void connect_server(); + void disc_server(); + int start_smtp_tls(); + + + void smtpSend( mailmime *mail,bool later); + + static void storeMail(const char*mail, size_t length, const QString&box); + static QString mailsmtpError( int err ); + static void progress( size_t current, size_t maximum ); + + int smtpSend(char*from,clist*rcpts,const char*data,size_t size); + + void storeMail(mailmime*mail, const QString&box); + + int sendQueuedMail(AbstractMail*wrap,const Opie::Core::OSmartPointer&which); + void storeFailedMail(const char*data,unsigned int size, const char*failuremessage); + + int m_queuedMail; + +protected slots: + void emitQCop( int queued ); + +}; + +#endif diff --git a/kmicromail/libmailwrapper/statusmail.cpp b/kmicromail/libmailwrapper/statusmail.cpp new file mode 100644 index 0000000..90c9233 --- a/dev/null +++ b/kmicromail/libmailwrapper/statusmail.cpp @@ -0,0 +1,94 @@ +#include "statusmail.h" + + + +using namespace Opie::Core; + +StatusMail::StatusMail(QList&list) +{ + currentImapStat.message_count=0; + currentImapStat.message_unseen=0; + currentImapStat.message_recent=0; + lastPop3Stat = currentImapStat; + currentPop3Stat = currentImapStat; + connectionList.setAutoDelete(true); + connectionList.clear(); + initAccounts(list); +} + +StatusMail::~StatusMail() +{ +} + +void StatusMail::initAccounts(QList&accounts) +{ + + Account *it; + folderStat currentStat; + AbstractMail * current = 0; + currentPop3Stat.message_count=0; + currentPop3Stat.message_recent=0; + currentPop3Stat.message_unseen=0; + for ( it = accounts.first(); it; it = accounts.next() ) { + if ( it->getType()==MAILLIB::A_IMAP && !it->getOffline() ) { + IMAPaccount*ima = static_cast(it); + current = AbstractMail::getWrapper(ima); + connectionList.append(current); + current->statusFolder(currentStat); + currentImapStat.message_count+=currentStat.message_unseen; + currentImapStat.message_count+=currentStat.message_recent; + currentImapStat.message_count+=currentStat.message_count; + } else if ( it->getType() == MAILLIB::A_POP3 && !it->getOffline() ) { + POP3account *pop3 = static_cast(it); + current = AbstractMail::getWrapper(pop3); + connectionList.append(current); + current->statusFolder(currentStat); + currentPop3Stat.message_count+=currentStat.message_count; + } + current->logout(); + } + ; // << "Pop3 init count: " << currentPop3Stat.message_count << "" << oendl; + currentPop3Stat.message_recent = currentPop3Stat.message_unseen = 0; + lastPop3Stat.message_unseen = currentPop3Stat.message_unseen; + lastPop3Stat.message_recent = currentPop3Stat.message_recent; + lastPop3Stat.message_count = currentPop3Stat.message_count; +} + +void StatusMail::reset_status() +{ + lastPop3Stat = currentPop3Stat; +} + +void StatusMail::check_current_stat(folderStat&targetStat) +{ + AbstractMail*it = 0; + folderStat currentStat; + currentPop3Stat.message_recent = 0; + currentPop3Stat.message_count = 0; + currentPop3Stat.message_unseen = 0; + currentImapStat = currentPop3Stat; + for ( it = connectionList.first(); it; it = connectionList.next() ) { + it->statusFolder(currentStat); + it->logout(); + if (it->getType() == MAILLIB::A_IMAP) { + currentImapStat.message_unseen+=currentStat.message_unseen; + currentImapStat.message_recent+=currentStat.message_recent; + currentImapStat.message_count+=currentStat.message_count; + } else if (it->getType() == MAILLIB::A_POP3) { + currentPop3Stat.message_count+=currentStat.message_count; + ; // << "Pop3 count: " << currentPop3Stat.message_count << "" << oendl; + } + } + ; // << "Pop3 last: " << lastPop3Stat.message_count << "" << oendl; + if (currentPop3Stat.message_count > lastPop3Stat.message_count) { + currentPop3Stat.message_recent = currentPop3Stat.message_count - lastPop3Stat.message_count; + currentPop3Stat.message_unseen = currentPop3Stat.message_recent; + } else { + lastPop3Stat.message_count = currentPop3Stat.message_count; + currentPop3Stat.message_recent = currentPop3Stat.message_unseen = 0; + } + targetStat = currentImapStat; + targetStat.message_unseen+=currentPop3Stat.message_unseen; + targetStat.message_recent+=currentPop3Stat.message_recent; + targetStat.message_count+=currentPop3Stat.message_count; +} diff --git a/kmicromail/libmailwrapper/statusmail.h b/kmicromail/libmailwrapper/statusmail.h new file mode 100644 index 0000000..2637232 --- a/dev/null +++ b/kmicromail/libmailwrapper/statusmail.h @@ -0,0 +1,31 @@ +#ifndef __MAIL_STATUS_H +#define __MAIL_STATUS_H + +#include "settings.h" +#include "abstractmail.h" +#include "mailtypes.h" + +class StatusMail +{ +public: + StatusMail(QList&list); + virtual ~StatusMail(); + + /* this should be called if opiemail is starte or a mailbox touched - may be trough + a qcop signal or if tab on the taskbar applet*/ + virtual void reset_status(); + virtual void check_current_stat(folderStat&targetStat); + +protected: + void initAccounts(QList&accounts); + /* this must be cause we have to calculate the recent for pop3*/ + folderStat currentImapStat; + /* currentPop3Stat is the sum of messages in POP3 accounts in CURRENT loop + the recent are calculated to the difference of the LAST loop */ + folderStat currentPop3Stat; + /* lastPop3Stat is the sum of messages in LAST loop */ + folderStat lastPop3Stat; + QList connectionList; +}; + +#endif diff --git a/kmicromail/libmailwrapper/storemail.cpp b/kmicromail/libmailwrapper/storemail.cpp new file mode 100644 index 0000000..ed1d44a --- a/dev/null +++ b/kmicromail/libmailwrapper/storemail.cpp @@ -0,0 +1,90 @@ +#include "storemail.h" +#include "mailwrapper.h" +#include "settings.h" +#include "abstractmail.h" + +#include +#include + +#include + +using namespace Opie::Core; +Storemail::Storemail(Account*aAccount,const QString&aFolder) + : Generatemail() +{ + wrapper = 0; + m_Account = aAccount; + m_tfolder = aFolder; + wrapper = AbstractMail::getWrapper(m_Account); + if (wrapper) { + wrapper->createMbox(m_tfolder); + } +} + +Storemail::Storemail(const QString&dir,const QString&aFolder) + : Generatemail() +{ + wrapper = 0; + m_Account = 0; + m_tfolder = aFolder; + wrapper = AbstractMail::getWrapper(dir); + if (wrapper) { + wrapper->createMbox(m_tfolder); + } +} + +Storemail::Storemail(const QString&aFolder) + : Generatemail() +{ + wrapper = 0; + m_Account = 0; + m_tfolder = aFolder; + wrapper = AbstractMail::getWrapper(AbstractMail::defaultLocalfolder()); + if (wrapper) { + wrapper->createMbox(m_tfolder); + } +} + +Storemail::~Storemail() +{ +} + +int Storemail::storeMail(const Opie::Core::OSmartPointer&mail) +{ + if (!wrapper) return 0; + int ret = 1; + + mailmime * mimeMail = 0; + mimeMail = createMimeMail(mail ); + if ( mimeMail == NULL ) { + qDebug("storeMail: error creating mime mail "); + return 0; + } + char *data; + size_t size; + data = 0; + + mailmessage * msg = 0; + msg = mime_message_init(mimeMail); + mime_message_set_tmpdir(msg,getenv( "HOME" )); + int r = mailmessage_fetch(msg,&data,&size); + mime_message_detach_mime(msg); + mailmessage_free(msg); + msg = 0; + if (r != MAIL_NO_ERROR || !data) { + qDebug("Error fetching mime... "); + ret = 0; + } + + if (ret) { + wrapper->storeMessage(data,size,m_tfolder); + } + + if (data) { + free(data); + } + if (mimeMail) { + mailmime_free( mimeMail ); + } + return ret; +} diff --git a/kmicromail/libmailwrapper/storemail.h b/kmicromail/libmailwrapper/storemail.h new file mode 100644 index 0000000..4433de0 --- a/dev/null +++ b/kmicromail/libmailwrapper/storemail.h @@ -0,0 +1,29 @@ +#ifndef __STORE_MAIL_H +#define __STORE_MAIL_H + +#include + +#include "generatemail.h" + +class Account; +class Mail; +class AbstractMail; + +class Storemail : public Generatemail +{ + Q_OBJECT +public: + Storemail(Account*aAccount,const QString&aFolder); + Storemail(const QString&dir,const QString&aFolder); + Storemail(const QString&aFolder); + virtual ~Storemail(); + + int storeMail(const Opie::Core::OSmartPointer&mail); + +protected: + Account* m_Account; + QString m_tfolder; + AbstractMail*wrapper; +}; + +#endif diff --git a/kmicromail/mailistviewitem.cpp b/kmicromail/mailistviewitem.cpp new file mode 100644 index 0000000..6073da6 --- a/dev/null +++ b/kmicromail/mailistviewitem.cpp @@ -0,0 +1,115 @@ +#include "mailistviewitem.h" +#include +#include +#include +//#include + +MailListViewItem::MailListViewItem(QListView * parent, MailListViewItem * item ) + :QListViewItem(parent,item),mail_data() +{ +} + +void MailListViewItem::showEntry() +{ + if ( mail_data->getFlags().testBit( FLAG_ANSWERED ) == true) { + setPixmap( 0, SmallIcon ( "kmmsgreplied") ); + } else if ( mail_data->getFlags().testBit( FLAG_SEEN ) == true ) { + /* I think it looks nicer if there are not such a log of icons but only on mails + replied or new - Alwin*/ + //setPixmap( 0,SmallIcon ("kmmsgunseen") ); + } else { + setPixmap( 0,SmallIcon ( "kmmsgnew") ); + } + double s = mail_data->Msgsize(); + int w; + w=0; + + while (s>1024) { + s/=1024; + ++w; + if (w>=2) break; + } + + QString q=""; + QString fsize=""; + switch(w) { + case 1: + q="k"; + break; + case 2: + q="M"; + break; + default: + break; + } + + { + QTextOStream o(&fsize); + if (w>0) o.precision(2); else o.precision(0); + o.setf(QTextStream::fixed); + o << s << " " << q << "Byte"; + } + + setText(1,mail_data->getSubject()); + setText(2,mail_data->getFrom()); + setText(3,fsize); + QString date = mail_data->getDate(); + + int kom = date.find( ",")+2; + if ( kom == 1 ) + kom = 0; + if ( date.mid(kom,1) == " ") + ++kom; + if ( date.mid(kom+1,1) == " " ) + date = "0" + date.mid( kom ); + else if ( kom ) + date = date.mid( kom ); + if ( kom || date.mid(2,1 ) == " ") { + QString mon = date.mid(3,3); + QString so = 00; + if ( mon == "Jan" ) + so = "01"; + else if ( mon == "Feb" ) + so = "02"; + else if ( mon == "Mar" ) + so = "03"; + else if ( mon == "Apr" ) + so = "04"; + else if ( mon == "May" ) + so = "05"; + else if ( mon == "Jun" ) + so = "06"; + else if ( mon == "Jul" ) + so = "07"; + else if ( mon == "Aug" ) + so = "08"; + else if ( mon == "Sep" ) + so = "09"; + else if ( mon == "Oct" ) + so = "10"; + else if ( mon == "Nov" ) + so = "11"; + else if ( mon == "Dec" ) + so = "12"; + date = date.mid(7,4)+"-"+so+"-"+date.left(2)+"-"+date.mid(12); + } + // if ( date.left(1) != "1" || date.left(1) != "2" ) + // date = date.mid(5); + setText(4,date); +} + +void MailListViewItem::storeData(const RecMailP&data) +{ + mail_data = data; +} + +const RecMailP& MailListViewItem::data()const +{ + return mail_data; +} + +MAILLIB::ATYPE MailListViewItem::wrapperType() +{ + if (!mail_data->Wrapper()) return MAILLIB::A_UNDEFINED; + return mail_data->Wrapper()->getType(); +} diff --git a/kmicromail/mailistviewitem.h b/kmicromail/mailistviewitem.h new file mode 100644 index 0000000..d953d83 --- a/dev/null +++ b/kmicromail/mailistviewitem.h @@ -0,0 +1,23 @@ +#ifndef __MAILLISTVIEWITEM_H +#define __MAILLISTVIEWITEM_H + +#include +#include +#include + +class MailListViewItem:public QListViewItem +{ +public: + MailListViewItem(QListView * parent, MailListViewItem * after ); + virtual ~MailListViewItem(){} + + void storeData(const RecMailP&data); + const RecMailP&data()const; + void showEntry(); + MAILLIB::ATYPE wrapperType(); + +protected: + RecMailP mail_data; +}; + +#endif diff --git a/kmicromail/main.cpp b/kmicromail/main.cpp new file mode 100644 index 0000000..f2879e8 --- a/dev/null +++ b/kmicromail/main.cpp @@ -0,0 +1,55 @@ + +#ifndef DESKTOP_VERSION +#include +#include +#else +#include +#include +#include +#include +#include +#endif +#include "opiemail.h" +#include +#include +#include +#include +#include "mainwindow.h" + +using namespace Opie::Core; +int main( int argc, char **argv ) { + +#ifndef DESKTOP_VERSION + QPEApplication a( argc, argv ); + a.setKeepRunning (); +#else + QApplication a( argc, argv ); + QApplication::setStyle( new QPlatinumStyle ()); +#endif + + KGlobal::setAppName( "kmicromail" ); + QString fileName ; +#ifndef DESKTOP_VERSION + fileName = getenv("QPEDIR"); + KGlobal::iconLoader()->setIconPath( fileName +"/pics/kdepim/kmicromail/"); +#else + fileName = qApp->applicationDirPath () + "/kdepim/kmicromail/"; + KGlobal::iconLoader()->setIconPath(QDir::convertSeparators(fileName)); +#endif + KStandardDirs::setAppDir( QDir::convertSeparators(locateLocal("data", "kmicromail"))); + OpieMail* mw = new OpieMail(); +#ifndef DESKTOP_VERSION + //qDebug("CONNECT "); + QObject::connect( &a, SIGNAL (appMessage ( const QCString &, const QByteArray & )),mw, SLOT(message( const QCString&, const QByteArray& ))); + a.showMainWidget(mw ); +#else + a.setMainWidget(mw ); + m.show(); + //m.resize( 800, 600 ); +#endif + QObject::connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); + int rv = a.exec(); + delete mw; + return rv; + +} diff --git a/kmicromail/mainwindow.cpp b/kmicromail/mainwindow.cpp new file mode 100644 index 0000000..78377ea --- a/dev/null +++ b/kmicromail/mainwindow.cpp @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include +#include + +#ifndef DESKTOP_VERSION +#include +#endif +#include "defines.h" +#include "mainwindow.h" +#include + + +#include + +MainWindow::MainWindow( QWidget *parent, const char *name, WFlags flags ) + : QMainWindow( parent, name, flags ) +{ + setCaption( tr( "KMicroMail" ) ); + setToolBarsMovable( false ); + KABC::StdAddressBook::self(); + toolBar = new QToolBar( this ); + menuBar = new QMenuBar( toolBar ); + mailMenu = new QPopupMenu( menuBar ); + menuBar->insertItem( tr( "Mail" ), mailMenu ); + settingsMenu = new QPopupMenu( menuBar ); + menuBar->insertItem( tr( "Settings" ), settingsMenu ); + + addToolBar( toolBar ); + toolBar->setHorizontalStretchable( true ); + + QLabel *spacer = new QLabel( toolBar ); + spacer->setBackgroundMode( QWidget::PaletteButton ); + toolBar->setStretchableWidget( spacer ); + + composeMail = new QAction( tr( "Compose new mail" ), SmallIcon("composemail"), + 0, 0, this ); + composeMail->addTo( toolBar ); + composeMail->addTo( mailMenu ); + + sendQueued = new QAction( tr( "Send queued mails" ), SmallIcon("sendqueued") , + 0, 0, this ); + sendQueued->addTo( toolBar ); + sendQueued->addTo( mailMenu ); + + /* + syncFolders = new QAction( tr( "Sync mailfolders" ), ICON_SYNC, + 0, 0, this ); + syncFolders->addTo( toolBar ); + syncFolders->addTo( mailMenu ); + */ + + showFolders = new QAction( tr( "Show/Hide folders" ), SmallIcon("showfolders") , + 0, 0, this, 0, true ); + showFolders->addTo( toolBar ); + showFolders->addTo( mailMenu ); + showFolders->setOn( true ); + connect(showFolders, SIGNAL( toggled(bool) ), + SLOT( slotShowFolders(bool) ) ); + + /* + searchMails = new QAction( tr( "Search mails" ), SmallIcon("find") ), + 0, 0, this ); + searchMails->addTo( toolBar ); + searchMails->addTo( mailMenu ); + */ + + deleteMails = new QAction(tr("Delete Mail"), SmallIcon("trash"), 0, 0, this); + deleteMails->addTo( toolBar ); + deleteMails->addTo( mailMenu ); + connect( deleteMails, SIGNAL( activated() ), + SLOT( slotDeleteMail() ) ); + + editSettings = new QAction( tr( "Edit settings" ), SmallIcon("SettingsIcon") , + 0, 0, this ); + editSettings->addTo( settingsMenu ); + connect( editSettings, SIGNAL( activated() ), + SLOT( slotEditSettings() ) ); + editAccounts = new QAction( tr( "Configure accounts" ), SmallIcon("editaccounts") , + 0, 0, this ); + editAccounts->addTo( settingsMenu ); + + //setCentralWidget( view ); + + QVBox* wrapperBox = new QVBox( this ); + setCentralWidget( wrapperBox ); + + // QWidget *view = new QWidget( wrapperBox ); + KDGanttMinimizeSplitter* split = new KDGanttMinimizeSplitter( Qt::Horizontal, wrapperBox); + split->setMinimizeDirection( KDGanttMinimizeSplitter::Left); + //layout = new QBoxLayout ( split, QBoxLayout::LeftToRight ); + + folderView = new AccountView( split ); + folderView->header()->hide(); + folderView->setRootIsDecorated( true ); + folderView->addColumn( tr( "Mailbox" ) ); + + //layout->addWidget( folderView ); + + mailView = new QListView( split ); + mailView->addColumn( tr( "" ) ); + mailView->addColumn( tr( "Subject" ),QListView::Manual ); + mailView->addColumn( tr( "Sender" ),QListView::Manual ); + mailView->addColumn( tr( "Size" ),QListView::Manual); + mailView->addColumn( tr( "Date" )); + mailView->setAllColumnsShowFocus(true); + //mailView->setSorting(-1); + + statusWidget = new StatusWidget( wrapperBox ); + statusWidget->hide(); + + //layout->addWidget( mailView ); + //layout->setStretchFactor( folderView, 1 ); + //layout->setStretchFactor( mailView, 2 ); + + slotAdjustLayout(); +#ifndef DESKTOP_VERSION + QPEApplication::setStylusOperation( mailView->viewport(),QPEApplication::RightOnHold); + QPEApplication::setStylusOperation( folderView->viewport(),QPEApplication::RightOnHold); +#endif + connect( mailView, SIGNAL( doubleClicked (QListViewItem* )),this, + SLOT( mailLeftClicked(QListViewItem*) ) ); + connect( mailView, SIGNAL( returnPressed (QListViewItem* )),this, + SLOT( mailLeftClicked(QListViewItem*) ) ); + connect( mailView, SIGNAL( mouseButtonPressed(int,QListViewItem*,const QPoint&,int) ),this, + SLOT( mailHold(int,QListViewItem*,const QPoint&,int) ) ); + connect(folderView, SIGNAL(refreshMailview(const QValueList&)), + this,SLOT(refreshMailView(const QValueList&))); + connect( composeMail, SIGNAL( activated() ), SLOT( slotComposeMail() ) ); + connect( sendQueued, SIGNAL( activated() ), SLOT( slotSendQueued() ) ); +// connect( searchMails, SIGNAL( activated() ), SLOT( slotSearchMails() ) ); + connect( editAccounts, SIGNAL( activated() ), SLOT( slotEditAccounts() ) ); + mailView->setMultiSelection ( true ); + //mailView->setSelectionMode( QListView::Extended ); + QValueList list; + int fw = 100; + if ( QApplication::desktop()->width() > 320 ) + fw = 50; + list.append( fw ); + list.append( 100 ); + split->setSizes( list ); + QTimer::singleShot( 1000, this, SLOT( slotAdjustColumns() ) ); + mailView->setShowSortIndicator ( true ); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::appMessage(const QCString &, const QByteArray &) +{ + qDebug("appMessage implemented by subclass"); +} + +void MainWindow::slotAdjustLayout() { + + /* + QWidget *d = QApplication::desktop(); + + if ( d->width() < d->height() ) { + layout->setDirection( QBoxLayout::TopToBottom ); + } else { + layout->setDirection( QBoxLayout::LeftToRight ); + } + */ +} + +void MainWindow::slotAdjustColumns() +{ + bool hidden = folderView->isHidden(); + if ( hidden ) folderView->show(); + folderView->setColumnWidth( 0, folderView->visibleWidth() ); + if ( hidden ) folderView->hide(); + + mailView->setColumnWidth( 0, 10 ); + mailView->setColumnWidth( 1, mailView->visibleWidth() - 130 ); + mailView->setColumnWidth( 2, 80 ); + mailView->setColumnWidth( 3, 50 ); + mailView->setColumnWidth( 4, 50 ); +} + +void MainWindow::slotEditSettings() +{ +} + +void MainWindow::slotShowFolders( bool ) +{ + qDebug("not implemented: "); +} + +void MainWindow::refreshMailView(const QValueList&) +{ + qDebug("not implemented: "); +} + +void MainWindow::mailLeftClicked(QListViewItem * ) +{ + qDebug("not implemented: "); +} + +void MainWindow::displayMail() +{ + qDebug("not implemented: "); +} + +void MainWindow::slotDeleteMail() +{ + qDebug("not implemented: "); +} + +void MainWindow::mailHold(int, QListViewItem *,const QPoint&,int ) +{ + qDebug("not implemented: "); +} + +void MainWindow::slotSendQueued() +{ + qDebug("not implemented: "); +} + +void MainWindow::slotEditAccounts() +{ + qDebug("not implemented: "); +} + +void MainWindow::slotComposeMail() +{ + qDebug("not implemented: "); +} diff --git a/kmicromail/mainwindow.h b/kmicromail/mainwindow.h new file mode 100644 index 0000000..0cb252c --- a/dev/null +++ b/kmicromail/mainwindow.h @@ -0,0 +1,56 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include + +#include +#include + +#include "accountview.h" +#include "statuswidget.h" + +#include +#include + +class RecMail; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow( QWidget *parent = 0, const char *name = 0, WFlags flags = 0 ); + virtual ~MainWindow(); + +public slots: + virtual void slotAdjustColumns(); + virtual void appMessage(const QCString &msg, const QByteArray &data); + virtual void slotComposeMail(); + +protected slots: + virtual void slotSendQueued(); + virtual void slotEditAccounts(); + virtual void slotShowFolders( bool show ); + virtual void refreshMailView(const QValueList&); + virtual void displayMail(); + virtual void slotDeleteMail(); + virtual void mailHold(int, QListViewItem *,const QPoint&,int); + virtual void slotAdjustLayout(); + virtual void slotEditSettings(); + virtual void mailLeftClicked( QListViewItem * ); + +protected: + QToolBar *toolBar; + StatusWidget *statusWidget; + QMenuBar *menuBar; + QPopupMenu *mailMenu, *settingsMenu; + QAction *composeMail, *sendQueued, *showFolders, *searchMails, *deleteMails, + *editSettings, *editAccounts, *syncFolders; + AccountView *folderView; + QListView *mailView; + //QBoxLayout *layout; +}; + +#endif diff --git a/kmicromail/newmaildir.cpp b/kmicromail/newmaildir.cpp new file mode 100644 index 0000000..e6e9dc7 --- a/dev/null +++ b/kmicromail/newmaildir.cpp @@ -0,0 +1,36 @@ +#include "newmaildir.h" +#include +#include + +Newmdirdlg::Newmdirdlg( QWidget* parent, const char* name,bool no_sub) + : Newmdirdlgui(parent,name,true),ndir(""),possible_subs(false) +{ + if (no_sub) { + subdirsPossibleBox->setChecked(false); + subdirsPossibleBox->hide(); + } +} + +Newmdirdlg::~Newmdirdlg() +{ +} + +void Newmdirdlg::accept() +{ + ndir = dirnameEdit->text(); + possible_subs = subdirsPossibleBox->isChecked(); + if (ndir.isEmpty()) { + return; + } + Newmdirdlgui::accept(); +} + +const QString&Newmdirdlg::Newdir()const +{ + return ndir; +} + +const bool Newmdirdlg::subpossible()const +{ + return possible_subs; +} diff --git a/kmicromail/newmaildir.h b/kmicromail/newmaildir.h new file mode 100644 index 0000000..496eaf4 --- a/dev/null +++ b/kmicromail/newmaildir.h @@ -0,0 +1,20 @@ +#include "newmaildirui.h" +#include + +class Newmdirdlg : public Newmdirdlgui +{ + Q_OBJECT +public: + Newmdirdlg( QWidget* parent = 0, const char* name = 0,bool no_sub=false); + ~Newmdirdlg(); + + const QString&Newdir()const; + const bool subpossible()const; + +protected slots: + virtual void accept(); + +protected: + QString ndir; + bool possible_subs; +}; diff --git a/kmicromail/newmaildirui.ui b/kmicromail/newmaildirui.ui new file mode 100644 index 0000000..72b2d04 --- a/dev/null +++ b/kmicromail/newmaildirui.ui @@ -0,0 +1,100 @@ + +Newmdirdlgui + + QDialog + + name + newmdirdlg + + + geometry + + 0 + 0 + 223 + 110 + + + + caption + Enter directory name + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout5 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + dirnameLabel + + + text + Directory name: + + + + QLineEdit + + name + dirnameEdit + + + + + + QCheckBox + + name + subdirsPossibleBox + + + text + Directory contains other subdirs + + + + + name + Spacer4 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + diff --git a/kmicromail/nntpconfigui.ui b/kmicromail/nntpconfigui.ui new file mode 100644 index 0000000..25d564e --- a/dev/null +++ b/kmicromail/nntpconfigui.ui @@ -0,0 +1,344 @@ + +NNTPconfigUI + + QDialog + + name + NNTPconfigUI + + + geometry + + 0 + 0 + 409 + 520 + + + + caption + Configure NNTP + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QTabWidget + + name + TabWidget2 + + + layoutMargin + + + layoutSpacing + + + QWidget + + name + tab + + + title + Account + + + + margin + 3 + + + spacing + 3 + + + QLineEdit + + name + serverLine + + + + QLabel + + name + portLabel + + + text + Port + + + + QLineEdit + + name + portLine + + + + QLineEdit + + name + accountLine + + + toolTip + Name of the Account + + + + QLabel + + name + accountLabel + + + text + Account + + + + QLabel + + name + serverLabel + + + enabled + true + + + caption + + + + text + Server + + + layoutMargin + + + layoutSpacing + + + + Line + + name + line1 + + + caption + + + + orientation + Horizontal + + + layoutMargin + + + layoutSpacing + + + + QCheckBox + + name + sslBox + + + text + Use SSL + + + + Line + + name + line2 + + + enabled + true + + + caption + + + + orientation + Horizontal + + + layoutMargin + + + layoutSpacing + + + + QLabel + + name + userLabel + + + text + User + + + + QLabel + + name + passLabel + + + text + Password + + + + + name + spacer + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QCheckBox + + name + loginBox + + + text + Use Login + + + + QLineEdit + + name + userLine + + + enabled + false + + + + QLineEdit + + name + passLine + + + enabled + false + + + echoMode + Password + + + + + + QWidget + + name + tab + + + title + Groups + + + + margin + 3 + + + spacing + 3 + + + QListView + + + text + Newsgroup + + + clickable + true + + + resizeable + true + + + + name + ListViewGroups + + + + QPushButton + + name + GetNGButton + + + text + Get newsgroup list from server + + + + + + + + + accountLine + serverLine + portLine + sslBox + loginBox + userLine + passLine + + diff --git a/kmicromail/nntpgroups.cpp b/kmicromail/nntpgroups.cpp new file mode 100644 index 0000000..c729f79 --- a/dev/null +++ b/kmicromail/nntpgroups.cpp @@ -0,0 +1,62 @@ +#include "nntpgroups.h" + +#include +#include +#include + +using namespace Opie::Core; + +NNTPGroups::NNTPGroups(NNTPaccount *account, QWidget* parent, const char* name, WFlags fl) + : NNTPGroupsUI(parent,name,fl),subscribedGroups() +{ + m_Account = account; + fillGroups(); +} + +NNTPGroups::~NNTPGroups() +{ + +} + +void NNTPGroups::slotGetNG() +{ + if (!m_Account) return; + GroupListView->clear(); + NNTPwrapper tmp( m_Account ); + QString filter = Groupfilteredit->text(); + QStringList list = tmp.listAllNewsgroups(filter); + subscribedGroupsNotListed = subscribedGroups; + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + QCheckListItem *item; + item = new QCheckListItem( GroupListView, (*it), QCheckListItem::CheckBox ); + if ( subscribedGroups.contains( (*it) ) >= 1 ) { + item->setOn( true ); + subscribedGroupsNotListed.remove((*it)); + } + } +} + +void NNTPGroups::fillGroups() +{ + if (!m_Account) return; + subscribedGroups = m_Account->getGroups(); + for ( QStringList::Iterator it = subscribedGroups.begin(); it != subscribedGroups.end(); ++it ) { + QCheckListItem *item; + item = new QCheckListItem( GroupListView, (*it), QCheckListItem::CheckBox ); + item->setOn( true ); + } +} + +void NNTPGroups::storeValues() +{ + if (!m_Account) return; + QListViewItemIterator list_it( GroupListView ); + subscribedGroups.clear(); + for ( ; list_it.current(); ++list_it ) { + if ( ( (QCheckListItem*)list_it.current() )->isOn() ) { + subscribedGroups.append( list_it.current()->text(0) ); + } + } + subscribedGroups+=subscribedGroupsNotListed; + m_Account->setGroups( subscribedGroups ); +} diff --git a/kmicromail/nntpgroups.h b/kmicromail/nntpgroups.h new file mode 100644 index 0000000..e5b7c35 --- a/dev/null +++ b/kmicromail/nntpgroups.h @@ -0,0 +1,33 @@ +#ifndef __NNTPGROUPS_WINDOW__ +#define __NNTPGROUPS_WINDOW__ + +#include "nntpgroupsui.h" + +#include + +class NNTPaccount; +class QStringList; + +class NNTPGroups:public NNTPGroupsUI +{ + Q_OBJECT +public: + NNTPGroups(NNTPaccount *account, QWidget* parent = 0, const char* name = 0, WFlags fl = 0); + virtual ~NNTPGroups(); + /* must be called from external. + * it will store the new subscription list into the account + * but don't save them, this must be done by the calling class. + */ + void storeValues(); + +protected slots: + virtual void slotGetNG(); + +protected: + virtual void fillGroups(); + + NNTPaccount*m_Account; + QStringList subscribedGroups,subscribedGroupsNotListed; +}; + +#endif diff --git a/kmicromail/nntpgroupsdlg.cpp b/kmicromail/nntpgroupsdlg.cpp new file mode 100644 index 0000000..c94d9fa --- a/dev/null +++ b/kmicromail/nntpgroupsdlg.cpp @@ -0,0 +1,29 @@ +#include "nntpgroupsdlg.h" +#include "nntpgroups.h" + +#include + +#include + +NNTPGroupsDlg::NNTPGroupsDlg(NNTPaccount *account,QWidget * parent, const char * name) + : QDialog(parent,name,true,WStyle_ContextHelp) +{ + setCaption(tr("Subscribed newsgroups")); + m_Account = account; + QVBoxLayout*dlglayout = new QVBoxLayout(this); + dlglayout->setSpacing(2); + dlglayout->setMargin(1); + groupsWidget = new NNTPGroups(account,this); + dlglayout->addWidget(groupsWidget); +} + +NNTPGroupsDlg::~NNTPGroupsDlg() +{ +} + +void NNTPGroupsDlg::accept() +{ + groupsWidget->storeValues(); + m_Account->save(); + QDialog::accept(); +} diff --git a/kmicromail/nntpgroupsdlg.h b/kmicromail/nntpgroupsdlg.h new file mode 100644 index 0000000..a21bac7 --- a/dev/null +++ b/kmicromail/nntpgroupsdlg.h @@ -0,0 +1,24 @@ +#ifndef __NNTP_GROUP_DLG_H +#define __NNTP_GROUP_DLG_H + +#include + +class NNTPGroups; +class NNTPaccount; + +class NNTPGroupsDlg : public QDialog +{ + Q_OBJECT +public: + NNTPGroupsDlg(NNTPaccount *account,QWidget * parent=0, const char * name=0); + virtual ~NNTPGroupsDlg(); + +protected: + NNTPGroups*groupsWidget; + NNTPaccount*m_Account; + +protected slots: + virtual void accept (); +}; + +#endif diff --git a/kmicromail/nntpgroupsui.ui b/kmicromail/nntpgroupsui.ui new file mode 100644 index 0000000..2902731 --- a/dev/null +++ b/kmicromail/nntpgroupsui.ui @@ -0,0 +1,129 @@ + +NNTPGroupsUI + + QWidget + + name + NNTPGroupsUI + + + geometry + + 0 + 0 + 254 + 330 + + + + caption + newsgroupslist + + + layoutMargin + + + layoutSpacing + + + + margin + 1 + + + spacing + 1 + + + QListView + + + text + Newsgroups + + + clickable + true + + + resizeable + true + + + + name + GroupListView + + + whatsThis + List of groups from the server. On start, only subscribed groups are listed. + + + + QLayoutWidget + + name + Layout1 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + filterlabel + + + text + Groupfilter: + + + + QLineEdit + + name + Groupfilteredit + + + whatsThis + Enter a filter string here. +Then hit "get newsgroup list" again and only groups starting +with that filter will be listet. + + + + + + QPushButton + + name + GetNGButton + + + text + Get newsgroup list from server + + + whatsThis + Retrieve the list of groups from server + + + + + + + GetNGButton + clicked() + NNTPGroupsUI + slotGetNG() + + slotGetNG() + + diff --git a/kmicromail/opie-mail.control b/kmicromail/opie-mail.control new file mode 100644 index 0000000..71fd0f2 --- a/dev/null +++ b/kmicromail/opie-mail.control @@ -0,0 +1,10 @@ +Package: opie-mail +Files: plugins/application/libopiemail.so* bin/opiemail apps/1Pim/mail.desktop pics/mail/*.png +Priority: optional +Section: opie/pim +Maintainer: Rajko Albrecht , Juergen Graf , Maximilian Reiß +Architecture: arm +Version: 0.6-$SUB_VERSION +Depends: task-opie-minimal, libopiecore2, libopieui2, libopiemm2, libopiedb2, libmailwrapper (>= 0.6) +Description: Opie's mail and news client (POP3, IMAP and NNTP) +License: LGPL diff --git a/kmicromail/opiemail.cpp b/kmicromail/opiemail.cpp new file mode 100644 index 0000000..b1992ec --- a/dev/null +++ b/kmicromail/opiemail.cpp @@ -0,0 +1,363 @@ + +#include "settingsdialog.h" +#include "opiemail.h" +#include "editaccounts.h" +#include "composemail.h" +#include "mailistviewitem.h" +#include "viewmail.h" +#include "selectstore.h" +#include "selectsmtp.h" + +#include + +#include +#include +#include +#include +/* OPIE */ +//#include +#include + +/* QT */ + +using namespace Opie::Core; + +OpieMail::OpieMail( QWidget *parent, const char *name, WFlags flags ) + : MainWindow( parent, name, WStyle_ContextHelp ) +{ + settings = new Settings(); + + folderView->populate( settings->getAccounts() ); + +} + +OpieMail::~OpieMail() +{ + if (settings) delete settings; +} + +void OpieMail::appMessage(const QCString &msg, const QByteArray &data) +{ + +} +#include +void OpieMail::message(const QCString &msg, const QByteArray &data) +{ + // copied from old mail2 + static int ii = 0; + + // block second call + if ( ii < 2 ) { + ++ii; + if ( ii > 1 ) { + qDebug("qcop call blocked "); + return; + } + } + //qDebug("KM:appMessage %d *%s* %x", ii, msg.data(), this); + if (msg == "writeMail(QString,QString)") + { + QDataStream stream(data,IO_ReadOnly); + QString name, email; + stream >> name >> email; + // removing the whitespaces at beginning and end is needed! + slotwriteMail(name.stripWhiteSpace(),email.stripWhiteSpace()); + } + else if (msg == "newMail()") + { + slotComposeMail(); + } + else if (msg == "newMail(QString)") + { + QDataStream stream(data,IO_ReadOnly); + QString nameemail; + stream >> nameemail; + // the format is + // NAME :SUBJECT + //qDebug("message %s ", nameemail.latin1()); + + slotwriteMail2( nameemail ); + } +} +void OpieMail::slotwriteMail2(const QString& namemail ) +{ + // qDebug("OpieMail::slotwriteMail2 "); + qApp->processEvents(); + ComposeMail compose( settings, this, 0, true ); + if ( !namemail.isEmpty() ) { + QString to = namemail; + if ( namemail.find( " <") > 1 ) { + to = "\"" +to.replace( QRegExp( " <"), "\" <") ; + } else + if ( namemail.find( "<") > 1 ) { + to = "\"" +to.replace( QRegExp( "<"), "\" <") ; + } + int sub = to.find( ">:"); + if ( sub > 0 ) { + compose.setTo( to.left(sub+1) ); + compose.setSubject( to.mid(sub+2) ); + } else + compose.setTo( to ); + } + compose.slotAdjustColumns(); + compose.showMaximized(); + compose.exec(); + //qDebug("retttich "); +} +void OpieMail::slotwriteMail(const QString&name,const QString&email) +{ + // qDebug("OpieMail::slotwriteMail "); + ComposeMail compose( settings, this, 0, true , WStyle_ContextHelp ); + if (!email.isEmpty()) + { + if (!name.isEmpty()) + { + compose.setTo("\"" + name + "\"" + " " + "<"+ email + ">"); + } + else + { + compose.setTo(email); + } + } + compose.slotAdjustColumns(); + compose.showMaximized(); + compose.exec(); +} + +void OpieMail::slotComposeMail() +{ + slotwriteMail2( QString () ); + //slotwriteMail(0l,0l); +} + +void OpieMail::slotSendQueued() +{ + SMTPaccount *smtp = 0; + + QList list = settings->getAccounts(); + QList smtpList; + smtpList.setAutoDelete(false); + Account *it; + for ( it = list.first(); it; it = list.next() ) + { + if ( it->getType() == MAILLIB::A_SMTP ) + { + smtp = static_cast(it); + smtpList.append(smtp); + } + } + if (smtpList.count()==0) + { + QMessageBox::information(0,tr("Info"),tr("Define a smtp account first")); + return; + } + if (smtpList.count()==1) + { + smtp = smtpList.at(0); + } + else + { + smtp = 0; + selectsmtp selsmtp; + selsmtp.setSelectionlist(&smtpList); + selsmtp.showMaximized(); + if ( selsmtp.exec() == QDialog::Accepted ) + { + smtp = selsmtp.selected_smtp(); + } + } + if (smtp) + { + SMTPwrapper * wrap = new SMTPwrapper(smtp); + if ( wrap->flushOutbox() ) + { + QMessageBox::information(0,tr("Info"),tr("Mail queue flushed")); + } + delete wrap; + } +} + +void OpieMail::slotSearchMails() +{ + qDebug("OpieMail::slotSearchMails():not implemented "); +} + +void OpieMail::slotEditSettings() +{ + SettingsDialog settingsDialog( this, 0, true, WStyle_ContextHelp ); + settingsDialog.showMaximized(); + settingsDialog.exec(); +} + +void OpieMail::slotEditAccounts() +{ + EditAccounts eaDialog( settings, this, 0, true, WStyle_ContextHelp ); + eaDialog.slotAdjustColumns(); + eaDialog.showMaximized(); + eaDialog.exec(); + if ( settings ) delete settings; + settings = new Settings(); + + folderView->populate( settings->getAccounts() ); +} + +void OpieMail::displayMail() +{ + QListViewItem*item = mailView->currentItem(); + if (!item) return; + RecMailP mail = ((MailListViewItem*)item)->data(); + RecBodyP body = folderView->fetchBody(mail); + ViewMail readMail( this,"", Qt::WType_Modal | WStyle_ContextHelp ); + readMail.setBody( body ); + readMail.setMail( mail ); + readMail.showMaximized(); + readMail.exec(); + + if ( readMail.deleted ) + { + folderView->refreshCurrent(); + } + else + { + ( (MailListViewItem*)item )->setPixmap( 0, QPixmap() ); + } +} + +void OpieMail::slotDeleteMail() +{ + if (!mailView->currentItem()) return; + RecMailP mail = ((MailListViewItem*)mailView->currentItem() )->data(); + if ( QMessageBox::warning(this, tr("Delete Mail"), QString( tr("

Do you really want to delete this mail?

" ) + mail->getFrom() + " - " + mail->getSubject() ) , QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) + { + mail->Wrapper()->deleteMail( mail ); + folderView->refreshCurrent(); + } +} +void OpieMail::slotDeleteAllMail() +{ + if (!mailView->currentItem()) return; + RecMailP mail = ((MailListViewItem*)mailView->currentItem() )->data(); + if ( QMessageBox::warning(this, tr("Delete All Mails"), tr("Do you really want to delete\nall selected mails?" ) , QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) + { + MailListViewItem* item = (MailListViewItem*)mailView->firstChild (); + while ( item ) { + if ( item->isSelected() ) { + RecMailP mail = item->data(); + mail->Wrapper()->deleteMail( mail ); + } + item = (MailListViewItem*)item->nextSibling(); + } + folderView->refreshCurrent(); + } +} +void OpieMail::clearSelection() +{ + mailView->clearSelection(); + +} + +void OpieMail::mailHold(int button, QListViewItem *item,const QPoint&,int ) +{ + if (!mailView->currentItem()) return; + MAILLIB::ATYPE mailtype = ((MailListViewItem*)mailView->currentItem() )->wrapperType(); + /* just the RIGHT button - or hold on pda */ + if (button!=2) {return;} + if (!item) return; + QPopupMenu *m = new QPopupMenu(0); + if (m) + { + if (mailtype==MAILLIB::A_NNTP) { + m->insertItem(tr("Read this posting"),this,SLOT(displayMail())); +// m->insertItem(tr("Copy this posting"),this,SLOT(slotMoveCopyMail())); + } else { + if (folderView->currentisDraft()) { + m->insertItem(tr("Edit this mail"),this,SLOT(reEditMail())); + } + m->insertItem(tr("Read this mail"),this,SLOT(displayMail())); + m->insertItem(tr("Copy/Move this mail"),this,SLOT(slotMoveCopyMail())); + m->insertItem(tr("Delete this mail"),this,SLOT(slotDeleteMail())); + m->insertSeparator(); + m->insertItem(tr("Delete all selected mails"),this,SLOT(slotDeleteAllMail())); + m->insertItem(tr("Clear selection"),this,SLOT(clearSelection())); + } + m->setFocus(); + m->exec( QPoint( QCursor::pos().x(), QCursor::pos().y()) ); + delete m; + } +} + +void OpieMail::slotShowFolders( bool show ) +{ + if ( show && folderView->isHidden() ) + { + folderView->show(); + } + else if ( !show && !folderView->isHidden() ) + { + folderView->hide(); + } +} + +void OpieMail::refreshMailView(const QValueList&list) +{ + MailListViewItem*item = 0; + mailView->clear(); + + QValueList::ConstIterator it; + for (it = list.begin(); it != list.end();++it) + { + item = new MailListViewItem(mailView,item); + item->storeData((*it)); + item->showEntry(); + } +} + +void OpieMail::mailLeftClicked( QListViewItem *item ) +{ + mailView->clearSelection(); + /* just LEFT button - or tap with stylus on pda */ + //if (button!=1) return; + if (!item) return; + if (folderView->currentisDraft()) { + reEditMail(); + } else { + displayMail(); + } +} + +void OpieMail::slotMoveCopyMail() +{ + if (!mailView->currentItem()) return; + RecMailP mail = ((MailListViewItem*)mailView->currentItem() )->data(); + AbstractMail*targetMail = 0; + QString targetFolder = ""; + Selectstore sels; + folderView->setupFolderselect(&sels); + if (!sels.exec()) return; + targetMail = sels.currentMail(); + targetFolder = sels.currentFolder(); + if ( (mail->Wrapper()==targetMail && mail->getMbox()==targetFolder) || + targetFolder.isEmpty()) + { + return; + } + if (sels.newFolder() && !targetMail->createMbox(targetFolder)) + { + QMessageBox::critical(0,tr("Error creating new Folder"), + tr("

Error while creating
new folder - breaking.
")); + return; + } + mail->Wrapper()->mvcpMail(mail,targetFolder,targetMail,sels.moveMails()); + folderView->refreshCurrent(); +} + +void OpieMail::reEditMail() +{ + if (!mailView->currentItem()) return; + + ComposeMail compose( settings, this, 0, true , WStyle_ContextHelp ); + compose.reEditMail(((MailListViewItem*)mailView->currentItem() )->data()); + compose.slotAdjustColumns(); + compose.showMaximized(); + compose.exec(); +} diff --git a/kmicromail/opiemail.h b/kmicromail/opiemail.h new file mode 100644 index 0000000..143b0c4 --- a/dev/null +++ b/kmicromail/opiemail.h @@ -0,0 +1,46 @@ +#ifndef OPIEMAIL_H +#define OPIEMAIL_H + +#include "mainwindow.h" +#include + +#include +#include + +class OpieMail : public MainWindow +{ + Q_OBJECT + +public: + OpieMail( QWidget *parent = 0, const char *name = 0, WFlags flags = 0 ); + virtual ~OpieMail(); + static QString appName() { return QString::fromLatin1("opiemail"); } + +public slots: + virtual void slotwriteMail(const QString&name,const QString&email); + virtual void slotwriteMail2(const QString&nameemail); + virtual void slotComposeMail(); + virtual void appMessage(const QCString &msg, const QByteArray &data); + virtual void message(const QCString &msg, const QByteArray &data); +protected slots: + virtual void slotSendQueued(); + virtual void slotSearchMails(); + virtual void slotEditSettings(); + virtual void slotEditAccounts(); + virtual void displayMail(); + virtual void slotDeleteMail(); + virtual void slotDeleteAllMail(); + virtual void mailHold(int, QListViewItem *,const QPoint&,int); + virtual void slotShowFolders( bool show ); + virtual void refreshMailView(const QValueList&); + virtual void mailLeftClicked( QListViewItem * ); + virtual void slotMoveCopyMail(); + virtual void reEditMail(); + void clearSelection(); + +private: + Settings *settings; + +}; + +#endif diff --git a/kmicromail/pop3configui.ui b/kmicromail/pop3configui.ui new file mode 100644 index 0000000..1014ef4 --- a/dev/null +++ b/kmicromail/pop3configui.ui @@ -0,0 +1,352 @@ + +POP3configUI + + QDialog + + name + POP3configUI + + + geometry + + 0 + 0 + 314 + 410 + + + + caption + Configure POP3 + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QLayoutWidget + + name + Layout12 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + accountLabel + + + text + Account + + + + QLineEdit + + name + accountLine + + + toolTip + Name of the Account + + + + + + Line + + name + line1 + + + orientation + Horizontal + + + + QLayoutWidget + + name + Layout11 + + + + margin + 0 + + + spacing + 6 + + + QLayoutWidget + + name + Layout9 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + serverLabel + + + text + Server + + + + QLabel + + name + portLabel + + + text + Port + + + + + + QLayoutWidget + + name + Layout10 + + + + margin + 0 + + + spacing + 6 + + + QLineEdit + + name + serverLine + + + + QLineEdit + + name + portLine + + + + + + + + QLayoutWidget + + name + Layout13 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + TextLabel1 + + + text + Use secure sockets: + + + + QComboBox + + name + ComboBox1 + + + + + + QLineEdit + + name + CommandEdit + + + text + ssh $SERVER exec imapd + + + + Line + + name + line2 + + + orientation + Horizontal + + + + QLayoutWidget + + name + Layout6 + + + + margin + 0 + + + spacing + 6 + + + QLayoutWidget + + name + Layout4 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + userLabel + + + text + User + + + + QLabel + + name + passLabel + + + text + Password + + + + + + QLayoutWidget + + name + Layout5 + + + + margin + 0 + + + spacing + 6 + + + QLineEdit + + name + userLine + + + + QLineEdit + + name + passLine + + + echoMode + Password + + + + + + + + + name + spacer + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + accountLine + serverLine + portLine + userLine + passLine + + diff --git a/kmicromail/selectmailtypeui.ui b/kmicromail/selectmailtypeui.ui new file mode 100644 index 0000000..1fe0369 --- a/dev/null +++ b/kmicromail/selectmailtypeui.ui @@ -0,0 +1,94 @@ + +SelectMailTypeUI + + QDialog + + name + SelectMailTypeUI + + + geometry + + 0 + 0 + 157 + 66 + + + + caption + Select Type + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 3 + + + QGroupBox + + name + groupBox + + + title + Select Account Type + + + layoutMargin + + + layoutSpacing + + + + margin + 4 + + + spacing + 3 + + + QComboBox + + + text + IMAP + + + + + text + POP3 + + + + + text + SMTP + + + + name + typeBox + + + + + + + + typeBox + + diff --git a/kmicromail/selectsmtp.cpp b/kmicromail/selectsmtp.cpp new file mode 100644 index 0000000..24eced1 --- a/dev/null +++ b/kmicromail/selectsmtp.cpp @@ -0,0 +1,63 @@ +#include "selectsmtp.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +selectsmtp::selectsmtp(QWidget* parent, const char* name, bool modal, WFlags fl) + : selectstoreui(parent,name,modal,fl) +{ + //m_smtpList.setAutoDelete(false); + m_smtpList = 0; + //headlabel->setText(tr("
Select SMTP account to use
")); + headlabel->hide(); + folderSelection->hide(); + folderLabel->hide(); + accountlabel->setText("
SMTP Accounts
"); + Line1->hide(); + newFoldersel->hide(); + newFolderedit->hide(); + newFolderLabel->hide(); + Line2->hide(); + selMove->hide(); + m_current_smtp = 0; + setCaption(tr("Select SMTP Account")); +} + +selectsmtp::~selectsmtp() +{ +} + +void selectsmtp::slotAccountselected(int which) +{ + if (!m_smtpList || (unsigned)which>=m_smtpList->count() || which < 0) { + m_current_smtp = 0; + return; + } + m_current_smtp = m_smtpList->at(which); +} + +void selectsmtp::setSelectionlist(QList*list) +{ + m_smtpList = list; + accountSelection->clear(); + if (!m_smtpList || m_smtpList->count()==0) { + accountSelection->setEnabled(false); + return; + } + accountSelection->setEnabled(true); + for (unsigned i = 0; m_smtpList!=0 && i < m_smtpList->count(); ++i) { + accountSelection->insertItem( m_smtpList->at(i)->getAccountName()); + } + m_current_smtp = m_smtpList->at(0); +} + +SMTPaccount*selectsmtp::selected_smtp() +{ + return m_current_smtp; +} diff --git a/kmicromail/selectsmtp.h b/kmicromail/selectsmtp.h new file mode 100644 index 0000000..9157ddf --- a/dev/null +++ b/kmicromail/selectsmtp.h @@ -0,0 +1,27 @@ +#ifndef __selectsmtp_h +#define __selectstmp_h + + +#include "selectstoreui.h" +#include + +class SMTPaccount; + +class selectsmtp : public selectstoreui +{ + Q_OBJECT +public: + selectsmtp(QWidget* parent = 0, const char* name = 0, bool modal = TRUE, WFlags fl = 0 ); + virtual ~selectsmtp(); + void setSelectionlist(QList*list); + SMTPaccount*selected_smtp(); + +protected: + QList*m_smtpList; + SMTPaccount*m_current_smtp; + +protected slots: + virtual void slotAccountselected(int); +}; + +#endif diff --git a/kmicromail/selectstore.cpp b/kmicromail/selectstore.cpp new file mode 100644 index 0000000..0a07d51 --- a/dev/null +++ b/kmicromail/selectstore.cpp @@ -0,0 +1,70 @@ +#include "selectstore.h" +#include +#include +#include +#include + +Selectstore::Selectstore(QWidget* parent, const char* name) + :selectstoreui(parent,name,true) +{ + folderMap.clear(); + mailMap.clear(); + cMail = 0; +} + +Selectstore::~Selectstore() +{ +} + +void Selectstore::slotCreateNewFolder() +{ + bool how = newFoldersel->isChecked(); + folderSelection->setEnabled(!how); + newFolderedit->setEnabled(how); +} + +void Selectstore::slotMoveMail() +{ +} + +void Selectstore::addAccounts(AbstractMail*mail,const QStringList&folders) +{ + accountSelection->insertItem(mail->getName()); + mailMap[accountSelection->count()-1]=mail; + folderMap[accountSelection->count()-1]=folders; + if (accountSelection->count()==1) { + cMail = mail; + folderSelection->insertStringList(folders); + } +} + +void Selectstore::slotAccountselected(int i) +{ + folderSelection->clear(); + folderSelection->insertStringList(folderMap[i]); + cMail = mailMap[i]; +} + +QString Selectstore::currentFolder() +{ + if (newFoldersel->isChecked()) { + return newFolderedit->text(); + } else { + return folderSelection->currentText(); + } +} + +AbstractMail*Selectstore::currentMail() +{ + return cMail; +} + +bool Selectstore::newFolder() +{ + return newFoldersel->isChecked(); +} + +bool Selectstore::moveMails() +{ + return selMove->isChecked(); +} diff --git a/kmicromail/selectstore.h b/kmicromail/selectstore.h new file mode 100644 index 0000000..447a6ae --- a/dev/null +++ b/kmicromail/selectstore.h @@ -0,0 +1,33 @@ +#ifndef _SELECTSTORE_H +#define _SELECTSTORE_H + +#include "selectstoreui.h" +#include +#include +#include + +class AbstractMail; + +class Selectstore:public selectstoreui +{ + Q_OBJECT +public: + Selectstore(QWidget* parent = 0, const char* name = 0); + virtual ~Selectstore(); + virtual void addAccounts(AbstractMail*mail,const QStringList&folders); + virtual QString currentFolder(); + virtual AbstractMail*currentMail(); + bool newFolder(); + bool moveMails(); + +protected slots: + virtual void slotCreateNewFolder(); + virtual void slotMoveMail(); + virtual void slotAccountselected(int); + +protected: + QMap folderMap; + QMap mailMap; + AbstractMail*cMail; +}; +#endif diff --git a/kmicromail/selectstoreui.ui b/kmicromail/selectstoreui.ui new file mode 100644 index 0000000..5f0e507 --- a/dev/null +++ b/kmicromail/selectstoreui.ui @@ -0,0 +1,279 @@ + +selectstoreui + + QDialog + + name + selectstoreui + + + geometry + + 0 + 0 + 182 + 273 + + + + caption + Select target box + + + layoutMargin + + + layoutSpacing + + + + margin + 1 + + + spacing + 1 + + + QLabel + + name + headlabel + + + text + <b>Store mail(s) to</b> + + + alignment + AlignCenter + + + hAlign + + + + QLayoutWidget + + name + Layout2 + + + + margin + 0 + + + spacing + 6 + + + QComboBox + + name + folderSelection + + + sizePolicy + + 3 + 0 + + + + + QLabel + + name + folderLabel + + + text + Folder: + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + QComboBox + + name + accountSelection + + + sizePolicy + + 3 + 0 + + + + + QLabel + + name + accountlabel + + + sizePolicy + + 1 + 1 + + + + text + Account: + + + alignment + AlignVCenter|AlignRight + + + hAlign + + + + + + Line + + name + Line1 + + + orientation + Horizontal + + + + QCheckBox + + name + newFoldersel + + + text + Create new folder + + + + QLineEdit + + name + newFolderedit + + + enabled + false + + + + QLabel + + name + newFolderLabel + + + text + Prefix will prepend, no need to enter it! + + + alignment + WordBreak|AlignCenter + + + hAlign + + + wordwrap + + + + Line + + name + Line2 + + + orientation + Horizontal + + + + QCheckBox + + name + selMove + + + text + Move mail(s) + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + selMove + clicked() + selectstoreui + slotMoveMail() + + + newFoldersel + clicked() + selectstoreui + slotCreateNewFolder() + + + accountSelection + activated(int) + selectstoreui + slotAccountselected(int) + + + folderSelection + activated(int) + selectstoreui + slotFolderSelected(int) + + slotFolderSelected(int) + slotAccountselected(int) + slotCreateNewFolder() + slotMoveMail() + + + accountSelection + folderSelection + newFoldersel + newFolderedit + selMove + + diff --git a/kmicromail/settingsdialog.cpp b/kmicromail/settingsdialog.cpp new file mode 100644 index 0000000..061ea72 --- a/dev/null +++ b/kmicromail/settingsdialog.cpp @@ -0,0 +1,49 @@ +#include +#include + +#include + +#include "settingsdialog.h" + + +SettingsDialog::SettingsDialog( QWidget* parent, const char* name, bool modal, WFlags fl ) + : SettingsDialogUI( parent, name, modal, fl ) { + + readConfig(); +} + +SettingsDialog::~SettingsDialog() { + +} + +void SettingsDialog::readConfig() { + Config cfg("mail"); + cfg.setGroup( "Settings" ); + showHtmlButton->setChecked( cfg.readBoolEntry( "showHtml", false ) ); + cfg.setGroup( "Compose" ); + checkBoxLater->setChecked( cfg.readBoolEntry( "sendLater", false ) ); + cfg.setGroup( "Applet" ); + cbEnableTaskbarApplet->setChecked( cfg.readBoolEntry( "Disabled", false ) ); + spCheckOften->setValue( cfg.readNumEntry( "CheckEvery", 5 ) ); + cbBlinkLed->setChecked( cfg.readBoolEntry( "BlinkLed", true ) ); + cbPlaySound->setChecked( cfg.readBoolEntry( "PlaySound", false ) ); + +} + +void SettingsDialog::writeConfig() { + Config cfg( "mail" ); + cfg.setGroup( "Settings" ); + cfg.writeEntry( "showHtml", showHtmlButton->isChecked() ); + cfg.setGroup( "Compose" ); + cfg.writeEntry( "sendLater", checkBoxLater->isChecked() ); + cfg.setGroup( "Applet" ); + cfg.writeEntry( "Disabled", cbEnableTaskbarApplet->isChecked() ); + cfg.writeEntry( "CheckEvery", spCheckOften->value() ); + cfg.writeEntry( "BlinkLed", cbBlinkLed->isChecked() ); + cfg.writeEntry( "PlaySound", cbPlaySound->isChecked() ); +} + +void SettingsDialog::accept() { + writeConfig(); + QDialog::accept(); +} diff --git a/kmicromail/settingsdialog.h b/kmicromail/settingsdialog.h new file mode 100644 index 0000000..6b4d456 --- a/dev/null +++ b/kmicromail/settingsdialog.h @@ -0,0 +1,29 @@ +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include + +#include "settingsdialogui.h" + +class SettingsDialog : public SettingsDialogUI { + +Q_OBJECT + +public: + SettingsDialog( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~SettingsDialog(); + +private: + void readConfig(); + void writeConfig(); + + +private slots: + void accept(); + + +}; + + + +#endif diff --git a/kmicromail/settingsdialogui.ui b/kmicromail/settingsdialogui.ui new file mode 100644 index 0000000..b503667 --- a/dev/null +++ b/kmicromail/settingsdialogui.ui @@ -0,0 +1,296 @@ + +SettingsDialogUI + + QDialog + + name + SettingsDialogUI + + + geometry + + 0 + 0 + 312 + 379 + + + + caption + Settings Dialog + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QTabWidget + + name + TabWidget2 + + + enabled + true + + + layoutMargin + + + layoutSpacing + + + QWidget + + name + tab + + + title + View Mail + + + + margin + 3 + + + spacing + 3 + + + QCheckBox + + name + showHtmlButton + + + text + View mail as Html + + + + + name + Spacer1 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + QWidget + + name + tab + + + title + Compose Mail + + + + margin + 3 + + + spacing + 3 + + + QCheckBox + + name + checkBoxLater + + + text + Send mails later ( enqueue in outbox ) + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + QWidget + + name + tab + + + title + Taskbar Applet + + + + margin + 3 + + + spacing + 3 + + + QCheckBox + + name + cbEnableTaskbarApplet + + + enabled + false + + + text + Disable Taskbar Applet + + + + QLayoutWidget + + name + Layout2 + + + + margin + 0 + + + spacing + 6 + + + QSpinBox + + name + spCheckOften + + + enabled + false + + + suffix + min + + + value + 5 + + + + QLabel + + name + TextLabel1 + + + text + Check how often + + + + + + QCheckBox + + name + cbBlinkLed + + + enabled + false + + + text + Blink Led when new mails arrive + + + + QCheckBox + + name + cbPlaySound + + + enabled + false + + + text + Play Sound when new mails arrive + + + + + name + Spacer3 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + diff --git a/kmicromail/smtpconfigui.ui b/kmicromail/smtpconfigui.ui new file mode 100644 index 0000000..d4151a9 --- a/dev/null +++ b/kmicromail/smtpconfigui.ui @@ -0,0 +1,360 @@ + +SMTPconfigUI + + QDialog + + name + SMTPconfigUI + + + geometry + + 0 + 0 + 335 + 426 + + + + caption + Configure SMTP + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QLabel + + name + accountLabel + + + text + Account + + + + QLineEdit + + name + accountLine + + + toolTip + Name of the Account + + + + Line + + name + line1 + + + sizePolicy + + 1 + 0 + + + + orientation + Horizontal + + + + QLayoutWidget + + name + Layout20 + + + + margin + 0 + + + spacing + 6 + + + QLayoutWidget + + name + Layout18 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + serverLabel + + + text + Server + + + + QLabel + + name + portLabel + + + text + Port + + + + + + QLayoutWidget + + name + Layout19 + + + + margin + 0 + + + spacing + 6 + + + QLineEdit + + name + serverLine + + + toolTip + Name of the SMTP Server + + + + QLineEdit + + name + portLine + + + toolTip + Port of the SMTP Server + + + + + + + + QLabel + + name + TextLabel1 + + + text + Use secure sockets: + + + + QComboBox + + name + ComboBox1 + + + + QLineEdit + + name + CommandEdit + + + text + ssh $SERVER exec + + + + Line + + name + line2 + + + sizePolicy + + 1 + 0 + + + + orientation + Horizontal + + + + QCheckBox + + name + loginBox + + + text + Use Login + + + + QLayoutWidget + + name + Layout17 + + + + margin + 0 + + + spacing + 6 + + + QLayoutWidget + + name + Layout15 + + + + margin + 0 + + + spacing + 6 + + + QLabel + + name + userLabel + + + text + User + + + + QLabel + + name + passLabel + + + text + Password + + + + + + QLayoutWidget + + name + Layout16 + + + + margin + 0 + + + spacing + 6 + + + QLineEdit + + name + userLine + + + enabled + false + + + + QLineEdit + + name + passLine + + + enabled + false + + + echoMode + Password + + + + + + + + + name + spacer + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + accountLine + serverLine + portLine + loginBox + userLine + passLine + + diff --git a/kmicromail/statuswidget.cpp b/kmicromail/statuswidget.cpp new file mode 100644 index 0000000..19cf635 --- a/dev/null +++ b/kmicromail/statuswidget.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +#include "statuswidget.h" + +// the current problem I see is "locking": used exclusive by one sender + + +StatusWidget::StatusWidget( QWidget* parent, const char* name,WFlags fl ) + : StatusWidgetUI( parent, name, fl ) { + + setMaximumHeight( 15 ); + // hide for now since nothing reports decent progress data yet. + statusProgress->hide(); + } + +StatusWidget::~StatusWidget() { +} + +void StatusWidget::setText( const QString& text ) { + show(); + statusText->setText( text ); + QTimer::singleShot( 5000, this, SLOT( hide() ) ); +} + +void StatusWidget::setProgress( int progress ) { + show(); + statusProgress->setProgress( progress ); + if ( progress == 100 ) { + hide(); + } +} diff --git a/kmicromail/statuswidget.h b/kmicromail/statuswidget.h new file mode 100644 index 0000000..73f0d75 --- a/dev/null +++ b/kmicromail/statuswidget.h @@ -0,0 +1,24 @@ +#ifndef STATUS_WIDGET_H +#define STATUS_WIDGET_H + +#include +#include "statuswidgetui.h" + +class StatusWidget : public StatusWidgetUI { + +Q_OBJECT + +public: + StatusWidget( QWidget* parent = 0, const char* name = 0,WFlags fl = 0 ); + ~StatusWidget(); + + +public slots: + + void setText( const QString& text ); + void setProgress( int progress ); +}; + + +#endif + diff --git a/kmicromail/statuswidgetui.ui b/kmicromail/statuswidgetui.ui new file mode 100644 index 0000000..ffe3528 --- a/dev/null +++ b/kmicromail/statuswidgetui.ui @@ -0,0 +1,71 @@ + +StatusWidgetUI + + QWidget + + name + StatusWidgetUI + + + geometry + + 0 + 0 + 596 + 480 + + + + caption + Form1 + + + layoutMargin + + + layoutSpacing + + + + margin + 3 + + + spacing + 3 + + + QProgressBar + + name + statusProgress + + + sizePolicy + + 5 + 0 + + + + + QLabel + + name + statusText + + + sizePolicy + + 5 + 1 + + + + text + TextLabel1 + + + + + diff --git a/kmicromail/viewmail.cpp b/kmicromail/viewmail.cpp new file mode 100644 index 0000000..1b74564 --- a/dev/null +++ b/kmicromail/viewmail.cpp @@ -0,0 +1,525 @@ +#include "composemail.h" +#include "viewmail.h" + +#include +#include +#include +#include + +/* OPIE */ +//#include +//#include +//#include + +#include +#include + +#include +#include + +/* QT */ +#include +#include +#include +#include +#include +#include +#include + +//using namespace Opie::Ui; +//using namespace Opie::Core; + +AttachItem::AttachItem(QListView * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file, + const QString&fsize,int num,const QValueList&path) + : QListViewItem(parent,after),_partNum(num) +{ + _path=path; + setText(0, mime); + setText(1, desc); + setText(2, file); + setText(3, fsize); +} + +AttachItem::AttachItem(QListViewItem * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file, + const QString&fsize,int num,const QValueList&path) + : QListViewItem(parent,after),_partNum(num) +{ + _path=path; + setText(0, mime); + setText(1, desc); + setText(2, file); + setText(3, fsize); +} + +bool AttachItem::isParentof(const QValueList&path) +{ + /* if not set, then no parent */ + if (path.count()==0||_path.count()==0) return false; + /* the parent must have one digit less then a child */ + if (path.count()!=_path.count()+1) return false; + for (unsigned int i=0; i < _path.count();++i) + { + if (_path[i]!=path[i]) return false; + } + return true; +} + +AttachItem* ViewMail::searchParent(const QValueList&path) +{ + QListViewItemIterator it( attachments ); + for ( ; it.current(); ++it ) + { + AttachItem*ati = (AttachItem*)it.current(); + if (ati->isParentof(path)) return ati; + } + return 0; +} + +AttachItem* ViewMail::lastChild(AttachItem*parent) +{ + if (!parent) return 0; + AttachItem* item = (AttachItem*)parent->firstChild(); + if (!item) return item; + AttachItem*temp=0; + while( (temp=(AttachItem*)item->nextSibling())) + { + item = temp; + } + return item; +} + +void ViewMail::setBody(const RecBodyP&body ) +{ + + m_body = body; + m_mail[2] = body->Bodytext(); + attachbutton->setEnabled(body->Parts().count()>0); + attachments->setEnabled(body->Parts().count()>0); + if (body->Parts().count()==0) + { + return; + } + AttachItem * curItem=0; + AttachItem * parentItem = 0; + QString type=body->Description()->Type()+"/"+body->Description()->Subtype(); + QString desc,fsize; + double s = body->Description()->Size(); + int w; + w=0; + + while (s>1024) + { + s/=1024; + ++w; + if (w>=2) break; + } + + QString q=""; + switch(w) + { + case 1: + q="k"; + break; + case 2: + q="M"; + break; + default: + break; + } + + { + /* I did not found a method to make a CONTENT reset on a QTextStream + so I use this construct that the stream will re-constructed in each + loop. To let it work, the textstream is packed into a own area of + code is it will be destructed after finishing its small job. + */ + QTextOStream o(&fsize); + if (w>0) o.precision(2); else o.precision(0); + o.setf(QTextStream::fixed); + o << s << " " << q << "Byte"; + } + + curItem=new AttachItem(attachments,curItem,type,"Mailbody","",fsize,-1,body->Description()->Positionlist()); + QString filename = ""; + + for (unsigned int i = 0; i < body->Parts().count();++i) + { + filename = ""; + type = body->Parts()[i]->Type()+"/"+body->Parts()[i]->Subtype(); + part_plist_t::ConstIterator it = body->Parts()[i]->Parameters().begin(); + for (;it!=body->Parts()[i]->Parameters().end();++it) + { + if (it.key().lower()=="name") + { + filename=it.data(); + } + } + s = body->Parts()[i]->Size(); + w = 0; + while (s>1024) + { + s/=1024; + ++w; + if (w>=2) break; + } + switch(w) + { + case 1: + q="k"; + break; + case 2: + q="M"; + break; + default: + q=""; + break; + } + QTextOStream o(&fsize); + if (w>0) o.precision(2); else o.precision(0); + o.setf(QTextStream::fixed); + o << s << " " << q << "Byte"; + desc = body->Parts()[i]->Description(); + parentItem = searchParent(body->Parts()[i]->Positionlist()); + if (parentItem) + { + AttachItem*temp = lastChild(parentItem); + if (temp) curItem = temp; + curItem=new AttachItem(parentItem,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist()); + attachments->setRootIsDecorated(true); + curItem = parentItem; + } + else + { + curItem=new AttachItem(attachments,curItem,type,desc,filename,fsize,i,body->Parts()[i]->Positionlist()); + } + } +} + + +void ViewMail::slotShowHtml( bool state ) +{ + m_showHtml = state; + setText(); +} + +void ViewMail::slotItemClicked( QListViewItem * item , const QPoint & point, int ) +{ + if (!item ) + return; + + if ( ( ( AttachItem* )item )->Partnumber() == -1 ) + { + setText(); + return; + } + QPopupMenu *menu = new QPopupMenu(); + int ret=0; + + if ( item->text( 0 ).left( 5 ) == "text/" || item->text(0)=="message/rfc822" ) + { + menu->insertItem( tr( "Show Text" ), 1 ); + } + if (item->text(0).left(6)=="image/") { + menu->insertItem(tr("Display image preview"),2); + } + menu->insertItem( tr( "Save Attachment" ), 0 ); + menu->insertSeparator(1); + + ret = menu->exec( point, 0 ); + + switch(ret) + { + case 0: + { + //MimeTypes types; + //types.insert( "all", "*" ); + QString str = KFileDialog::getSaveFileName( "/", item->text( 2 ), this ); + + if( !str.isEmpty() ) + { + encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] ); + if (content) + { + QFile output(str); + output.open(IO_WriteOnly); + output.writeBlock(content->Content(),content->Length()); + output.close(); + delete content; + } + } + } + break ; + + case 2: + { + QString tmpfile = "/tmp/opiemail-image"; + encodedString*content = m_recMail->Wrapper()->fetchDecodedPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] ); + if (content) { + QFile output(tmpfile); + output.open(IO_WriteOnly); + output.writeBlock(content->Content(),content->Length()); + output.close(); + delete content; + MailImageDlg iview(""); + iview.setName(tmpfile); + KApplication::execDialog(&iview); + output.remove(); + } + } + break; + case 1: + if ( ( ( AttachItem* )item )->Partnumber() == -1 ) + { + setText(); + } + else + { + if ( m_recMail->Wrapper() != 0l ) + { // make sure that there is a wrapper , even after delete or simular actions + browser->setText( m_recMail->Wrapper()->fetchTextPart( m_recMail, m_body->Parts()[ ( ( AttachItem* )item )->Partnumber() ] ) ); + } + } + break; + } + delete menu; +} + + +void ViewMail::setMail(const RecMailP&mail ) +{ + + m_recMail = mail; + + m_mail[0] = mail->getFrom(); + m_mail[1] = mail->getSubject(); + m_mail[3] = mail->getDate(); + m_mail[4] = mail->Msgid(); + + m_mail2[0] = mail->To(); + m_mail2[1] = mail->CC(); + m_mail2[2] = mail->Bcc(); + + setText(); +} + + + +ViewMail::ViewMail( QWidget *parent, const char *name, WFlags fl) + : ViewMailBase(parent, name, fl), _inLoop(false) +{ + m_gotBody = false; + deleted = false; + + connect( reply, SIGNAL(activated()), SLOT(slotReply())); + connect( forward, SIGNAL(activated()), SLOT(slotForward())); + connect( deleteMail, SIGNAL( activated() ), SLOT( slotDeleteMail() ) ); + connect( showHtml, SIGNAL( toggled(bool) ), SLOT( slotShowHtml(bool) ) ); + + attachments->setEnabled(m_gotBody); + connect( attachments, SIGNAL( clicked(QListViewItem*,const QPoint&, int) ), SLOT( slotItemClicked(QListViewItem*,const QPoint&, int) ) ); + + readConfig(); + attachments->setSorting(-1); +} + +void ViewMail::readConfig() +{ + Config cfg( "mail" ); + cfg.setGroup( "Settings" ); + m_showHtml = cfg.readBoolEntry( "showHtml", false ); + showHtml->setOn( m_showHtml ); +} + +void ViewMail::setText() +{ + + QString toString; + QString ccString; + QString bccString; + + for ( QStringList::Iterator it = ( m_mail2[0] ).begin(); it != ( m_mail2[0] ).end(); ++it ) + { + toString += (*it); + } + for ( QStringList::Iterator it = ( m_mail2[1] ).begin(); it != ( m_mail2[1] ).end(); ++it ) + { + ccString += (*it); + } + for ( QStringList::Iterator it = ( m_mail2[2] ).begin(); it != ( m_mail2[2] ).end(); ++it ) + { + bccString += (*it); + } + + setCaption( caption().arg( m_mail[0] ) ); + + m_mailHtml = "" + "
" + "
" + deHtml( m_mail[1] ) + "
" + "
" + "" + tr( "From" ) + ": " + deHtml( m_mail[0] ) + "
" + "" + tr( "To" ) + ": " + deHtml( toString ) + "
" + + tr( "Cc" ) + ": " + deHtml( ccString ) + "
" + "" + tr( "Date" ) + ": " + m_mail[3] + + "
"; + + if ( !m_showHtml ) + { + browser->setText( QString( m_mailHtml) + deHtml( m_mail[2] ) + "" ); + } + else + { + browser->setText( QString( m_mailHtml) + m_mail[2] + "" ); + } + // remove later in favor of a real handling + m_gotBody = true; +} + + +ViewMail::~ViewMail() +{ + m_recMail->Wrapper()->cleanMimeCache(); + hide(); +} + +void ViewMail::hide() +{ + QWidget::hide(); + + if (_inLoop) + { + _inLoop = false; + qApp->exit_loop(); + + } + +} + +void ViewMail::exec() +{ + show(); + + if (!_inLoop) + { + _inLoop = true; + qApp->enter_loop(); + } + +} + +QString ViewMail::deHtml(const QString &string) +{ + QString string_ = string; + string_.replace(QRegExp("&"), "&"); + string_.replace(QRegExp("<"), "<"); + string_.replace(QRegExp(">"), ">"); + string_.replace(QRegExp("\\n"), "
"); + return string_; +} + +void ViewMail::slotReply() +{ + if (!m_gotBody) + { + QMessageBox::information(this, tr("Error"), tr("

The mail body is not yet downloaded, so you cannot reply yet."), tr("Ok")); + return; + } + + QString rtext; + rtext += QString("* %1 wrote on %2:\n") // no i18n on purpose + .arg( m_mail[0] ) + .arg( m_mail[3] ); + + QString text = m_mail[2]; + QStringList lines = QStringList::split(QRegExp("\\n"), text); + QStringList::Iterator it; + for (it = lines.begin(); it != lines.end(); it++) + { + rtext += "> " + *it + "\n"; + } + rtext += "\n"; + + QString prefix; + if ( m_mail[1].find(QRegExp("^Re: .*$")) != -1) prefix = ""; + else prefix = "Re: "; // no i18n on purpose + + Settings *settings = new Settings(); + ComposeMail composer( settings ,this, 0, true); + if (m_recMail->Replyto().isEmpty()) { + composer.setTo( m_recMail->getFrom()); + } else { + composer.setTo( m_recMail->Replyto()); + } + composer.setSubject( prefix + m_mail[1] ); + composer.setMessage( rtext ); + composer.setInReplyTo(m_recMail->Msgid()); + + if ( QDialog::Accepted == KApplication::execDialog( &composer ) ) + { + m_recMail->Wrapper()->answeredMail(m_recMail); + } +} + +void ViewMail::slotForward() +{ + if (!m_gotBody) + { + QMessageBox::information(this, tr("Error"), tr("

The mail body is not yet downloaded, so you cannot forward yet."), tr("Ok")); + return; + } + + QString ftext; + ftext += QString("\n----- Forwarded message from %1 -----\n\n") + .arg( m_mail[0] ); + if (!m_mail[3].isNull()) + ftext += QString("Date: %1\n") + .arg( m_mail[3] ); + if (!m_mail[0].isNull()) + ftext += QString("From: %1\n") + .arg( m_mail[0] ); + if (!m_mail[1].isNull()) + ftext += QString("Subject: %1\n") + .arg( m_mail[1] ); + + ftext += QString("\n%1\n") + .arg( m_mail[2]); + + ftext += QString("----- End forwarded message -----\n"); + + Settings *settings = new Settings(); + ComposeMail composer( settings ,this, 0, true); + composer.setSubject( "Fwd: " + m_mail[1] ); + composer.setMessage( ftext ); + if ( QDialog::Accepted == KApplication::execDialog( &composer )) + { + } +} + +void ViewMail::slotDeleteMail( ) +{ + if ( QMessageBox::warning(this, tr("Delete Mail"), QString( tr("

Do you really want to delete this mail?

" ) + m_mail[0] + " - " + m_mail[1] ) , QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) + { + m_recMail->Wrapper()->deleteMail( m_recMail ); + hide(); + deleted = true; + } +} + +MailImageDlg::MailImageDlg(const QString&fname,QWidget *parent, const char *name, bool modal, WFlags f) + : KDialog(parent,name,modal) +{ + QVBoxLayout*dlglayout = new QVBoxLayout(this); + dlglayout->setSpacing(2); + dlglayout->setMargin(1); + //m_imageview = new Opie::MM::OImageScrollView(this); + //dlglayout->addWidget(m_imageview); +} + +MailImageDlg::~MailImageDlg() +{ +} + +void MailImageDlg::setName(const QString&fname) +{ + qDebug("viewmail.cpp: MailImageDlg::setName Pending"); + // m_imageview->setImage(fname); +} diff --git a/kmicromail/viewmail.h b/kmicromail/viewmail.h new file mode 100644 index 0000000..c42577e --- a/dev/null +++ b/kmicromail/viewmail.h @@ -0,0 +1,86 @@ +#ifndef VIEWMAIL_H +#define VIEWMAIL_H + +#include "viewmailbase.h" +#include + +#include + +#include +#include +#include +#include + +//namespace Opie { namespace MM { class OImageScrollView; } } + +class AttachItem : public QListViewItem +{ +public: + AttachItem(QListView * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file, + const QString&fsize,int num,const QValueList&path); + AttachItem(QListViewItem * parent,QListViewItem *after, const QString&mime,const QString&desc,const QString&file, + const QString&fsize,int num,const QValueList&path); + int Partnumber() { return _partNum; } + bool isParentof(const QValueList&path); + +private: + int _partNum; + /* needed for a better display of attachments */ + QValueList _path; +}; + +class ViewMail : public ViewMailBase +{ + Q_OBJECT + +public: + ViewMail( QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + ~ViewMail(); + + void hide(); + void exec(); + void setMail(const RecMailP&mail ); + void setBody(const RecBodyP&body); + bool deleted; + +protected: + QString deHtml(const QString &string); + AttachItem* searchParent(const QValueList&path); + AttachItem* lastChild(AttachItem*parent); + +protected slots: + void slotReply(); + void slotForward(); + void setText(); + void slotItemClicked( QListViewItem * item , const QPoint & point, int c ); + void slotDeleteMail( ); + void slotShowHtml( bool ); + +private: + void readConfig(); + + bool _inLoop; + QString m_mailHtml; + bool m_gotBody; + RecBodyP m_body; + RecMailP m_recMail; + bool m_showHtml; + + // 0 from 1 subject 2 bodytext 3 date + QMap m_mail; + // 0 to 1 cc 2 bcc + QMap m_mail2; +}; + +class MailImageDlg:public KDialog +{ + Q_OBJECT +public: + MailImageDlg(const QString&,QWidget *parent = 0, const char *name = 0, bool modal = true, WFlags f = 0); + ~MailImageDlg(); + void setName(const QString&); +protected: + //Opie::MM::OImageScrollView*m_imageview; +}; + +#endif diff --git a/kmicromail/viewmailbase.cpp b/kmicromail/viewmailbase.cpp new file mode 100644 index 0000000..c761815 --- a/dev/null +++ b/kmicromail/viewmailbase.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +//#include + +#include "viewmailbase.h" +//#include "opendiag.h" + +ViewMailBase::ViewMailBase(QWidget *parent, const char *name, WFlags fl) + : QMainWindow(parent, name, fl) +{ + setCaption(tr("E-Mail by %1")); + setToolBarsMovable(false); + + toolbar = new QToolBar(this); + menubar = new QMenuBar( toolbar ); + mailmenu = new QPopupMenu( menubar ); + menubar->insertItem( tr( "Mail" ), mailmenu ); + + toolbar->setHorizontalStretchable(true); + addToolBar(toolbar); + + QLabel *spacer = new QLabel(toolbar); + spacer->setBackgroundMode(QWidget::PaletteButton); + toolbar->setStretchableWidget(spacer); + + reply = new QAction(tr("Reply"),SmallIcon("reply"), 0, 0, this); + reply->addTo(toolbar); + reply->addTo(mailmenu); + + forward = new QAction(tr("Forward"),SmallIcon("forward"), 0, 0, this); + forward->addTo(toolbar); + forward->addTo(mailmenu); + + attachbutton = new QAction(tr("Attachments"),SmallIcon("attach"), 0, 0, this, 0, true); + attachbutton->addTo(toolbar); + attachbutton->addTo(mailmenu); + connect(attachbutton, SIGNAL(toggled(bool)), SLOT(slotChangeAttachview(bool))); + + + showHtml = new QAction( tr( "Show Html" ), SmallIcon( "html" ), 0, 0, this, 0, true ); + showHtml->addTo( toolbar ); + showHtml->addTo( mailmenu ); + + deleteMail = new QAction(tr("Delete Mail"),SmallIcon("trash"), 0, 0, this); + deleteMail->addTo(toolbar); + deleteMail->addTo(mailmenu); + + QVBox *view = new QVBox(this); + setCentralWidget(view); + + attachments = new QListView(view); + attachments->setMinimumHeight(90); + attachments->setMaximumHeight(90); + attachments->setAllColumnsShowFocus(true); + attachments->addColumn("Mime Type", 60); + attachments->addColumn(tr("Description"), 100); + attachments->addColumn(tr("Filename"), 80); + attachments->addColumn(tr("Size"), 80); + attachments->setSorting(-1); + attachments->hide(); + + browser = new QTextBrowser(view); + +// openDiag = new OpenDiag(view); +// openDiag->hide(); + +} + +void ViewMailBase::slotChangeAttachview(bool state) +{ + if (state) attachments->show(); + else attachments->hide(); +} + +void ViewMailBase::keyPressEvent ( QKeyEvent * e ) +{ + if( e->key()==Qt::Key_Escape ) { + close(); + e->accept(); + return; + } + QWidget::keyPressEvent(e); +} diff --git a/kmicromail/viewmailbase.h b/kmicromail/viewmailbase.h new file mode 100644 index 0000000..fdaad2a --- a/dev/null +++ b/kmicromail/viewmailbase.h @@ -0,0 +1,38 @@ +#ifndef VIEWMAILBASE_H +#define VIEWMAILBASE_H + +#include + +class QAction; +class OpenDiag; +class QListView; +class QToolBar; +class QTextBrowser; +class QMenuBar; +class QPopupMenu; + +class ViewMailBase : public QMainWindow +{ + Q_OBJECT + +public: + ViewMailBase(QWidget *parent = 0, const char *name = 0, WFlags fl = 0); + +protected: + QAction *reply, *forward, *attachbutton, *deleteMail, *showHtml; + QListView *attachments; + QToolBar *toolbar; + QTextBrowser *browser; + OpenDiag *openDiag; + QMenuBar *menubar; + QPopupMenu *mailmenu; + +protected slots: + void slotChangeAttachview(bool state); + virtual void keyPressEvent ( QKeyEvent * e ); + + +}; + +#endif + -- cgit v0.9.0.2