diff options
Diffstat (limited to 'libmail/mbox.H')
| -rw-r--r-- | libmail/mbox.H | 470 | 
1 files changed, 470 insertions, 0 deletions
| diff --git a/libmail/mbox.H b/libmail/mbox.H new file mode 100644 index 0000000..f736503 --- /dev/null +++ b/libmail/mbox.H @@ -0,0 +1,470 @@ +/* +** Copyright 2002, Double Precision Inc. +** +** See COPYING for distribution information. +*/ +#ifndef libmail_mbox_H +#define libmail_mbox_H + +#include "libmail_config.h" +#include "mail.H" + +#include "unicode/unicode.h" +#include "maildir/maildirkeywords.h" + +#include <time.h> +#include <unistd.h> +#include <stdio.h> +#include <queue> +#include <map> +#include <set> +#include <vector> + +#include "mboxmagictag.H" +#include "generic.H" + +#include "namespace.H" + +struct ll_mail; + +LIBMAIL_START + +class file; + +///////////////////////////////////////////////////////////////////////// +// +// Legacy mbox driver. +// +// +class mbox : public mail::account, public generic { + +	void resumed(); +	void handler(std::vector<pollfd> &fds, int &timeout); + +	bool calledDisconnected; // True if the disconnect callback was invoked +	bool magicInbox;	// True if this account uses INBOX +	std::string inboxSpoolPath; // Path to the system spool inbox +	std::string inboxMailboxPath; // $HOME/mboxAccount + +	std::string rootPath;   // Root path for folders. + +	class folder : public mail::folder { + +		std::string path; +		std::string name; +		mbox &mboxAccount; + +		bool saveHasMessages; +		bool saveHasFolders; + +		class closeCallback : public mail::callback { + +			void reportProgress(size_t bytesCompleted, +					    size_t bytesEstimatedTotal, +			     +					    size_t messagesCompleted, +					    size_t messagesEstimatedTotal) {} +			//TODO + +		public: +			ptr<mbox> origmbox; +			mail::callback &origCallback; +			mail::callback::folder &origFolderCallback; +			std::string origPath; + +			closeCallback(mbox *origmboxArg, +				      mail::callback &origCallbackArg, +				      mail::callback::folder +				      &origFolderCallbackarg, +				      std::string origPathArg); +			~closeCallback(); + +			void success(std::string); +			void fail(std::string); +		}; + +		class add; + +	public: +		friend class mbox; + +		folder(std::string pathArg, +		       mbox &mboxArg); +		~folder(); + +		folder(const mbox::folder &); + +		static std::string defaultName(std::string path); + +		void sameServerAsHelperFunc() const; + +		std::string getName() const; +		std::string getPath() const; + +		bool hasMessages() const; +		bool hasSubFolders() const; + +		bool isParentOf(std::string path) const; + +		void hasMessages(bool); +		void hasSubFolders(bool); + + +		void getParentFolder(callback::folderList &callback1, +				     callback &callback2) const; + +		void readFolderInfo( mail::callback::folderInfo +				     &callback1, +				     mail::callback &callback2) const; + +		void readSubFolders( mail::callback::folderList &callback1, +				     mail::callback &callback2) const; + +		mail::addMessage *addMessage(mail::callback &callback) const; + +		void createSubFolder(std::string name, bool isDirectory, +				     mail::callback::folderList &callback1, +				     mail::callback &callback2) const; + +		void create(bool isDirectory, +			    mail::callback &callback) const; + +		void destroy(mail::callback &callback, bool destroyDir) +			const; + +		void renameFolder(const mail::folder *newParent, +				  std::string newName, +				  mail::callback::folderList &callback1, +				  callback &callback) const; + +		mail::folder *clone() const; +		std::string toString() const; + +		void open(mail::callback &openCallback, +			  snapshot *restoreSnapshot, +			  mail::callback::folder &folderCallback) const; +	}; + +	// Special folders + +	folder inboxFolder, hierarchyFolder; + +	// Stuff gets done by creating a task object, and pushing it into +	// the tasks queue (see below).  The first task in the queue gets +	// its doit() method called.  doit() receives the timeout parameter +	// from mbox::handler(), which it can adjust, if necessary. +	// +	// The doit() method should invoke done() when its done, otherwise +	// it can simply exit, and be re-invoked the next time the handler +	// is invoked. +	// +	// The task's disconnected() method gets invoked if the mbox +	// object is destroyed in mid-stream, or if there's a fatal timeout +	// trying to lock the mboxAccount file.  disconnected() should NOT invoke +	// done(), because that's going to happen anyway as soon as +	// disconnected() wraps up.  disconnected() is present so that +	// the task can invoke any application callbacks the task is +	// responsible for. + +	class task { + +	protected: +		mbox &mboxAccount; + +	public: +		task(mbox &mboxAccount); +		virtual ~task(); + +		virtual void doit(int &timeout)=0; +		virtual void disconnected()=0; + +		virtual void done(); +	}; + +	// TimedTask subclasses from task, to provide a task with a timeout. +	// +	// Subclasses should implement bool doit().  bool doit() should return +	// true if the task succeeded, or failed.  If the task is deferred, +	// the subclass's doit() method should return false. +	// +	// The subclass should call either fail() or success(), which invokes +	// the callback's method, then invokes done(). +	// +	// The timedOut() method invokes the callback's fail method, if this +	// tasks times out.  The subclass can override this method to provide +	// some value-added functionality. +	// + +	class TimedTask : public mbox::task { + +		time_t timeout; +		time_t nextTry; + +	protected: +		mail::callback &callback; +	public: +		TimedTask(mbox &mboxAccount, +			  mail::callback &callbackArg, int timeoutArg=60); +		~TimedTask(); + +		void doit(int &timeout); + +		void fail(std::string errmsg); +		virtual bool doit()=0; +		virtual void timedOut(); +		virtual void disconnected(); +	}; + +	// This is a wrapper for liblock's locking functions + +	class lock { +		struct ll_mail *ll; + +		int fd; + +		bool readOnlyLock; + +		lock(); + +	public: +		lock(std::string filename); // File to create an mboxAccount lock for. +		~lock(); + +		bool operator()(bool readOnly=false); +		// Attempt to lock this mboxAccount file, via liblock. +		// Set readOnly to true if a read-only lock is permissible. + +		int getfd() const { return fd; } +		// Success - return the file descriptor of locked file. + +		bool readOnly() const { return readOnlyLock; } +		// Indicator whether the file was locked in read-only mode. + + +		lock *copy(); +		// Copy this lock structure to another object, used for +		// optimizing consecutive parallel locks. + +	}; + +	class StatusTask; +	class sighandler; +	class OpenTask; +	class CheckNewMailTask; + +	class LockTask; +	class GenericReadTask; +	class GenericGetMessageTask; +	class ExpungeTask; + +	class MultiLock; +	class MultiLockGenericMessageRead; +	class MultiLockGenericAttributes; +	class MultiLockRelease; +	class RenameTask; + +	std::queue<task *> tasks; + +	void installTask(task *); + +	// The currently open folder. + +	std::string currentFolder; +	bool currentFolderReadOnly;	// Folder opened in readonly mode. + +	off_t folderSavedSize; +	time_t folderSavedTimestamp; +	// Detect if someone else modified the folder file. + +	std::string multiLockFilename; +	lock *multiLockLock; + +	bool folderDirty; +	// Set to true when message metadata has been modified, but the +	// folder file has not been updated to reflect these changes. + +	bool newMessages; +	// Set when index is updated from folderMessageIndex, and new messages +	// were found. + +	//////////////////////////////////////////////////////// +	// +	// The actual parsed contents of the folder: + +	struct mboxMessageIndex { + +		off_t startingPos;	// Starting offset +		time_t internalDate;	// Synthesized message arrival date +		mboxMagicTag tag;	// The synthesized UID. +	}; + +	mail::keywords::Hashtable keywordHashtable; +	std::vector<mboxMessageIndex> folderMessageIndex; // The folder + +	std::map<std::string, size_t> uidmap;	// Look up index from uid. + +	// Generic interface caches the temporary file with the most recently +	// opened message: + +	std::string cachedMessageUid;	// The cached uid +	struct rfc2045 *cachedMessageRfcp; +	FILE *cachedMessageFp; + +	void resetFolder(); + +	mail::callback::folder *currentFolderCallback; + +	// The application sees the following index: + +	std::vector<mail::messageInfo> index; + +	// Update the mboxAccount file.  This is where everything happens. + +	bool scan(file &scanFile, +		  file *saveFile, +		  bool reopening, +		  std::set<std::string> *deleteMsgs, +		  bool rewrite, +		  mail::callback *progress); + +	void checkNewMail(); + +public: +	friend class folder; +	friend class task; +	friend class TimedTask; +	friend class StatusTask; +	friend class OpenTask; +	friend class CheckNewMailTask; +	friend class RenameTask; + +	friend class LockTask; +	friend class GenericReadTask; +	friend class GenericGetMessageTask; +	friend class ExpungeTask; +	friend class MultiLock; +	friend class MultiLockGenericMessageRead; +	friend class MultiLockGenericAttributes; +	friend class MultiLockRelease; + +	mbox(bool magicInboxArg, +		   std::string folderRootArg, mail::callback &callback, +		   mail::callback::disconnect &disconnect_callback); +	~mbox(); + +	void logout(mail::callback &callback); +	void checkNewMail(mail::callback &callback); + +	bool hasCapability(std::string capability); +	std::string getCapability(std::string capability); + +	mail::folder *folderFromString(std::string); + +	void readTopLevelFolders(mail::callback::folderList &callback1, +				 mail::callback &callback2); + +	void findFolder(std::string folder, +			mail::callback::folderList &callback1, +			mail::callback &callback2); +	std::string translatePath(std::string path); + +	static std::string translatePathCommon(std::string path, +					       const char *verbotten, +					       const char *sep); + +	void readMessageAttributes(const std::vector<size_t> &messages, +				   MessageAttributes attributes, +				   mail::callback::message &callback); + +	void readMessageContent(const std::vector<size_t> &messages, +				bool peek, +				enum mail::readMode readType, +				mail::callback::message &callback); + +	void readMessageContent(size_t messageNum, +				bool peek, +				const mimestruct &msginfo, +				enum mail::readMode readType, +				mail::callback::message &callback); + +	void readMessageContentDecoded(size_t messageNum, +				       bool peek, +				       const mimestruct &msginfo, +				       mail::callback::message &callback); + +	size_t getFolderIndexSize(); +	mail::messageInfo getFolderIndexInfo(size_t); + +	void saveFolderIndexInfo(size_t, +					 const mail::messageInfo &, +					 mail::callback &); + +	void updateFolderIndexFlags(const std::vector<size_t> &messages, +				    bool doFlip, +				    bool enableDisable, +				    const mail::messageInfo &flags, +				    mail::callback &callback); + +	void updateFolderIndexInfo(mail::callback &); + + +	void updateKeywords(const std::vector<size_t> &messages, +			    const std::set<std::string> &keywords, +			    bool setOrChange, +			    // false: set, true: see changeTo +			    bool changeTo, +			    callback &cb); +	void getFolderKeywordInfo(size_t, std::set<std::string> &); + +	bool genericProcessKeyword(size_t messageNumber, +				   generic::updateKeywordHelper &helper); + +	void removeMessages(const std::vector<size_t> &messages, +			    callback &cb); + +	void copyMessagesTo(const std::vector<size_t> &messages, +			    mail::folder *copyTo, +			    mail::callback &callback); + +	void searchMessages(const class mail::searchParams &searchInfo, +			    class mail::searchCallback &callback); + +	bool verifyUid(std::string uid, size_t &messageNumber, +		       mail::callback &callback); + + +	void genericMessageRead(std::string uid, +				size_t messageNumber, +				bool peek, +				mail::readMode, +				mail::callback::message &callback); + +	void genericMessageSize(std::string uid, +				size_t messageNumber, +				mail::callback::message &callback); + +	void genericGetMessageFd(std::string uid, +				 size_t messageNumber, +				 bool peek, +				 int &fdRet, +				 mail::callback &callback); + +	void genericGetMessageStruct(std::string uid, +				     size_t messageNumber, +				     struct rfc2045 *&structRet, +				     mail::callback &callback); + +	bool genericCachedUid(std::string uid); + +	void genericGetMessageFdStruct(std::string uid, +				       size_t messageNumber, +				       bool peek, +				       int &fdRet, +				       struct rfc2045 *&structret, +				       mail::callback &callback); +	void genericMarkRead(size_t messageNumber); +}; + +LIBMAIL_END + +#endif | 
