diff options
Diffstat (limited to 'libmail/imapfolders.C')
| -rw-r--r-- | libmail/imapfolders.C | 1637 |
1 files changed, 0 insertions, 1637 deletions
diff --git a/libmail/imapfolders.C b/libmail/imapfolders.C deleted file mode 100644 index ac7928a..0000000 --- a/libmail/imapfolders.C +++ /dev/null @@ -1,1637 +0,0 @@ -/* -** Copyright 2002-2004, Double Precision Inc. -** -** See COPYING for distribution information. -*/ -#include "libmail_config.h" -#include "addmessage.H" -#include "imap.H" -#include "misc.H" -#include "imapacl.H" -#include "imapfolder.H" -#include "imapfolders.H" -#include "imaplisthandler.H" - -#include "smapacl.H" -#include "smapcreate.H" -#include "smapdelete.H" -#include "smapaddmessage.H" -#include "smapsendfolder.H" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#include <sstream> -#include "unicode/courier-unicode.h" -#include "rfc822/rfc822.h" -#include "maildir/maildiraclt.h" - -using namespace std; - -// -// Top level folders -- this stuff is taken from the IMAP NAMESPACE messages -// at login. - -void mail::imap::readTopLevelFolders(mail::callback::folderList &callback1, - mail::callback &callback2) -{ - vector<const mail::folder *> folders; - vector<mail::imapFolder>::iterator b, e; - - b=namespaces.begin(); - e=namespaces.end(); - - while (b != e) - { - folders.push_back(&*b); - b++; - } - - callback1.success(folders); - callback2.success("OK"); -} - -mail::folder *mail::imap::folderFromString(string s) -{ - string words[4]; - - words[0]=""; - words[1]=""; - words[2]=""; - words[3]=""; - int i=0; - - string::iterator b=s.begin(), e=s.end(); - - while (b != e) - { - if (*b == ':') - { - b++; - ++i; - continue; - } - - if (*b == '\\') - { - b++; - if (b == e) - break; - } - - if (i < 4) - words[i].append(&*b, 1); - b++; - } - - mail::imapFolder *f=new mail::imapFolder(*this, - words[0], - words[1], - words[2], - -1); - - if (f == NULL) - return NULL; - - f->hasMessages(words[3].find('S') != std::string::npos); - f->hasSubFolders(words[3].find('C') != std::string::npos); - - return f; -} - -mail::imapFolder::imapFolder(mail::imap &myImap, string pathArg, - string hierArg, string nameArg, - int typeArg) - : mail::folder(&myImap), - imapAccount(myImap), path(pathArg), hiersep(hierArg), name(nameArg), - hasmessages(true), - hassubfolders(false), type(typeArg) -{ -} - -mail::imapFolder::imapFolder(const mail::imapFolder &c) - : mail::folder(&c.imapAccount), imapAccount(c.imapAccount) -{ - (*this)=c; -} - -mail::imapFolder &mail::imapFolder::operator=(const mail::imapFolder &c) -{ - mail::folder::operator=(c); - path=c.path; - hiersep=c.hiersep; - name=c.name; - - hasmessages=c.hasmessages; - hassubfolders=c.hassubfolders; - type=c.type; - return *this; -} - -mail::imapFolder::~imapFolder() -{ -} - -void mail::imapFolder::hasMessages(bool flag) -{ - hasmessages=flag; -} - -void mail::imapFolder::hasSubFolders(bool flag) -{ - hassubfolders=flag; -} - -string mail::imapFolder::getName() const -{ - return name; -} - -string mail::imapFolder::getPath() const -{ - return path; -} - -bool mail::imapFolder::isParentOf(string cpath) const -{ - if (isDestroyed()) - return false; - - string pfix=path + hiersep; - - if (imapAccount.smap) - pfix += "/"; // SMAP implies this - - return (cpath.size() > pfix.size() && - pfix == cpath.substr(0, pfix.size())); -} - -bool mail::imapFolder::hasMessages() const -{ - return hasmessages; -} - -bool mail::imapFolder::hasSubFolders() const -{ - return hassubfolders; -} - -void mail::imapFolder::getParentFolder(callback::folderList &callback1, - callback &callback2) const -{ - if (isDestroyed(callback2)) - return; - - string sep=hiersep; - - if (imapAccount.smap) - sep="/"; // SMAP implied - - if (sep.size() > 0) - { - size_t n=path.rfind(sep[0]); - - if (n != std::string::npos) - { - mail::account &a=imapAccount; - - a.findFolder(path.substr(0, n), - callback1, callback2); - return; - } - } - - mail::imapFolder topFolder( *this ); - - topFolder.path=""; - topFolder.hiersep=""; - topFolder.hasmessages=false; - topFolder.hassubfolders=true; - topFolder.name=""; - - vector<const mail::folder *> array; - - array.push_back(&topFolder); - - callback1.success(array); - callback2.success("OK"); -} - -void mail::imapFolder::readSubFolders(mail::callback::folderList &callback1, - mail::callback &callback2) - const -{ - if (isDestroyed(callback2)) - return; - - imapAccount.readSubFolders(path + hiersep, callback1, callback2); -} - -mail::addMessage *mail::imapFolder::addMessage(mail::callback &callback) const -{ - if (isDestroyed(callback)) - return NULL; - - return imapAccount.addMessage(path, callback); -} - -void mail::imapFolder::readFolderInfo(mail::callback::folderInfo &callback1, - mail::callback &callback2) const -{ - if (isDestroyed(callback2)) - return; - - if (imapAccount.currentFolder && - imapAccount.currentFolder->path == path) - { - imapFOLDERinfo *f=imapAccount.currentFolder; - - vector<imapFOLDERinfo::indexInfo>::iterator b, e; - - b=f->index.begin(); - e=f->index.end(); - - callback1.messageCount=f->index.size(); - callback1.unreadCount=0; - - while (b != e) - { - if (b->unread) - ++callback1.unreadCount; - b++; - } - callback1.success(); - callback2.success("OK"); - return; - } - - if (!imapAccount.smap && callback1.fastInfo && - !imapAccount.hasCapability(LIBMAIL_CHEAPSTATUS)) - { - callback2.success("OK"); - return; - } - - imapAccount.folderStatus(path, callback1, callback2); -} - -////////////////////////////////////////////////////////////////////////////// -// -// CREATE a subfolder of an existing folder. First, issue a LIST to -// determine the eventual hierarchy separator character, followed by a CREATE. -// -// imapCREATE is also commandeered to rename a folder, since the processing -// is rather similar. - -LIBMAIL_START - -class imapCREATE : public imapCommandHandler { - - string renamePath; // If not empty, this is a rename - string parentPath; - string name; - string encodedname; - bool hasMessages; - bool hasSubfolders; - mail::callback::folderList &callback1; - mail::callback &callback2; - - bool listHierSent; - vector <imapFolder> hiersep; // Results of LIST for the hier sep - -public: - imapCREATE(string parentPathArg, // path + hiersep - string nameArg, - bool hasMessagesArg, - bool hasSubfoldersArg, - mail::callback::folderList &callback1Arg, - mail::callback &callback2Arg); - - imapCREATE(string renamePathArg, - string parentPathArg, // path + hiersep - string nameArg, - bool hasMessagesArg, - bool hasSubfoldersArg, - mail::callback::folderList &callback1Arg, - mail::callback &callback2Arg); - - void installed(imap &imapAccount); - -private: - const char *getName(); - void timedOut(const char *errmsg); - - bool untaggedMessage(imap &imapAccount, string msgname); - - bool taggedMessage(imap &imapAccount, string msgname, - string message, - bool okfail, string errmsg); -}; - -LIBMAIL_END - -mail::imapCREATE::imapCREATE(string parentPathArg, - string nameArg, - bool hasMessagesArg, - bool hasSubfoldersArg, - mail::callback::folderList &callback1Arg, - mail::callback &callback2Arg) - : renamePath(""), - parentPath(parentPathArg), - name(nameArg), - hasMessages(hasMessagesArg), - hasSubfolders(hasSubfoldersArg), - callback1(callback1Arg), - callback2(callback2Arg), - listHierSent(false) -{ -} - -mail::imapCREATE::imapCREATE(string renamePathArg, - string parentPathArg, - string nameArg, - bool hasMessagesArg, - bool hasSubfoldersArg, - mail::callback::folderList &callback1Arg, - mail::callback &callback2Arg) - : renamePath(renamePathArg), - parentPath(parentPathArg), - name(nameArg), - hasMessages(hasMessagesArg), - hasSubfolders(hasSubfoldersArg), - callback1(callback1Arg), - callback2(callback2Arg), - listHierSent(false) -{ -} - -void mail::imapCREATE::installed(mail::imap &imapAccount) -{ - // First things first, get the hier separator. - - imapAccount.imapcmd("CREATE", "LIST " - + imapAccount.quoteSimple(parentPath + "tree") - + " \"\"\r\n"); -} - -const char *mail::imapCREATE::getName() -{ - return "CREATE"; -} - -void mail::imapCREATE::timedOut(const char *errmsg) -{ - callbackTimedOut(callback2, errmsg); -} - -bool mail::imapCREATE::untaggedMessage(mail::imap &imapAccount, string msgname) -{ - if (msgname == "LIST") // Untagged LIST replies - { - hiersep.clear(); - imapAccount.installBackgroundTask( new mail::imapLIST(hiersep, - 0, true)); - return true; - } - return false; -} - -bool mail::imapCREATE::taggedMessage(mail::imap &imapAccount, string msgname, - string message, - bool okfail, string errmsg) -{ - if (msgname != "CREATE") - return false; - - if (!okfail) - { - callback2.fail(errmsg); - imapAccount.uninstallHandler(this); - return true; - } - - if (!listHierSent) - { - if (hiersep.size() == 0) - { - callback2.fail("IMAP server failed to process the LIST command."); - imapAccount.uninstallHandler(this); - return true; - } - - - listHierSent=true; - encodedname=name; - - // The folder name should be utf7-encoded - - { - char *p=unicode_convert_toutf8(encodedname.c_str(), - unicode_default_chset(), - NULL); - - if (!p && strchr(p, *hiersep[0].getHierSep().c_str()) - != NULL) - { - if (p) - free(p); - callback2.fail("Folder name contains an invalid character."); - imapAccount.uninstallHandler(this); - return true; - } - free(p); - - - p=unicode_convert_tobuf(encodedname.c_str(), - unicode_default_chset(), - unicode_x_imap_modutf7, - NULL); - - if (p) - { - try { - encodedname=p; - free(p); - } catch (...) { - free(p); - LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); - } - } - } - - - imapAccount.imapcmd("CREATE", - (renamePath.size() > 0 - ? string("RENAME ") + - imapAccount.quoteSimple(renamePath) + " ": - string("CREATE ")) + - imapAccount - .quoteSimple(parentPath + - encodedname + - (!hasMessages ? - hiersep[0].getHierSep() - :"")) - + "\r\n"); - return true; - - } - - mail::imapFolder new_folder(imapAccount, parentPath + encodedname, - hiersep[0].getHierSep(), - name, -1); - - new_folder.hasMessages(hasMessages); - new_folder.hasSubFolders(hasSubfolders); - - vector<const mail::folder *> dummy_list; - - dummy_list.push_back(&new_folder); - - callback1.success(dummy_list); - callback2.success(errmsg); - imapAccount.uninstallHandler(this); - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Creating a previously known folder, from scratch. This is much easier. - -LIBMAIL_START - -class imapRECREATE : public imapCommandHandler { - - string path; - mail::callback &callback; - -public: - imapRECREATE(string pathArg, mail::callback &callbackArg); - ~imapRECREATE(); - - void installed(imap &imapAccount); - - const char *getName(); - void timedOut(const char *errmsg); - - bool untaggedMessage(imap &imapAccount, string msgname); - - bool taggedMessage(imap &imapAccount, string msgname, - string message, - bool okfail, string errmsg); -}; - -LIBMAIL_END - -mail::imapRECREATE::imapRECREATE(string pathArg, - mail::callback &callbackArg) - : path(pathArg), callback(callbackArg) -{ -} - -mail::imapRECREATE::~imapRECREATE() -{ -} - -void mail::imapRECREATE::installed(mail::imap &imapAccount) -{ - imapAccount.imapcmd("CREATE", "CREATE " - + imapAccount.quoteSimple(path) + "\r\n"); -} - -const char *mail::imapRECREATE::getName() -{ - return "CREATE"; -} - -void mail::imapRECREATE::timedOut(const char *errmsg) -{ - callbackTimedOut(callback, errmsg); -} - -bool mail::imapRECREATE::untaggedMessage(mail::imap &imapAccount, string msgname) -{ - return false; -} - -bool mail::imapRECREATE::taggedMessage(mail::imap &imapAccount, string msgname, - string message, - bool okfail, string errmsg) -{ - if (msgname == "CREATE") - { - if (okfail) - callback.success(errmsg); - else - callback.fail(errmsg); - imapAccount.uninstallHandler(this); - return true; - } - return false; -} - -/////////////////////////////////////////////////////////////////////////// -// -// DELETE a folder. - -LIBMAIL_START - -class imapDELETE : public imapCommandHandler { - mail::callback &callback; - string path; - -public: - imapDELETE(mail::callback &callbackArg, - string pathArg); - - void installed(imap &imapAccount); - -private: - const char *getName(); - void timedOut(const char *errmsg); - bool untaggedMessage(imap &imapAccount, string name); - - bool taggedMessage(imap &imapAccount, string name, - string message, - bool okfail, string errmsg); -}; - -LIBMAIL_END - -mail::imapDELETE::imapDELETE(mail::callback &callbackArg, - string pathArg) - : callback(callbackArg), path(pathArg) -{ -} - -void mail::imapDELETE::installed(mail::imap &imapAccount) -{ - imapAccount.imapcmd("DELETE", "DELETE " + imapAccount.quoteSimple(path) - + "\r\n"); -} - -const char *mail::imapDELETE::getName() -{ - return "DELETE"; -} - -void mail::imapDELETE::timedOut(const char *errmsg) -{ - callbackTimedOut(callback, errmsg); -} - -bool mail::imapDELETE::untaggedMessage(mail::imap &imapAccount, string name) -{ - return false; -} - -bool mail::imapDELETE::taggedMessage(mail::imap &imapAccount, string name, - string message, - bool okfail, string errmsg) -{ - if (name == "DELETE") - { - if (okfail) - callback.success(errmsg); - else - callback.fail(errmsg); - imapAccount.uninstallHandler(this); - return true; - } - return false; -} - -///////////////////////////////////////////////////////////////////////////// - -void mail::imapFolder::createSubFolder(string name, bool isDirectory, - mail::callback::folderList &callback1, - mail::callback &callback2) const -{ - if (isDestroyed(callback2)) - return; - - if (!imapAccount.ready(callback2)) - return; - - if (imapAccount.smap) - { - mail::smapCREATE *h= - new mail::smapCREATE(path, name, isDirectory, - callback1, callback2); - - if (!h) - { - callback2.fail(strerror(errno)); - return; - } - - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } - - return; - } - - mail::imapCREATE *h=new mail::imapCREATE(path + hiersep, - name, - !isDirectory, - isDirectory, - callback1, - callback2); - if (!h) - { - callback2.fail(strerror(errno)); - return; - } - - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } -} - -void mail::imapFolder::renameFolder(const folder *newParent, - std::string newName, - mail::callback::folderList &callback1, - callback &callback2) const -{ - if (isDestroyed(callback2)) - return; - - if (!imapAccount.ready(callback2)) - return; - - imapAccount.sameServerFolderPtr=NULL; - - string newPath=""; - - if (newParent) - { - newParent->sameServerAsHelperFunc(); - - if (imapAccount.sameServerFolderPtr == NULL) - { - callback2.fail("mail::imapFolder::renameFolder -" - " invalid destination folder object."); - return; - } - - newPath=imapAccount.sameServerFolderPtr->path + - imapAccount.sameServerFolderPtr->hiersep; - } - - imapHandler *h=imapAccount.smap ? - (imapHandler *) - new mail::smapCREATE(path, newPath, newName, - callback1, callback2) : - new mail::imapCREATE(path, newPath, newName, - hasmessages, - hassubfolders, - callback1, - callback2); - - if (!h) - { - callback2.fail(strerror(errno)); - return; - } - - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } -} - -void mail::imapFolder::create(bool isDirectory, mail::callback &callback2) - const -{ - if (isDestroyed(callback2)) - return; - if (!imapAccount.ready(callback2)) - return; - - if (imapAccount.smap) - { - mail::smapCREATE *h= - new mail::smapCREATE(path, isDirectory, callback2); - - if (!h) - { - callback2.fail(strerror(errno)); - return; - } - - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } - return; - } - - mail::imapRECREATE *h=new mail::imapRECREATE(path + (isDirectory ? - hiersep:""), - callback2); - if (!h) - { - callback2.fail(strerror(errno)); - return; - } - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } -} - -void mail::imapFolder::destroy(mail::callback &callback, bool subdirs) const -{ - if (isDestroyed(callback)) - return; - - if (!imapAccount.ready(callback)) - return; - - imapHandler *h=imapAccount.smap ? (imapHandler *) - new mail::smapDELETE(path, subdirs, callback) - : new mail::imapDELETE(callback, - path + (subdirs ? hiersep:"")); - - if (!h) - { - callback.fail(strerror(errno)); - return; - } - try { - imapAccount.installForegroundTask(h); - } catch (...) { - delete h; - throw; - } -} - -void mail::imapFolder::open(mail::callback &openCallback, - mail::snapshot *restoreSnapshot, - mail::callback::folder &folderCallback) const -{ - if (isDestroyed(openCallback)) - return; - imapAccount.openFolder(path, restoreSnapshot, - openCallback, folderCallback); -} - - -mail::folder *mail::imapFolder::clone() const -{ - mail::imapFolder *i=new mail::imapFolder(*this); - - if (i) return i; - return NULL; -} - -string mail::imapFolder::toString() const -{ - string s=""; - - int i; - - for (i=0; i<3; i++) - { - if (i > 0) - s.append(":",1); - - string ss; - - string::iterator b, e; - - switch (i) { - case 0: - ss=path; - break; - case 1: - ss=hiersep; - break; - default: - ss=name; - break; - } - - b=ss.begin(); - e=ss.end(); - - while (b != e) - { - if (*b == '\\' || *b == ':') - s.append("\\", 1); - s.append(&*b, 1); - b++; - } - } - - s += ":"; - if (hasMessages()) - s += "S"; - if (hasSubFolders()) - s += "C"; - - return s; -} - -void mail::imapFolder::getMyRights(callback &getCallback, string &rights) - const -{ - if (isDestroyed(getCallback)) - return; - - if (!imapAccount.ready(getCallback)) - return; - - if (!imapAccount.hasCapability("ACL")) - { - mail::folder::getMyRights(getCallback, rights); - return; - } - - string s=getPath(); - - if (s.find('\r') != std::string::npos || - s.find('\n') != std::string::npos) // Sanity check - { - getCallback.fail(strerror(EINVAL)); - return; - } - - - if (imapAccount.smap) - { - if (imapAccount.getCapability("ACL") == "ACL") - { - // SMAP uses ACL2 - - mail::folder::getMyRights(getCallback, rights); - return; - } - - smapACL *sa=new smapACL(s, rights, getCallback); - - if (!sa) - { - getCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sa); - } catch (...) - { - delete sa; - throw; - } - return; - } - - imapGetMyRights *gm=new imapGetMyRights(s, rights, - getCallback); - - if (!gm) - { - getCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(gm); - } catch (...) { - delete gm; - throw; - } -} - -void mail::imapFolder::getRights(callback &getCallback, - list<pair<string, string> > &rights) const -{ - if (isDestroyed(getCallback)) - return; - - if (!imapAccount.ready(getCallback)) - return; - - if (!imapAccount.hasCapability("ACL")) - { - mail::folder::getRights(getCallback, rights); - return; - } - - string s=getPath(); - - if (s.find('\r') != std::string::npos || - s.find('\n') != std::string::npos) // Sanity check - { - getCallback.fail(strerror(EINVAL)); - return; - } - - if (imapAccount.smap) - { - if (imapAccount.getCapability("ACL") == "ACL") - { - // SMAP uses ACL2 - - mail::folder::getRights(getCallback, rights); - return; - } - - smapGETACL *sa=new smapGETACL(s, rights, getCallback); - - if (!sa) - { - getCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sa); - } catch (...) - { - delete sa; - throw; - } - return; - } - - imapGetRights *gr=new imapGetRights(s, rights, - getCallback); - - if (!gr) - { - getCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(gr); - } catch (...) { - delete gr; - throw; - } -} - -void mail::imapFolder::setRights(callback &setCallback, - string &errorIdentifier, - vector<string> &errorRights, - string identifier, - string rights) const -{ - errorIdentifier=""; - errorRights.clear(); - if (isDestroyed(setCallback)) - return; - - if (!imapAccount.ready(setCallback)) - return; - - if (!imapAccount.hasCapability("ACL")) - { - mail::folder::setRights(setCallback, - errorIdentifier, - errorRights, - identifier, rights); - return; - } - - string s=getPath(); - - if (s.find('\r') != std::string::npos || - s.find('\n') != std::string::npos || - identifier.find('\r') != std::string::npos || - identifier.find('\n') != std::string::npos || - rights.find('\r') != std::string::npos || - rights.find('\n') != std::string::npos) // Sanity check - { - setCallback.fail(strerror(EINVAL)); - return; - } - - if (imapAccount.smap) - { - if (imapAccount.getCapability("ACL") == "ACL") - { - // SMAP uses ACL2 - - mail::folder::setRights(setCallback, - errorIdentifier, - errorRights, - identifier, rights); - return; - } - - smapSETACL *sa=new smapSETACL(s, identifier, rights, - false, - errorIdentifier, - errorRights, - setCallback); - - if (!sa) - { - setCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sa); - } catch (...) - { - delete sa; - throw; - } - return; - } - - - - - /* Fix ACL/ACL2 brokenness */ - - if (rights.find(ACL_DELETEMSGS[0]) != std::string::npos && - rights.find(ACL_DELETEFOLDER[0]) != std::string::npos && - rights.find(ACL_EXPUNGE[0]) != std::string::npos) - { - size_t p=rights.find(ACL_DELETEMSGS[0]); - - rights.erase(rights.begin()+p, rights.begin()+p+1); - p=rights.find(ACL_DELETEFOLDER[0]); - rights.erase(rights.begin()+p, rights.begin()+p+1); - p=rights.find(ACL_EXPUNGE[0]); - rights.erase(rights.begin()+p, rights.begin()+p+1); - - rights += ACL_DELETE_SPECIAL; - } - - imapSetRights *sr=new imapSetRights(s, identifier, rights, - false, - errorIdentifier, - errorRights, - setCallback); - - if (!sr) - { - setCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sr); - } catch (...) { - delete sr; - throw; - } -} - -void mail::imapFolder::delRights(callback &setCallback, - string &errorIdentifier, - vector<std::string> &errorRights, - string identifier) const -{ - errorIdentifier=""; - errorRights.clear(); - if (isDestroyed(setCallback)) - return; - - if (!imapAccount.ready(setCallback)) - return; - - if (!imapAccount.hasCapability("ACL")) - { - mail::folder::delRights(setCallback, - errorIdentifier, - errorRights, - identifier); - return; - } - - string s=getPath(); - - if (s.find('\r') != std::string::npos || - s.find('\n') != std::string::npos) // Sanity check - { - setCallback.fail(strerror(EINVAL)); - return; - } - - if (imapAccount.smap) - { - if (imapAccount.getCapability("ACL") == "ACL") - { - // SMAP uses ACL2 - - mail::folder::delRights(setCallback, - errorIdentifier, - errorRights, - identifier); - return; - } - - smapSETACL *sa=new smapSETACL(s, identifier, "", - true, - errorIdentifier, - errorRights, - setCallback); - - if (!sa) - { - setCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sa); - } catch (...) - { - delete sa; - throw; - } - return; - } - imapSetRights *sr=new imapSetRights(s, identifier, "", - true, - errorIdentifier, - errorRights, - setCallback); - - if (!sr) - { - setCallback.fail(strerror(errno)); - return; - } - - try - { - imapAccount.installForegroundTask(sr); - } catch (...) { - delete sr; - throw; - } -} - - -///////////////////////////////////////////////////////////////////////////// -// -// Adding a new message. - -LIBMAIL_START - -class imapAPPEND : public imapCommandHandler, - public addMessage { - - imap &imapAccount; - mail::callback &callback; - string path; - - bool continuationReceived; - - // Helper class that pushes the temp file's contents to the server. - - class Pusher : public fd::WriteBuffer { - - public: - - imapAPPEND *myappend; - - Pusher(); - ~Pusher(); - - bool fillWriteBuffer(); - }; - - Pusher *myPusher; -public: - friend class Pusher; - - FILE *tmpfileptr; - string appendcmd; - long bytes; - long bytesDone; - long bytesTotal; - - imapAPPEND(imap &imapArg, - mail::callback &callbackArg, - string pathArg); - ~imapAPPEND(); - - void installed(imap &imapAccount); - - - void saveMessageContents(string txt); - void go(); - void fail(string errmsg); - -private: - const char *getName(); - void timedOut(const char *timedout); - bool untaggedMessage(imap &imapAccount, string msgname); - bool taggedMessage(imap &imapAccount, string msgname, - string message, - bool okfail, string errmsg); - bool continuationRequest(imap &imapAccount, string msg); - - bool fillWriteBuffer(); - - -}; - -LIBMAIL_END - -mail::imapAPPEND::imapAPPEND(mail::imap &imapArg, - mail::callback &callbackArg, - string pathArg) - : mail::addMessage(&imapArg), - imapAccount(imapArg), callback(callbackArg), path(pathArg), - continuationReceived(false), myPusher(NULL), tmpfileptr(NULL) -{ -} - -mail::imapAPPEND::~imapAPPEND() -{ - if (tmpfileptr) - fclose(tmpfileptr); - if (myPusher) - myPusher->myappend=NULL; -} - -const char *mail::imapAPPEND::getName() -{ - return "APPEND"; -} - -void mail::imapAPPEND::timedOut(const char *timedout) -{ - callbackTimedOut(callback, timedout); -} - -// The application pushes the message's contents here. Save the contents -// into a temporary file, using CRNL line termination. - -void mail::imapAPPEND::saveMessageContents(string s) -{ - string::iterator b=s.begin(), e=s.end(); - - while (b != e) - { - char c= *b++; - - if (c == '\n') - putc('\r', tmpfileptr); - putc(c, tmpfileptr); - } -} - - -void mail::imapAPPEND::installed(mail::imap &imapAccount) -{ - myPusher=new Pusher(); - - if (!myPusher) - LIBMAIL_THROW("Out of memory."); - - try { - imapAccount.imapcmd("APPEND", appendcmd); - imapAccount.socketWrite(myPusher); - myPusher->myappend=this; - } catch (...) { - delete myPusher; - myPusher=NULL; - } -} - -bool mail::imapAPPEND::untaggedMessage(mail::imap &imapAccount, string msgname) -{ - return false; -} - -bool mail::imapAPPEND::continuationRequest(mail::imap &imapAccount, string msg) -{ - continuationReceived=true; // Tell pusher the show's on. - return true; -} - -bool mail::imapAPPEND::taggedMessage(mail::imap &imapAccount, string name, - string message, - bool okfail, string errmsg) -{ - if (name == "APPEND") - { - if (okfail) - callback.success(errmsg); - else - callback.fail(errmsg); - imapAccount.uninstallHandler(this); - return true; - } - return false; -} - -bool mail::imapAPPEND::fillWriteBuffer() -{ - char buffer[BUFSIZ]; - - if (!continuationReceived) - return true; - - if (bytes <= 0) - { - callback.reportProgress(bytesTotal, bytesTotal, 0, 1); - return false; - } - - int n=fread(buffer, 1, bytes > (long)sizeof(buffer) - ? sizeof(buffer):bytes, tmpfileptr); - - if (n <= 0) - { - n=bytes > (long)sizeof(buffer) ? sizeof(buffer):bytes; - memset(buffer, '\n', n); - } - - bytes -= n; - bytesDone += n; - setTimeout(); - callback.reportProgress(bytesDone, bytesTotal, 0, 1); - myPusher->writebuffer.insert(myPusher->writebuffer.end(), - buffer, buffer+n); - return true; -} - -mail::imapAPPEND::Pusher::Pusher() : myappend(NULL) -{ -} - -mail::imapAPPEND::Pusher::~Pusher() -{ - if (myappend) - myappend->myPusher=NULL; -} - -bool mail::imapAPPEND::Pusher::fillWriteBuffer() -{ - if (!myappend) - return false; - - return myappend->fillWriteBuffer(); -} - -void mail::imap::addSmapFolderCmd(mail::smapAddMessage *add, - std::string path) -{ - vector<string> words; - smapHandler::path2words(path, words); - - vector<string>::iterator b, e; - - string pstr="ADD FOLDER "; - - b=words.begin(); - e=words.end(); - - while (b != e) - { - pstr += " "; - pstr += quoteSMAP( *b ); - b++; - } - - pstr += " \"\"\n"; - - add->cmds.push_back(pstr); -} - -mail::folder *mail::imap::getSendFolder(const smtpInfo &info, - const mail::folder *folder, - std::string &errmsg) -{ - if (!smap) - return mail::account::getSendFolder(info, folder, errmsg); - - if (folder) - { - sameServerFolderPtr=NULL; - folder->sameServerAsHelperFunc(); - if (!sameServerFolderPtr) - return mail::account::getSendFolder(info, folder, - errmsg); - } - - if (info.recipients.size() == 0) - { - errno=ENOENT; - errmsg="Empty recipient list."; - return NULL; - } - - mail::folder *f= - new smapSendFolder(this, info, folder ? folder->getPath():""); - - if (!f) - errmsg=strerror(errno); - return f; -} - -mail::addMessage *mail::imap::addMessage(string path, - mail::callback &callback) -{ - if (smap) - { - mail::smapAddMessage *add=new - smapAddMessage(*this, callback); - - if (!add) - { - callback.fail(strerror(errno)); - return NULL; - } - - try { - addSmapFolderCmd(add, path); - } catch (...) { - delete add; - add=NULL; - } - return add; - } - - mail::imapAPPEND *append=new mail::imapAPPEND(*this, callback, path); - - if (!append) - { - callback.fail(strerror(errno)); - return NULL; - } - - if ((append->tmpfileptr=tmpfile()) == NULL) - { - callback.fail(strerror(errno)); - delete append; - return NULL; - } - - time(&append->messageDate); - - return append; -} - -void mail::imapAPPEND::fail(string errmsg) -{ - callback.fail(errmsg); - delete this; -} - -void mail::imapAPPEND::go() -{ - if (!checkServer()) - return; - - if (!imapAccount.ready(callback)) - { - delete this; - return; - } - - try { - - string flags=imapAccount.messageFlagStr(messageInfo); - - fprintf(tmpfileptr, "\r\n"); - - // Part of the APPEND cmd, actually - - bytesDone=0; - - if (fflush(tmpfileptr) < 0 || ferror(tmpfileptr) - || (bytes=ftell(tmpfileptr)) == -1 - || fseek(tmpfileptr, 0L, SEEK_SET) < 0) - { - callback.fail(strerror(errno)); - delete this; - return; - } - - bytesTotal=bytes; - - string cnt_s; - - { - ostringstream o; - - o << bytes-2; - cnt_s=o.str(); - } - - char buffer[100]; - - rfc822_mkdate_buf(messageDate, buffer); - - char *p=strchr(buffer, ','); - - if (p && *++p && *++p) - { - char *q=strchr(p, ' '); - - if (q) - *q='-'; - - q=strchr(p, ' '); - - if (q) - *q='-'; - } - else - p=buffer; - - appendcmd="APPEND " + imapAccount.quoteSimple(path) - + " (" + flags + ") " - + imapAccount.quoteSimple(p) - + " {" + cnt_s + "}\r\n"; - - imapAccount.installForegroundTask(this); - } catch (...) { - callback.fail(strerror(errno)); - delete this; - } -} - -#if 0 -bool mail::imapFolder:sameServerAs(const mail::folder *f) const -{ - if (isDestroyed()) - return false; - - imapAccount.sameServerHelperFlag=false; - - f->sameServerAsHelperFunc(); - - return imapAccount.sameServerHelperFlag; -} -#endif - -void mail::imapFolder::sameServerAsHelperFunc() const -{ - if (isDestroyed()) - return; - - imapAccount.sameServerFolderPtr=this; -} |
