summaryrefslogtreecommitdiffstats
path: root/libmail/imapfolders.C
diff options
context:
space:
mode:
Diffstat (limited to 'libmail/imapfolders.C')
-rw-r--r--libmail/imapfolders.C1637
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;
-}