⛏️ index : haiku.git

/*
 * Copyright 2012-2016, Axel DΓΆrfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef IMAP_FOLDER_H
#define IMAP_FOLDER_H


#include <hash_map>
#include <hash_set>

#include <sys/stat.h>

#include <Entry.h>
#include <Node.h>
#include <Handler.h>
#include <String.h>

#include <locks.h>

#include "Commands.h"


class BFile;
class IMAPProtocol;


struct MessageToken {
	BString	mailboxName;
	uint32	uidValidity;
	uint32	uid;
};

// Additional local only message flags
enum FolderMessageFlags {
	kPartialMessage = 0x00010000,
};


class FolderListener {
public:
	virtual	uint32				MessageAdded(const MessageToken& fromToken,
									const entry_ref& ref) = 0;
	virtual void				MessageDeleted(const MessageToken& token) = 0;

	virtual void				MessageFlagsChanged(const MessageToken& token,
									const entry_ref& ref, uint32 oldFlags,
									uint32 newFlags) = 0;
};


class IMAPFolder : public BHandler {
public:
								IMAPFolder(IMAPProtocol& protocol,
									const BString& mailboxName,
									const entry_ref& ref);
	virtual						~IMAPFolder();

			status_t			Init();

			const BString&		MailboxName() const { return fMailboxName; }
			ino_t				NodeID() const { return fNodeID; }

			void				SetListener(FolderListener* listener);
			void				SetUIDValidity(uint32 uidValidity);

			uint32				LastUID() const { return fLastUID; }

			status_t			GetMessageEntryRef(uint32 uid, entry_ref& ref);
			status_t			GetMessageUID(const entry_ref& ref,
									uint32& uid) const;
			uint32				MessageFlags(uint32 uid);

			void				SyncMessageFlags(uint32 uid,
									uint32 mailboxFlags);
			void				MessageEntriesFetched();

			status_t			StoreMessage(uint32 fetchFlags, BDataIO& stream,
									size_t& length, entry_ref& ref,
									BFile& file);
			void				MessageStored(entry_ref& ref, BFile& file,
									uint32 fetchFlags, uint32 uid,
									uint32 flags);

			void				RegisterPendingBodies(
									IMAP::MessageUIDList& uids,
									const BMessenger* replyTo);
			status_t			StoreBody(uint32 uid, BDataIO& stream,
									size_t& length, entry_ref& ref,
									BFile& file);
			void				BodyStored(entry_ref& ref, BFile& file,
									uint32 uid);
			void				StoringBodyFailed(const entry_ref& ref,
									uint32 uid, status_t error);

			void				DeleteMessage(uint32 uid);

	virtual void				MessageReceived(BMessage* message);

private:
			void				_WaitForFolderState();
			void				_InitializeFolderState();
			void				_ReadFolderState();
	static	status_t			_ReadFolderState(void* self);

			const MessageToken	_Token(uint32 uid) const;
			void				_NotifyStoredBody(const entry_ref& ref,
									uint32 uid, status_t status);
			status_t			_GetMessageEntryRef(uint32 uid,
									entry_ref& ref) const;
			status_t			_DeleteLocalMessage(uint32 uid);

			void				_IMAPToMailFlags(uint32 flags,
									BMessage& attributes);
			status_t			_MailToIMAPFlags(BNode& node, uint32& flags);
			void				_TestMessageFlags(uint32 previousFlags,
									uint32 mailboxFlags, uint32 currentFlags,
									uint32 testFlag, uint32& nextFlags);

			uint32				_ReadUniqueID(BNode& node) const;
			status_t			_WriteUniqueID(BNode& node, uint32 uid) const;
			uint32				_ReadUniqueIDValidity(BNode& node) const;
			status_t			_WriteUniqueIDValidity(BNode& node) const;
			uint32				_ReadFlags(BNode& node) const;
			status_t			_WriteFlags(BNode& node, uint32 flags) const;

			uint32				_ReadUInt32(BNode& node,
									const char* attribute) const;
			status_t			_WriteUInt32(BNode& node,
									const char* attribute, uint32 value) const;

			status_t			_WriteStream(BFile& file, BDataIO& stream,
									size_t& length) const;

private:
	typedef std::vector<BMessenger> MessengerList;
#if __GNUC__ >= 4
	typedef __gnu_cxx::hash_map<uint32, uint32> UIDToFlagsMap;
	typedef __gnu_cxx::hash_map<uint32, entry_ref> UIDToRefMap;
	typedef __gnu_cxx::hash_map<uint32, MessengerList> MessengerMap;
	typedef __gnu_cxx::hash_set<uint32> UIDSet;
#else
	typedef std::hash_map<uint32, uint32> UIDToFlagsMap;
	typedef std::hash_map<uint32, entry_ref> UIDToRefMap;
	typedef std::hash_map<uint32, MessengerList> MessengerMap;
	typedef std::hash_set<uint32> UIDSet;
#endif

			IMAPProtocol&		fProtocol;
			const entry_ref		fRef;
			BString				fMailboxName;
			ino_t				fNodeID;
			uint32				fUIDValidity;
			uint32				fLastUID;
			FolderListener*		fListener;
			mutex				fLock;
			mutex				fFolderStateLock;
			thread_id			fReadFolderStateThread;
			bool				fFolderStateInitialized;
			bool				fQuitFolderState;
			UIDToRefMap			fRefMap;
			UIDToFlagsMap		fFlagsMap;
			UIDSet				fSynchronizedUIDsSet;
			UIDToFlagsMap		fPendingFlagsMap;
			MessengerMap		fPendingBodies;
};


#endif	// IMAP_FOLDER_H