1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsMsgDBFolder_h__
7 #define nsMsgDBFolder_h__
8 
9 #include "mozilla/Attributes.h"
10 #include "msgCore.h"
11 #include "nsIMsgFolder.h"
12 #include "nsIDBFolderInfo.h"
13 #include "nsIMsgDatabase.h"
14 #include "nsIMsgIncomingServer.h"
15 #include "nsCOMPtr.h"
16 #include "nsIDBChangeListener.h"
17 #include "nsIMsgPluggableStore.h"
18 #include "nsIURL.h"
19 #include "nsIFile.h"
20 #include "nsWeakReference.h"
21 #include "nsIWeakReferenceUtils.h"
22 #include "nsIMsgFilterList.h"
23 #include "nsIUrlListener.h"
24 #include "nsIMsgHdr.h"
25 #include "nsIOutputStream.h"
26 #include "nsITransport.h"
27 #include "nsIStringBundle.h"
28 #include "nsTObserverArray.h"
29 #include "nsCOMArray.h"
30 #include "nsMsgKeySet.h"
31 #include "nsMsgMessageFlags.h"
32 #include "nsIMsgFilterPlugin.h"
33 
34 // We declare strings for folder properties and events.
35 // Properties:
36 extern const nsLiteralCString kBiffState;
37 extern const nsLiteralCString kCanFileMessages;
38 extern const nsLiteralCString kDefaultServer;
39 extern const nsLiteralCString kFlagged;
40 extern const nsLiteralCString kFolderFlag;
41 extern const nsLiteralCString kFolderSize;
42 extern const nsLiteralCString kIsDeferred;
43 extern const nsLiteralCString kIsSecure;
44 extern const nsLiteralCString kJunkStatusChanged;
45 extern const nsLiteralCString kKeywords;
46 extern const nsLiteralCString kMRMTimeChanged;
47 extern const nsLiteralCString kMsgLoaded;
48 extern const nsLiteralCString kName;
49 extern const nsLiteralCString kNewMailReceived;
50 extern const nsLiteralCString kNewMessages;
51 extern const nsLiteralCString kOpen;
52 extern const nsLiteralCString kSortOrder;
53 extern const nsLiteralCString kStatus;
54 extern const nsLiteralCString kSynchronize;
55 extern const nsLiteralCString kTotalMessages;
56 extern const nsLiteralCString kTotalUnreadMessages;
57 
58 // Events:
59 extern const nsLiteralCString kAboutToCompact;
60 extern const nsLiteralCString kCompactCompleted;
61 extern const nsLiteralCString kDeleteOrMoveMsgCompleted;
62 extern const nsLiteralCString kDeleteOrMoveMsgFailed;
63 extern const nsLiteralCString kFiltersApplied;
64 extern const nsLiteralCString kFolderCreateCompleted;
65 extern const nsLiteralCString kFolderCreateFailed;
66 extern const nsLiteralCString kFolderLoaded;
67 extern const nsLiteralCString kNumNewBiffMessages;
68 extern const nsLiteralCString kRenameCompleted;
69 
70 class nsIMsgFolderCacheElement;
71 class nsICollation;
72 class nsMsgKeySetU;
73 
74 class nsMsgFolderService final : public nsIMsgFolderService {
75  public:
76   NS_DECL_ISUPPORTS
77   NS_DECL_NSIMSGFOLDERSERVICE
78 
nsMsgFolderService()79   nsMsgFolderService(){};
80 
81  protected:
~nsMsgFolderService()82   ~nsMsgFolderService(){};
83 };
84 
85 /*
86  * nsMsgDBFolder
87  * class derived from nsMsgFolder for those folders that use an nsIMsgDatabase
88  */
89 class nsMsgDBFolder : public nsSupportsWeakReference,
90                       public nsIMsgFolder,
91                       public nsIDBChangeListener,
92                       public nsIUrlListener,
93                       public nsIJunkMailClassificationListener,
94                       public nsIMsgTraitClassificationListener {
95  public:
96   friend class nsMsgFolderService;
97 
98   nsMsgDBFolder(void);
99   NS_DECL_THREADSAFE_ISUPPORTS
100   NS_DECL_NSIMSGFOLDER
101   NS_DECL_NSIDBCHANGELISTENER
102   NS_DECL_NSIURLLISTENER
103   NS_DECL_NSIJUNKMAILCLASSIFICATIONLISTENER
104   NS_DECL_NSIMSGTRAITCLASSIFICATIONLISTENER
105 
106   NS_IMETHOD WriteToFolderCacheElem(nsIMsgFolderCacheElement* element);
107   NS_IMETHOD ReadFromFolderCacheElem(nsIMsgFolderCacheElement* element);
108 
109   nsresult CreateDirectoryForFolder(nsIFile** result);
110   nsresult CreateBackupDirectory(nsIFile** result);
111   nsresult GetBackupSummaryFile(nsIFile** result, const nsACString& newName);
112   nsresult GetMsgPreviewTextFromStream(nsIMsgDBHdr* msgHdr,
113                                        nsIInputStream* stream);
114   nsresult HandleAutoCompactEvent(nsIMsgWindow* aMsgWindow);
115 
116  protected:
117   virtual ~nsMsgDBFolder();
118 
119   virtual nsresult CreateBaseMessageURI(const nsACString& aURI);
120 
121   void compressQuotesInMsgSnippet(const nsString& aMessageText,
122                                   nsAString& aCompressedQuotesStr);
123   void decodeMsgSnippet(const nsACString& aEncodingType, bool aIsComplete,
124                         nsCString& aMsgSnippet);
125 
126   // helper routine to parse the URI and update member variables
127   nsresult parseURI(bool needServer = false);
128   nsresult GetBaseStringBundle(nsIStringBundle** aBundle);
129   nsresult GetStringFromBundle(const char* msgName, nsString& aResult);
130   nsresult ThrowConfirmationPrompt(nsIMsgWindow* msgWindow,
131                                    const nsAString& confirmString,
132                                    bool* confirmed);
133   nsresult GetWarnFilterChanged(bool* aVal);
134   nsresult SetWarnFilterChanged(bool aVal);
135   nsresult CreateCollationKey(const nsString& aSource, uint8_t** aKey,
136                               uint32_t* aLength);
137 
138   // All children will override this to create the right class of object.
139   virtual nsresult CreateChildFromURI(const nsACString& uri,
140                                       nsIMsgFolder** folder) = 0;
141   virtual nsresult ReadDBFolderInfo(bool force);
142   virtual nsresult FlushToFolderCache();
143   virtual nsresult GetDatabase() = 0;
144   virtual nsresult SendFlagNotifications(nsIMsgDBHdr* item, uint32_t oldFlags,
145                                          uint32_t newFlags);
146   nsresult CheckWithNewMessagesStatus(bool messageAdded);
147   void UpdateNewMessages();
148   nsresult OnHdrAddedOrDeleted(nsIMsgDBHdr* hdrChanged, bool added);
149   nsresult CreateFileForDB(const nsAString& userLeafName, nsIFile* baseDir,
150                            nsIFile** dbFile);
151 
152   nsresult GetFolderCacheKey(nsIFile** aFile, bool createDBIfMissing = false);
153   nsresult GetFolderCacheElemFromFile(nsIFile* file,
154                                       nsIMsgFolderCacheElement** cacheElement);
155   nsresult AddDirectorySeparator(nsIFile* path);
156   nsresult CheckIfFolderExists(const nsAString& newFolderName,
157                                nsIMsgFolder* parentFolder,
158                                nsIMsgWindow* msgWindow);
159   bool ConfirmAutoFolderRename(nsIMsgWindow* aMsgWindow,
160                                const nsString& aOldName,
161                                const nsString& aNewName);
162 
163   // Returns true if: a) there is no need to prompt or b) the user is already
164   // logged in or c) the user logged in successfully.
165   static bool PromptForMasterPasswordIfNecessary();
166 
167   // offline support methods.
168   nsresult StartNewOfflineMessage();
169   nsresult WriteStartOfNewLocalMessage();
170   nsresult EndNewOfflineMessage();
171   nsresult CompactOfflineStore(nsIMsgWindow* inWindow,
172                                nsIUrlListener* aUrlListener);
173   nsresult AutoCompact(nsIMsgWindow* aWindow);
174   // this is a helper routine that ignores whether nsMsgMessageFlags::Offline is
175   // set for the folder
176   nsresult MsgFitsDownloadCriteria(nsMsgKey msgKey, bool* result);
177   nsresult GetPromptPurgeThreshold(bool* aPrompt);
178   nsresult GetPurgeThreshold(int32_t* aThreshold);
179   nsresult ApplyRetentionSettings(bool deleteViaFolder);
180   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult AddMarkAllReadUndoAction(
181       nsIMsgWindow* msgWindow, nsMsgKey* thoseMarked, uint32_t numMarked);
182 
183   nsresult PerformBiffNotifications(
184       void);  // if there are new, non spam messages, do biff
185   nsresult CloseDBIfFolderNotOpen();
186 
187   // Helper function for Move code to call to update the MRU and MRM time.
188   void UpdateTimestamps(bool allowUndo);
189   void SetMRUTime();
190   void SetMRMTime();
191   /**
192    * Clear all processing flags, presumably because message keys are no longer
193    * valid.
194    */
195   void ClearProcessingFlags();
196 
197   nsresult NotifyHdrsNotBeingClassified();
198   static nsresult BuildFolderSortKey(nsIMsgFolder* aFolder,
199                                      nsTArray<uint8_t>& aKey);
200   /**
201    * Produce an array of messages ordered like the input keys.
202    */
203   nsresult MessagesInKeyOrder(nsTArray<nsMsgKey> const& aKeyArray,
204                               nsIMsgFolder* srcFolder,
205                               nsTArray<RefPtr<nsIMsgDBHdr>>& messages);
206   nsCString mURI;
207 
208   nsCOMPtr<nsIMsgDatabase> mDatabase;
209   nsCOMPtr<nsIMsgDatabase> mBackupDatabase;
210   bool mAddListener;
211   bool mNewMessages;
212   bool mGettingNewMessages;
213   nsMsgKey mLastMessageLoaded;
214 
215   nsCOMPtr<nsIMsgDBHdr> m_offlineHeader;
216   int32_t m_numOfflineMsgLines;
217   int32_t m_bytesAddedToLocalMsg;
218   // this is currently used when we do a save as of an imap or news message..
219   nsCOMPtr<nsIOutputStream> m_tempMessageStream;
220 
221   nsCOMPtr<nsIMsgRetentionSettings> m_retentionSettings;
222   nsCOMPtr<nsIMsgDownloadSettings> m_downloadSettings;
223   static nsrefcnt mInstanceCount;
224 
225   uint32_t mFlags;
226   nsWeakPtr mParent;          // This won't be refcounted for ownership reasons.
227   int32_t mNumUnreadMessages; /* count of unread messages (-1 means unknown; -2
228                                  means unknown but we already tried to find
229                                  out.) */
230   int32_t mNumTotalMessages;  /* count of existing messages. */
231   bool mNotifyCountChanges;
232   int64_t mExpungedBytes;
233   nsCOMArray<nsIMsgFolder> mSubFolders;
234   nsTObserverArray<nsCOMPtr<nsIFolderListener>> mListeners;
235 
236   bool mInitializedFromCache;
237   nsISupports* mSemaphoreHolder;  // set when the folder is being written to
238                                   // Due to ownership issues, this won't be
239                                   // AddRef'd.
240 
241   nsWeakPtr mServer;
242 
243   // These values are used for tricking the front end into thinking that we have
244   // more messages than are really in the DB.  This is usually after and IMAP
245   // message copy where we don't want to do an expensive select until the user
246   // actually opens that folder
247   int32_t mNumPendingUnreadMessages;
248   int32_t mNumPendingTotalMessages;
249   int64_t mFolderSize;
250 
251   int32_t mNumNewBiffMessages;
252 
253   // these are previous set of new msgs, which we might
254   // want to run junk controls on. This is in addition to "new" hdrs
255   // in the db, which might get cleared because the user clicked away
256   // from the folder.
257   nsTArray<nsMsgKey> m_saveNewMsgs;
258 
259   // These are the set of new messages for a folder who has had
260   // its db closed, without the user reading the folder. This
261   // happens with pop3 mail filtered to a different local folder.
262   nsTArray<nsMsgKey> m_newMsgs;
263 
264   //
265   // stuff from the uri
266   //
267   bool mHaveParsedURI;  // is the URI completely parsed?
268   bool mIsServerIsValid;
269   bool mIsServer;
270   nsString mName;
271   nsCOMPtr<nsIFile> mPath;
272   nsCString mBaseMessageURI;  // The uri with the message scheme
273 
274   // static stuff for cross-instance objects like atoms
275   static nsrefcnt gInstanceCount;
276 
277   static nsresult initializeStrings();
278   static nsresult createCollationKeyGenerator();
279 
280   static nsString kLocalizedInboxName;
281   static nsString kLocalizedTrashName;
282   static nsString kLocalizedSentName;
283   static nsString kLocalizedDraftsName;
284   static nsString kLocalizedTemplatesName;
285   static nsString kLocalizedUnsentName;
286   static nsString kLocalizedJunkName;
287   static nsString kLocalizedArchivesName;
288 
289   static nsString kLocalizedBrandShortName;
290 
291   static nsICollation* gCollationKeyGenerator;
292   static bool gInitializeStringsDone;
293 
294   // store of keys that have a processing flag set
295   struct {
296     uint32_t bit;
297     nsMsgKeySetU* keys;
298   } mProcessingFlag[nsMsgProcessingFlags::NumberOfFlags];
299 
300   // list of nsIMsgDBHdrs for messages to process post-bayes
301   nsTArray<RefPtr<nsIMsgDBHdr>> mPostBayesMessagesToFilter;
302 
303   /**
304    * The list of message keys that have been classified for msgsClassified
305    * batch notification purposes.  We add to this list in OnMessageClassified
306    * when we are told about a classified message (a URI is provided), and we
307    * notify for the list and clear it when we are told all the messages in
308    * the batch were classified (a URI is not provided).
309    */
310   nsTArray<nsMsgKey> mClassifiedMsgKeys;
311   // Is the current bayes filtering doing junk classification?
312   bool mBayesJunkClassifying;
313   // Is the current bayes filtering doing trait classification?
314   bool mBayesTraitClassifying;
315 };
316 
317 // This class is a kludge to allow nsMsgKeySet to be used with uint32_t keys
318 class nsMsgKeySetU {
319  public:
320   // Creates an empty set.
321   static nsMsgKeySetU* Create();
322   ~nsMsgKeySetU();
323   // IsMember() returns whether the given key is a member of this set.
324   bool IsMember(nsMsgKey key);
325   // Add() adds the given key to the set.  (Returns 1 if a change was
326   // made, 0 if it was already there, and negative on error.)
327   int Add(nsMsgKey key);
328   // Remove() removes the given article from the set.
329   int Remove(nsMsgKey key);
330   // Add the keys in the set to aArray.
331   nsresult ToMsgKeyArray(nsTArray<nsMsgKey>& aArray);
332 
333  protected:
334   nsMsgKeySetU();
335   nsMsgKeySet* loKeySet;
336   nsMsgKeySet* hiKeySet;
337 };
338 
339 #endif
340