void mail::addressbook::getEntry( string uid, vector<T> &addrListArg, mail::callback &callback) { size_t n=index.size(); size_t i; for (i=0; i<n; i++) if (server->getFolderIndexInfo(i).uid == uid) { GetAddressList<T> *get= new GetAddressList<T>(this, i, addrListArg, callback); if (!get) { callback.fail(strerror(errno)); return; } try { get->go(); } catch (...) { delete get; LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } return; } callback.success("NOT FOUND."); }
void mail::maildir::folder::destroy(mail::callback &callback, bool destroyDir) const { if (isDestroyed(callback)) return; if (!destroyDir) // Folder directories are imaginary, cannot be nuked { string s; char *d=maildir_name2dir(maildirAccount->path.c_str(), path.c_str()); if (!d) { callback.fail(strerror(errno)); return; } try { s=d; free(d); } catch (...) { free(d); LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } if (!mail::maildir::maildirdestroy(s)) { callback.fail(strerror(errno)); return; } } callback.success("Mail folder deleted"); }
void mail::maildir::saveFolderIndexInfo(size_t msgNum, const mail::messageInfo &info, mail::callback &callback) { if (msgNum >= index.size()) { callback.success("OK"); return; } mail::messageInfo &newFlags=index[msgNum]; #define DOFLAG(dummy, field, dummy2) \ newFlags.field=info.field; LIBMAIL_MSGFLAGS; #undef DOFLAG string errmsg="Message updated"; if (!updateFlags(msgNum)) errmsg="Folder opened in read-only mode."; callback.success(errmsg); }
void mail::mbox::findFolder(string path, mail::callback::folderList &callback1, mail::callback &callback2) { if (path.size() == 0) path=rootPath; else if (path[0] != '/' && path != "INBOX") path=rootPath + "/" + path; folder *f=new folder(path, *this); if (!f) { callback2.fail(path + ": " + strerror(errno)); return; } try { vector<const mail::folder *> folder_list; folder_list.push_back(f); callback1.success(folder_list); callback2.success("OK"); delete f; } catch (...) { delete f; LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } }
void mail::maildir::folder::readFolderInfo( mail::callback::folderInfo &callback1, mail::callback &callback2) const { if (isDestroyed(callback2)) return; callback1.messageCount=0; callback1.unreadCount=0; vector<maildirMessageInfo> dummyIndex; if (!maildirAccount->scan(path, dummyIndex, true)) { callback1.success(); callback2.fail("Invalid folder"); return; } vector<maildirMessageInfo>::iterator b=dummyIndex.begin(), e=dummyIndex.end(); while (b != e) { callback1.messageCount++; if ( b->unread) callback1.unreadCount++; b++; } callback1.success(); callback2.success("OK"); }
void mail::maildir::folder::create(bool isDirectory, mail::callback &callback) const { if (!doCreate(isDirectory)) { callback.fail(strerror(errno)); } else { callback.success("Mail folder created"); } }
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::maildir::folder::createSubFolder(string name, bool isDirectory, mail::callback::folderList &callback1, mail::callback &callback2) const { if (isDestroyed(callback2)) return; // The name of the folder is translated from the local charset // to modified UTF-7 (Courier-IMAP compatibility), with the following // blacklisted characters: char *p=libmail_u_convert_tobuf(name.c_str(), unicode_default_chset(), unicode_x_imap_modutf7 " ./~:", NULL); if (!p) { callback2.fail(strerror(errno)); return; } std::string nameutf7; errno=ENOMEM; try { nameutf7=p; free(p); } catch (...) { free(p); callback2.fail(strerror(errno)); return; } mail::maildir::folder newFolder(maildirAccount, path + "." + nameutf7); newFolder.hasMessagesFlag= ! (newFolder.hasSubfoldersFlag= isDirectory); if (!newFolder.doCreate(isDirectory)) { callback2.fail(strerror(errno)); return; } vector<const mail::folder *> folders; folders.push_back(&newFolder); callback1.success( folders ); callback2.success("Mail folder created"); }
void mail::mbox::folder::open(mail::callback &openCallback, snapshot *restoreSnapshot, mail::callback::folder &folderCallback) const { if (mboxAccount.currentFolder.size() == 0 && mboxAccount.folderDirty) { closeCallback *cc=new closeCallback(&mboxAccount, openCallback, folderCallback, path); if (!cc) { openCallback.fail("Out of memory."); return; } try { mboxAccount .installTask(new mail::mbox ::ExpungeTask(mboxAccount, *cc, false, NULL)); } catch (...) { delete cc; LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } return; } mboxAccount.installTask(new mail::mbox::OpenTask(mboxAccount, path, openCallback, &folderCallback)); }
void mail::addressbook::searchNickname( string nickname, vector<T> &addrListArg, mail::callback &callback) { Search<T> *s=new Search<T>(this, addrListArg, callback); if (!s) { callback.fail(strerror(errno)); return; } try { size_t n=index.size(); size_t i; for (i=0; i<n; i++) if (index[i].nickname == nickname) s->uidList.push_back(server-> getFolderIndexInfo(i) .uid); s->go(); } catch (...) { delete s; LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } }
void mail::imap::findFolder(string folder, mail::callback::folderList &callback1, mail::callback &callback2) { if (!ready(callback2)) return; if (folder.size() == 0) // Top level hierarchy { mail::imapFolder f(*this, "", "", "", -1); f.hasMessages(false); f.hasSubFolders(true); vector<const mail::folder *> list; list.push_back(&f); callback1.success(list); callback2.success("OK"); return; } installForegroundTask( smap ? (imapHandler *) new mail::smapLISToneFolder(folder, callback1, callback2) : new mail::imapListHandler(callback1, callback2, folder_chset(), folder, true)); }
void mail::mbox::saveFolderIndexInfo(size_t messageNum, const mail::messageInfo &info, mail::callback &callback) { MONITOR(mail::mbox); if (messageNum < index.size()) { folderDirty=true; #define DOFLAG(dummy1, field, dummy2) \ (index[messageNum].field= info.field) LIBMAIL_MSGFLAGS; #undef DOFLAG } callback.success(currentFolderReadOnly ? "Folder opened in read-only mode.": "Message updated."); if (! DESTROYED() && messageNum < index.size() && currentFolderCallback) currentFolderCallback->messageChanged(messageNum); }
void mail::addressbook::addEntry(Entry &newEntry, string olduid, mail::callback &callback) { vector<Index>::iterator b=index.begin(), e=index.end(); while (b != e) { Index &i= *b++; if (olduid.size() > 0 && i.uid == olduid) continue; if (newEntry.nickname == i.nickname) { callback.fail("Address book entry with the same name already exists."); return; } } Add *add=new Add(this, newEntry, olduid, callback); try { add->go(); } catch (...) { delete add; } }
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; } }
mail::maildir::maildir(mail::callback::disconnect &disconnect_callback, mail::callback &callback, string pathArg) : mail::account(disconnect_callback), CONSTRUCTOR { if (init(callback, pathArg)) callback.success("Mail folders opened"); }
void mail::mbox::folder::createSubFolder(string name, bool isDirectory, mail::callback::folderList &callback1, mail::callback &callback2) const { string fpath; char *p=libmail_u_convert_tobuf(name.c_str(), unicode_default_chset(), unicode_x_imap_modutf7 " ./~:", NULL); if (!p) LIBMAIL_THROW("Out of memory."); try { fpath=path + "/" + p; free(p); } catch (...) { free(p); LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } if (isDirectory) { if (mkdir(fpath.c_str(), 0700) < 0) { callback2.fail(fpath + ": " + strerror(errno)); return; } } else { int fd= ::open(fpath.c_str(), O_RDWR|O_CREAT|O_EXCL, 0600); if (fd < 0) { callback2.fail(fpath + ": " + strerror(errno)); return; } close(fd); } folder newFolder(fpath, mboxAccount); vector<const mail::folder *> folderList; folderList.push_back(&newFolder); callback1.success(folderList); callback2.success("OK"); }
void mail::maildir::updateNotify(bool enableDisable, mail::callback &callback) { updateNotify(enableDisable); if (!enableDisable) updateFolderIndexInfo(&callback, false); else callback.success("OK"); }
void mail::mbox::updateFolderIndexInfo(mail::callback &callback) { if (currentFolder.size() == 0) { callback.success("Mail folder updated"); return; } installTask(new ExpungeTask(*this, callback, true, NULL)); }
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::maildir::logout(mail::callback &callback) { updateNotify(false); if (!calledDisconnected) { calledDisconnected=true; disconnect_callback.disconnected(""); } callback.success("OK"); }
void mail::mbox::logout(mail::callback &callback) { if (!folderDirty) { callback.success("Mail folder closed."); return; } // Something dirty needs to be saved. installTask(new ExpungeTask(*this, callback, false, NULL)); }
void mail::maildir::findFolder(string folder, mail::callback::folderList &callback1, mail::callback &callback2) { mail::maildir::folder tempFolder(this, folder); vector<const mail::folder *> folderList; folderList.push_back(&tempFolder); callback1.success(folderList); callback2.success("OK"); }
void mail::mbox::folder::create(bool isDirectory, mail::callback &callback) const { if (isDirectory) { if (mkdir(path.c_str(), 0700) < 0) { callback.fail(path + ": " + strerror(errno)); return; } } else { int fd= ::open(path.c_str(), O_RDWR|O_CREAT|O_EXCL, 0600); if (fd < 0) { callback.fail(path + ": " + strerror(errno)); return; } close(fd); } callback.success("OK"); }
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); }
void mail::mbox::updateFolderIndexFlags(const vector<size_t> &messages, bool doFlip, bool enableDisable, const mail::messageInfo &flags, mail::callback &callback) { vector<size_t>::const_iterator b, e; b=messages.begin(); e=messages.end(); size_t n=index.size(); while (b != e) { size_t i= *b++; if (i < n) { #define DOFLAG(dummy, field, dummy2) \ if (flags.field) \ { \ index[i].field=\ doFlip ? !index[i].field\ : enableDisable; \ } LIBMAIL_MSGFLAGS; #undef DOFLAG } } folderDirty=true; b=messages.begin(); e=messages.end(); MONITOR(mail::mbox); while (!DESTROYED() && b != e) { size_t i= *b++; if (i < n && currentFolderCallback) currentFolderCallback->messageChanged(i); } callback.success(!DESTROYED() && currentFolderReadOnly ? "Folder opened in read-only mode.": "Message updated."); }
void mail::maildir::moveMessagesTo(const vector<size_t> &messages, mail::folder *copyTo, mail::callback &callback) { sameServerFolderPtr=NULL; copyTo->sameServerAsHelperFunc(); if (sameServerFolderPtr == NULL) { mail::account::moveMessagesTo(messages, copyTo, callback); return; } string destFolderPath; char *p=maildir_name2dir(path.c_str(), sameServerFolderPtr->path.c_str()); if (!p) { callback.fail(strerror(errno)); return; } try { destFolderPath=p; free(p); } catch (...) { free(p); LIBMAIL_THROW(LIBMAIL_THROW_EMPTY); } vector<size_t>::const_iterator b=messages.begin(), e=messages.end(); while (b != e) { size_t n=*b++; string messageFn=getfilename(n); if (messageFn.size() > 0) { string destName= destFolderPath + messageFn.substr(messageFn.rfind('/')); rename(messageFn.c_str(), destName.c_str()); } } updateFolderIndexInfo(&callback, false); }
void mail::mbox::genericGetMessageStruct(string uid, size_t messageNumber, struct rfc2045 *&structRet, mail::callback &callback) { if (uid == cachedMessageUid && cachedMessageRfcp) { structRet=cachedMessageRfcp; callback.success("OK"); return; } installTask(new GenericGetMessageTask(*this, callback, uid, messageNumber, true, NULL, &structRet)); }
void mail::addressbook::getIndex( list< pair<string, std::string> > &listArg, mail::callback &callback) { size_t n=index.size(); size_t i; for (i=0; i<n; i++) { string nickname=index[i].nickname; string uid=index[i].uid; if (nickname.size() > 0 && uid.size() > 0) listArg.push_back( make_pair(nickname, uid)); } callback.success("Address book index retrieved"); }
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"); }
void mail::mbox::genericGetMessageFd(string uid, size_t messageNumber, bool peek, int &fdRet, mail::callback &callback) { if (uid == cachedMessageUid && cachedMessageFp) { fdRet=fileno(cachedMessageFp); callback.success("OK"); return; } installTask(new GenericGetMessageTask(*this, callback, uid, messageNumber, peek, &fdRet, NULL)); }