1/*
2 * Copyright 2012-2016, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef IMAP_FOLDER_H
6#define IMAP_FOLDER_H
7
8
9#include <hash_map>
10#include <hash_set>
11
12#include <sys/stat.h>
13
14#include <Entry.h>
15#include <Node.h>
16#include <Handler.h>
17#include <String.h>
18
19#include <locks.h>
20
21#include "Commands.h"
22
23
24class BFile;
25class IMAPProtocol;
26
27
28struct MessageToken {
29	BString	mailboxName;
30	uint32	uidValidity;
31	uint32	uid;
32};
33
34// Additional local only message flags
35enum FolderMessageFlags {
36	kPartialMessage = 0x00010000,
37};
38
39
40class FolderListener {
41public:
42	virtual	uint32				MessageAdded(const MessageToken& fromToken,
43									const entry_ref& ref) = 0;
44	virtual void				MessageDeleted(const MessageToken& token) = 0;
45
46	virtual void				MessageFlagsChanged(const MessageToken& token,
47									const entry_ref& ref, uint32 oldFlags,
48									uint32 newFlags) = 0;
49};
50
51
52class IMAPFolder : public BHandler {
53public:
54								IMAPFolder(IMAPProtocol& protocol,
55									const BString& mailboxName,
56									const entry_ref& ref);
57	virtual						~IMAPFolder();
58
59			status_t			Init();
60
61			const BString&		MailboxName() const { return fMailboxName; }
62			ino_t				NodeID() const { return fNodeID; }
63
64			void				SetListener(FolderListener* listener);
65			void				SetUIDValidity(uint32 uidValidity);
66
67			uint32				LastUID() const { return fLastUID; }
68
69			status_t			GetMessageEntryRef(uint32 uid, entry_ref& ref);
70			status_t			GetMessageUID(const entry_ref& ref,
71									uint32& uid) const;
72			uint32				MessageFlags(uint32 uid);
73
74			void				SyncMessageFlags(uint32 uid,
75									uint32 mailboxFlags);
76			void				MessageEntriesFetched();
77
78			status_t			StoreMessage(uint32 fetchFlags, BDataIO& stream,
79									size_t& length, entry_ref& ref,
80									BFile& file);
81			void				MessageStored(entry_ref& ref, BFile& file,
82									uint32 fetchFlags, uint32 uid,
83									uint32 flags);
84
85			void				RegisterPendingBodies(
86									IMAP::MessageUIDList& uids,
87									const BMessenger* replyTo);
88			status_t			StoreBody(uint32 uid, BDataIO& stream,
89									size_t& length, entry_ref& ref,
90									BFile& file);
91			void				BodyStored(entry_ref& ref, BFile& file,
92									uint32 uid);
93			void				StoringBodyFailed(const entry_ref& ref,
94									uint32 uid, status_t error);
95
96			void				DeleteMessage(uint32 uid);
97
98	virtual void				MessageReceived(BMessage* message);
99
100private:
101			void				_WaitForFolderState();
102			void				_InitializeFolderState();
103			void				_ReadFolderState();
104	static	status_t			_ReadFolderState(void* self);
105
106			const MessageToken	_Token(uint32 uid) const;
107			void				_NotifyStoredBody(const entry_ref& ref,
108									uint32 uid, status_t status);
109			status_t			_GetMessageEntryRef(uint32 uid,
110									entry_ref& ref) const;
111			status_t			_DeleteLocalMessage(uint32 uid);
112
113			void				_IMAPToMailFlags(uint32 flags,
114									BMessage& attributes);
115			status_t			_MailToIMAPFlags(BNode& node, uint32& flags);
116			void				_TestMessageFlags(uint32 previousFlags,
117									uint32 mailboxFlags, uint32 currentFlags,
118									uint32 testFlag, uint32& nextFlags);
119
120			uint32				_ReadUniqueID(BNode& node) const;
121			status_t			_WriteUniqueID(BNode& node, uint32 uid) const;
122			uint32				_ReadUniqueIDValidity(BNode& node) const;
123			status_t			_WriteUniqueIDValidity(BNode& node) const;
124			uint32				_ReadFlags(BNode& node) const;
125			status_t			_WriteFlags(BNode& node, uint32 flags) const;
126
127			uint32				_ReadUInt32(BNode& node,
128									const char* attribute) const;
129			status_t			_WriteUInt32(BNode& node,
130									const char* attribute, uint32 value) const;
131
132			status_t			_WriteStream(BFile& file, BDataIO& stream,
133									size_t& length) const;
134
135private:
136	typedef std::vector<BMessenger> MessengerList;
137#if __GNUC__ >= 4
138	typedef __gnu_cxx::hash_map<uint32, uint32> UIDToFlagsMap;
139	typedef __gnu_cxx::hash_map<uint32, entry_ref> UIDToRefMap;
140	typedef __gnu_cxx::hash_map<uint32, MessengerList> MessengerMap;
141	typedef __gnu_cxx::hash_set<uint32> UIDSet;
142#else
143	typedef std::hash_map<uint32, uint32> UIDToFlagsMap;
144	typedef std::hash_map<uint32, entry_ref> UIDToRefMap;
145	typedef std::hash_map<uint32, MessengerList> MessengerMap;
146	typedef std::hash_set<uint32> UIDSet;
147#endif
148
149			IMAPProtocol&		fProtocol;
150			const entry_ref		fRef;
151			BString				fMailboxName;
152			ino_t				fNodeID;
153			uint32				fUIDValidity;
154			uint32				fLastUID;
155			FolderListener*		fListener;
156			mutex				fLock;
157			mutex				fFolderStateLock;
158			thread_id			fReadFolderStateThread;
159			bool				fFolderStateInitialized;
160			bool				fQuitFolderState;
161			UIDToRefMap			fRefMap;
162			UIDToFlagsMap		fFlagsMap;
163			UIDSet				fSynchronizedUIDsSet;
164			UIDToFlagsMap		fPendingFlagsMap;
165			MessengerMap		fPendingBodies;
166};
167
168
169#endif	// IMAP_FOLDER_H
170