Пример #1
0
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);
}
Пример #2
0
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");
}
Пример #3
0
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.");
}
Пример #4
0
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);
}
Пример #5
0
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);
	}
}
Пример #6
0
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");
}
Пример #7
0
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));
}
Пример #8
0
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");
}
Пример #9
0
void mail::maildir::updateNotify(bool enableDisable,
				 mail::callback &callback)
{
	updateNotify(enableDisable);
	if (!enableDisable)
		updateFolderIndexInfo(&callback, false);
	else
		callback.success("OK");
}
Пример #10
0
void mail::mbox::updateFolderIndexInfo(mail::callback &callback)
{
	if (currentFolder.size() == 0)
	{
		callback.success("Mail folder updated");
		return;
	}

	installTask(new ExpungeTask(*this, callback, true, NULL));
}
Пример #11
0
void mail::maildir::logout(mail::callback &callback)
{
	updateNotify(false);

	if (!calledDisconnected)
	{
		calledDisconnected=true;
		disconnect_callback.disconnected("");
	}
	callback.success("OK");
}
Пример #12
0
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));
}
Пример #13
0
void mail::maildir::folder::create(bool isDirectory,
				   mail::callback &callback) const
{
	if (!doCreate(isDirectory))
	{
		callback.fail(strerror(errno));
	}
	else
	{
		callback.success("Mail folder created");
	}
}
Пример #14
0
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");
}
Пример #15
0
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);
}
Пример #16
0
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");
}
Пример #17
0
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.");
}
Пример #18
0
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));
}
Пример #19
0
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");
}
Пример #20
0
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");
}
Пример #21
0
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));
}
Пример #22
0
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");
}
Пример #23
0
void mail::maildir::readTopLevelFolders(mail::callback::folderList &callback1,
					mail::callback &callback2)
{
	mail::maildir::folder inbox(this, INBOX);
	mail::maildir::folder folders(this, INBOX);

	inbox.hasSubfoldersFlag=false;
	folders.hasMessagesFlag=false;

	vector<const mail::folder *> folderList;

	folderList.push_back(&inbox);

	if (!ispop3maildrop)
		folderList.push_back(&folders);

	callback1.success(folderList);
	callback2.success("OK");
}
Пример #24
0
void mail::maildir::updateFolderIndexFlags(const vector<size_t> &messages,
					   bool doFlip,
					   bool enableDisable,
					   const mail::messageInfo &flags,
					   mail::callback &callback)
{
	string errmsg="Message updated";

	vector<size_t>::const_iterator b, e;

	b=messages.begin();
	e=messages.end();

	size_t n=index.size();

	MONITOR(mail::maildir);

	while (!DESTROYED() && 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
		}

		if (!updateFlags(i))
			errmsg="Folder opened in read-only mode.";

	}

	callback.success(errmsg);
}
Пример #25
0
void mail::mbox::folder::readFolderInfo( mail::callback::folderInfo
					 &callback1,
					 mail::callback &callback2) const
{
	if (isDestroyed(callback2))
		return;

	callback1.messageCount=0;
	callback1.unreadCount=0;

	if (path.size() == 0)
	{
		callback1.success();
		callback2.success("OK");
		return;
	}

	mboxAccount.installTask(new mail::mbox::StatusTask(path, mboxAccount, callback2,
						    callback1));
}
Пример #26
0
void mail::mbox::genericGetMessageFdStruct(string uid,
					   size_t messageNumber,
					   bool peek,
					   int &fdRet,
					   struct rfc2045 *&structret,
					   mail::callback &callback)
{
	if (uid == cachedMessageUid && cachedMessageRfcp &&
	    cachedMessageFp)
	{
		structret=cachedMessageRfcp;
		fdRet=fileno(cachedMessageFp);
		callback.success("OK");
		return;
	}

	installTask(new GenericGetMessageTask(*this, callback,
					      uid, messageNumber,
					      peek,
					      &fdRet, &structret));
}
Пример #27
0
void mail::addressbook::del(std::string uid, mail::callback &callback)
{
	vector<Index>::iterator b=index.begin(), e=index.end();

	while (b != e)
	{
		if (b->uid == uid)
		{
			vector<size_t> msgList;

			msgList.push_back(b - index.begin());

			server->removeMessages(msgList, callback);
			return;
		}

		b++;
	}

	callback.success("OK");
}
Пример #28
0
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");
}
Пример #29
0
void mail::maildir::updateKeywords(const vector<size_t> &messages,
				   const set<string> &keywords,
				   bool setOrChange,
				   bool changeTo,
				   mail::callback &cb)
{
	bool keepGoing;

	if (folderPath.size() == 0)
	{
		cb.success("Ok.");
		return;
	}

	string dir;

	{
		char *dirs=maildir_name2dir(path.c_str(), folderPath.c_str());
		if (!dirs)
		{
			cb.fail(strerror(errno));
			return;
		}

		try {
			dir=dirs;
			free(dirs);
		} catch (...) {
			free(dirs);
			LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
		}
	}

	if (!setOrChange)
	{
		if (!updateKeywords(dir,
				    messages, keywords, setOrChange, changeTo,
				    NULL, NULL))
		{
			cb.fail(strerror(errno));
			return;
		}
	}
	else do {
		struct libmail_kwGeneric g;

		libmail_kwgInit(&g);

		char *imap_lock=NULL;

		if (lockFolder)
		{
			int flag;

			imap_lock=maildir_lock(dir.c_str(), lockFolder,
					       &flag);

			if (!imap_lock)
			{
				if (!flag)
				{
					libmail_kwgDestroy(&g);
					cb.fail(strerror(errno));
					return;
				}
			}
		}

		try {
			if (libmail_kwgReadMaildir(&g, dir.c_str()) < 0)
			{
				if (imap_lock)
				{
					unlink(imap_lock);
					free(imap_lock);
					imap_lock=NULL;
				}

				cb.fail(strerror(errno));
				return;
			}

			keepGoing=false;

			if (!updateKeywords(dir,
					    messages, keywords, setOrChange,
					    changeTo,
					    &g, &keepGoing))
			{
				if (imap_lock)
				{
					unlink(imap_lock);
					free(imap_lock);
					imap_lock=NULL;
				}
				libmail_kwgDestroy(&g);
				if (keepGoing)
					continue;

				cb.fail(strerror(errno));
				return;
			}
			if (imap_lock)
			{
				unlink(imap_lock);
				free(imap_lock);
				imap_lock=NULL;
			}
			libmail_kwgDestroy(&g);
		} catch (...) {
			if (imap_lock)
			{
				unlink(imap_lock);
				free(imap_lock);
				imap_lock=NULL;
			}
			libmail_kwgDestroy(&g);
			throw;
		}
	} while (keepGoing);

	cb.success("Message keywords updated.");
}
Пример #30
0
mail::mbox::mbox(bool magicInboxArg,
		       string folderRoot, mail::callback &callback,
		       mail::callback::disconnect &disconnect_callback)
	: mail::account(disconnect_callback),
	  calledDisconnected(false),
	  magicInbox(magicInboxArg),
	  inboxFolder("INBOX", *this),
	  hierarchyFolder("", *this),
	  currentFolderReadOnly(false),
	  folderSavedSize(0),
	  folderSavedTimestamp(0),
	  multiLockLock(NULL),
	  folderDirty(false),
	  newMessages(false),
	  cachedMessageRfcp(NULL),
	  cachedMessageFp(NULL),
	  currentFolderCallback(NULL)
{
	sigset_t ss;

	// Ignore SIGUSR2 from c-client

	sigemptyset(&ss);
	sigaddset(&ss, SIGUSR2);
	sigprocmask(SIG_BLOCK, &ss, NULL);

	const char *m=getenv("MAIL");

	string h=mail::homedir();
	struct passwd *pw=getpwuid(getuid());

	if (!pw || h.size() == 0)
	{
		callback.fail("Cannot find my home directory!");
		return;
	}


	inboxMailboxPath=h + "/Inbox";

	// Figure out the mail spool directory.

	if (m && *m)
		inboxSpoolPath=m;
	else
	{
		static const char *spools[]={"/var/spool/mail", "/var/mail",
					     "/usr/spool/mail", "/usr/mail",
					     0};

		size_t i;

		for (i=0; spools[i]; i++)
			if (access(spools[i], X_OK) == 0)
			{
				inboxSpoolPath=string(spools[i]) + "/"
					+ pw->pw_name;
				break;
			}

		if (!spools[i])
		{
			callback.fail("Cannot determine your system mailbox location,");
			return;
		}
	}

	if (folderRoot.size() > 0 && folderRoot[0] != '/')
		folderRoot=h + "/" + folderRoot;

	rootPath=folderRoot;

	// Initialize the top level folder.

	hierarchyFolder.path=folderRoot;
	hierarchyFolder.name=folder::defaultName(folderRoot);

	// First time through, create the top level folder directory, if
	// necessary.

	if (magicInboxArg)
		mkdir(folderRoot.c_str(), 0700);

	struct stat stat_buf;

	if (stat(folderRoot.c_str(), &stat_buf) == 0 &&
	    S_ISDIR(stat_buf.st_mode))
	{
		hierarchyFolder.hasMessages(false);
		hierarchyFolder.hasSubFolders(true);
	}
	else
	{
		hierarchyFolder.hasMessages(true);
		hierarchyFolder.hasSubFolders(false);
	}

	callback.success("Mail folder opened.");
}