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 _NSMSGUTILS_H
7 #define _NSMSGUTILS_H
8 
9 #include "nsIURL.h"
10 #include "nsString.h"
11 #include "msgCore.h"
12 #include "nsCOMPtr.h"
13 #include "MailNewsTypes2.h"
14 #include "nsTArray.h"
15 #include "nsInterfaceRequestorAgg.h"
16 #include "nsILoadGroup.h"
17 #include "nsINetUtil.h"
18 #include "nsIRequest.h"
19 #include "nsILoadInfo.h"
20 #include "nsServiceManagerUtils.h"
21 #include "nsUnicharUtils.h"
22 #include "nsIFile.h"
23 
24 class nsIChannel;
25 class nsIFile;
26 class nsIPrefBranch;
27 class nsIMsgFolder;
28 class nsIMsgMessageService;
29 class nsIUrlListener;
30 class nsIOutputStream;
31 class nsIInputStream;
32 class nsIMsgDatabase;
33 class nsIProxyInfo;
34 class nsIMsgWindow;
35 class nsIStreamListener;
36 class nsICancelable;
37 class nsIProtocolProxyCallback;
38 class nsIMsgSearchTerm;
39 
40 #define FILE_IO_BUFFER_SIZE (16 * 1024)
41 #define MSGS_URL "chrome://messenger/locale/messenger.properties"
42 
43 // These are utility functions that can used throughout the mailnews code
44 
45 NS_MSG_BASE nsresult GetMessageServiceContractIDForURI(const char* uri,
46                                                        nsCString& contractID);
47 
48 NS_MSG_BASE nsresult GetMessageServiceFromURI(
49     const nsACString& uri, nsIMsgMessageService** aMessageService);
50 
51 NS_MSG_BASE nsresult GetMsgDBHdrFromURI(const nsACString& uri,
52                                         nsIMsgDBHdr** msgHdr);
53 
54 NS_MSG_BASE nsresult NS_MsgGetPriorityFromString(
55     const char* const priority, nsMsgPriorityValue& outPriority);
56 
57 NS_MSG_BASE nsresult NS_MsgGetPriorityValueString(const nsMsgPriorityValue p,
58                                                   nsACString& outValueString);
59 
60 NS_MSG_BASE nsresult NS_MsgGetUntranslatedPriorityName(
61     const nsMsgPriorityValue p, nsACString& outName);
62 
63 NS_MSG_BASE nsresult NS_MsgHashIfNecessary(nsAutoString& name);
64 NS_MSG_BASE nsresult NS_MsgHashIfNecessary(nsAutoCString& name);
65 
66 NS_MSG_BASE nsresult FormatFileSize(int64_t size, bool useKB,
67                                     nsAString& formattedSize);
68 
69 /**
70  * given a folder uri, return the path to folder in the user profile directory.
71  *
72  * @param aFolderURI uri of folder we want the path to, without the scheme
73  * @param[out] aPathString result path string
74  * @param aScheme scheme of the uri
75  * @param[optional] aIsNewsFolder is this a news folder?
76  */
77 NS_MSG_BASE nsresult NS_MsgCreatePathStringFromFolderURI(
78     const char* aFolderURI, nsCString& aPathString, const nsCString& aScheme,
79     bool aIsNewsFolder = false);
80 
81 /**
82  * Given a string and a length, removes any "Re:" strings from the front.
83  * It also deals with that dumbass "Re[2]:" thing that some losing mailers do.
84  *
85  * If mailnews.localizedRe is set, it will also remove localized "Re:" strings.
86  *
87  * @return true if it made a change (in which case the caller should look to
88  *         modifiedSubject for the result) and false otherwise (in which
89  *         case the caller should look at subject for the result)
90  */
91 NS_MSG_BASE bool NS_MsgStripRE(const nsCString& subject,
92                                nsCString& modifiedSubject);
93 
94 NS_MSG_BASE char* NS_MsgSACopy(char** destination, const char* source);
95 
96 NS_MSG_BASE char* NS_MsgSACat(char** destination, const char* source);
97 
98 NS_MSG_BASE nsresult NS_MsgEscapeEncodeURLPath(const nsAString& aStr,
99                                                nsCString& aResult);
100 
101 NS_MSG_BASE nsresult NS_MsgDecodeUnescapeURLPath(const nsACString& aPath,
102                                                  nsAString& aResult);
103 
104 NS_MSG_BASE bool WeAreOffline();
105 
106 // Get a folder by Uri, returning null if it doesn't exist (or if some
107 // error occurs). A missing folder is not considered an error.
108 NS_MSG_BASE nsresult FindFolder(const nsACString& aFolderURI,
109                                 nsIMsgFolder** aFolder);
110 
111 // Get a folder by Uri.
112 // A missing folder is considered to be an error.
113 // Returns a non-null folder if and only if result is NS_OK.
114 NS_MSG_BASE nsresult GetExistingFolder(const nsACString& aFolderURI,
115                                        nsIMsgFolder** aFolder);
116 
117 // Get a folder by Uri, creating it if it doesn't already exist.
118 // An error is returned if a folder cannot be found or created.
119 // Created folders will be 'dangling' folders (ie not connected to a
120 // parent).
121 NS_MSG_BASE nsresult GetOrCreateFolder(const nsACString& aFolderURI,
122                                        nsIMsgFolder** aFolder);
123 
124 // Escape lines starting with "From ", ">From ", etc. in a buffer.
125 NS_MSG_BASE nsresult EscapeFromSpaceLine(nsIOutputStream* ouputStream,
126                                          char* start, const char* end);
127 NS_MSG_BASE bool IsAFromSpaceLine(char* start, const char* end);
128 
129 NS_MSG_BASE nsresult NS_GetPersistentFile(
130     const char* relPrefName, const char* absPrefName,
131     const char* dirServiceProp,  // Can be NULL
132     bool& gotRelPref, nsIFile** aFile, nsIPrefBranch* prefBranch = nullptr);
133 
134 NS_MSG_BASE nsresult NS_SetPersistentFile(const char* relPrefName,
135                                           const char* absPrefName,
136                                           nsIFile* aFile,
137                                           nsIPrefBranch* prefBranch = nullptr);
138 
139 NS_MSG_BASE nsresult IsRFC822HeaderFieldName(const char* aHdr, bool* aResult);
140 
141 NS_MSG_BASE nsresult NS_GetUnicharPreferenceWithDefault(
142     nsIPrefBranch* prefBranch,  // can be null, if so uses the root branch
143     const char* prefName, const nsAString& defValue, nsAString& prefValue);
144 
145 NS_MSG_BASE nsresult NS_GetLocalizedUnicharPreferenceWithDefault(
146     nsIPrefBranch* prefBranch,  // can be null, if so uses the root branch
147     const char* prefName, const nsAString& defValue, nsAString& prefValue);
148 
149 NS_MSG_BASE nsresult NS_GetLocalizedUnicharPreference(
150     nsIPrefBranch* prefBranch,  // can be null, if so uses the root branch
151     const char* prefName, nsAString& prefValue);
152 
153 /**
154  * this needs a listener, because we might have to create the folder
155  * on the server, and that is asynchronous
156  */
157 NS_MSG_BASE nsresult GetOrCreateJunkFolder(const nsACString& aURI,
158                                            nsIUrlListener* aListener);
159 
160 // Returns true if the nsIURI is a message under an RSS account
161 NS_MSG_BASE nsresult IsRSSArticle(nsIURI* aMsgURI, bool* aIsRSSArticle);
162 
163 // digest needs to be a pointer to a 16 byte buffer
164 #define DIGEST_LENGTH 16
165 
166 NS_MSG_BASE nsresult MSGCramMD5(const char* text, int32_t text_len,
167                                 const char* key, int32_t key_len,
168                                 unsigned char* digest);
169 NS_MSG_BASE nsresult MSGApopMD5(const char* text, int32_t text_len,
170                                 const char* password, int32_t password_len,
171                                 unsigned char* digest);
172 
173 // helper functions to convert a 64bits PRTime into a 32bits value (compatible
174 // time_t) and vice versa.
175 NS_MSG_BASE void PRTime2Seconds(PRTime prTime, uint32_t* seconds);
176 NS_MSG_BASE void PRTime2Seconds(PRTime prTime, int32_t* seconds);
177 NS_MSG_BASE void Seconds2PRTime(uint32_t seconds, PRTime* prTime);
178 // helper function to generate current date+time as a string
179 NS_MSG_BASE void MsgGenerateNowStr(nsACString& nowStr);
180 
181 // Appends the correct summary file extension onto the supplied fileLocation
182 // and returns it in summaryLocation.
183 NS_MSG_BASE nsresult GetSummaryFileLocation(nsIFile* fileLocation,
184                                             nsIFile** summaryLocation);
185 
186 // Gets a special directory and appends the supplied file name onto it.
187 NS_MSG_BASE nsresult GetSpecialDirectoryWithFileName(const char* specialDirName,
188                                                      const char* fileName,
189                                                      nsIFile** result);
190 
191 // cleanup temp files with the given filename and extension, including
192 // the consecutive -NNNN ones that we can find. If there are holes, e.g.,
193 // <filename>-1-10,12.<extension> exist, but <filename>-11.<extension> does not
194 // we'll clean up 1-10. If the leaks are common, I think the gaps will tend to
195 // be filled.
196 NS_MSG_BASE nsresult MsgCleanupTempFiles(const char* fileName,
197                                          const char* extension);
198 
199 NS_MSG_BASE nsresult MsgGetFileStream(nsIFile* file,
200                                       nsIOutputStream** fileStream);
201 
202 NS_MSG_BASE nsresult MsgReopenFileStream(nsIFile* file,
203                                          nsIInputStream* fileStream);
204 
205 // Automatically creates an output stream with a suitable buffer
206 NS_MSG_BASE nsresult MsgNewBufferedFileOutputStream(nsIOutputStream** aResult,
207                                                     nsIFile* aFile,
208                                                     int32_t aIOFlags = -1,
209                                                     int32_t aPerm = -1);
210 
211 // Automatically creates an output stream with a suitable buffer, but write to a
212 // temporary file first, then rename to aFile
213 NS_MSG_BASE nsresult
214 MsgNewSafeBufferedFileOutputStream(nsIOutputStream** aResult, nsIFile* aFile,
215                                    int32_t aIOFlags = -1, int32_t aPerm = -1);
216 
217 // fills in the position of the passed in keyword in the passed in keyword list
218 // and returns false if the keyword isn't present
219 NS_MSG_BASE bool MsgFindKeyword(const nsCString& keyword, nsCString& keywords,
220                                 int32_t* aStartOfKeyword, int32_t* aLength);
221 
222 NS_MSG_BASE bool MsgHostDomainIsTrusted(nsCString& host,
223                                         nsCString& trustedMailDomains);
224 
225 // gets an nsIFile from a UTF-8 file:// path
226 NS_MSG_BASE nsresult MsgGetLocalFileFromURI(const nsACString& aUTF8Path,
227                                             nsIFile** aFile);
228 
229 NS_MSG_BASE void MsgStripQuotedPrintable(nsCString& aSrc);
230 
231 /*
232  * Utility functions that call functions from nsINetUtil
233  */
234 
235 NS_MSG_BASE nsresult MsgEscapeString(const nsACString& aStr, uint32_t aType,
236                                      nsACString& aResult);
237 
238 NS_MSG_BASE nsresult MsgUnescapeString(const nsACString& aStr, uint32_t aFlags,
239                                        nsACString& aResult);
240 
241 NS_MSG_BASE nsresult MsgEscapeURL(const nsACString& aStr, uint32_t aFlags,
242                                   nsACString& aResult);
243 
244 // Given a message db and a set of keys, fetch the corresponding message
245 // headers.
246 NS_MSG_BASE nsresult
247 MsgGetHeadersFromKeys(nsIMsgDatabase* aDB, const nsTArray<nsMsgKey>& aKeys,
248                       nsTArray<RefPtr<nsIMsgDBHdr>>& aHeaders);
249 
250 NS_MSG_BASE nsresult MsgExamineForProxyAsync(nsIChannel* channel,
251                                              nsIProtocolProxyCallback* listener,
252                                              nsICancelable** result);
253 
254 NS_MSG_BASE int32_t MsgFindCharInSet(const nsCString& aString,
255                                      const char* aChars, uint32_t aOffset = 0);
256 NS_MSG_BASE int32_t MsgFindCharInSet(const nsString& aString,
257                                      const char* aChars, uint32_t aOffset = 0);
258 
259 // advances bufferOffset to the beginning of the next line, if we don't
260 // get to maxBufferOffset first. Returns false if we didn't get to the
261 // next line.
262 NS_MSG_BASE bool MsgAdvanceToNextLine(const char* buffer,
263                                       uint32_t& bufferOffset,
264                                       uint32_t maxBufferOffset);
265 
266 /**
267  * Alerts the user that the login to the server failed. Asks whether the
268  * connection should: retry, cancel, or request a new password.
269  *
270  * @param aMsgWindow The message window associated with this action (cannot
271  *                   be null).
272  * @param aHostname  The hostname of the server for which the login failed.
273  * @param aResult    The button pressed. 0 for retry, 1 for cancel,
274  *                   2 for enter a new password.
275  * @return           NS_OK for success, NS_ERROR_* if there was a failure in
276  *                   creating the dialog.
277  */
278 NS_MSG_BASE nsresult MsgPromptLoginFailed(nsIMsgWindow* aMsgWindow,
279                                           const nsACString& aHostname,
280                                           const nsACString& aUsername,
281                                           const nsAString& aAccountname,
282                                           int32_t* aResult);
283 
284 /**
285  * Calculate a PRTime value used to determine if a date is XX
286  * days ago. This is used by various retention setting algorithms.
287  */
288 NS_MSG_BASE PRTime MsgConvertAgeInDaysToCutoffDate(int32_t ageInDays);
289 
290 /**
291  * Converts the passed in term list to its string representation.
292  *
293  * @param      aTermList    Array of nsIMsgSearchTerms
294  * @param[out] aOutString   result representation of search terms.
295  *
296  */
297 NS_MSG_BASE nsresult MsgTermListToString(
298     nsTArray<RefPtr<nsIMsgSearchTerm>> const& aTermList, nsCString& aOutString);
299 
300 NS_MSG_BASE nsresult MsgStreamMsgHeaders(nsIInputStream* aInputStream,
301                                          nsIStreamListener* aConsumer);
302 
303 /**
304  * convert string to uint64_t
305  *
306  * @param str converted string
307  * @returns   uint64_t value for success, 0 for parse failure
308  */
309 NS_MSG_BASE uint64_t ParseUint64Str(const char* str);
310 
311 /**
312  * Detect charset of file
313  *
314  * @param      aFile    The target of nsIFile
315  * @param[out] aCharset The charset string
316  */
317 NS_MSG_BASE nsresult MsgDetectCharsetFromFile(nsIFile* aFile,
318                                               nsACString& aCharset);
319 
320 /*
321  * Converts a buffer to plain text. Some conversions may
322  * or may not work with certain end charsets which is why we
323  * need that as an argument to the function. If charset is
324  * unknown or deemed of no importance NULL could be passed.
325  * @param[in/out] aConBuf        Variable with the text to convert
326  * @param         formatFlowed   Use format flowed?
327  * @param         formatOutput   Reformat the output?
328  & @param         disallowBreaks Disallow breaks when formatting
329  */
330 NS_MSG_BASE nsresult ConvertBufToPlainText(nsString& aConBuf, bool formatFlowed,
331                                            bool formatOutput,
332                                            bool disallowBreaks);
333 
334 #include "nsEscape.h"
335 
336 /**
337  * Converts a hex string into an integer.
338  * Processes up to aNumChars characters or the first non-hex char.
339  * It is not an error if less than aNumChars valid hex digits are found.
340  */
341 NS_MSG_BASE uint64_t MsgUnhex(const char* aHexString, size_t aNumChars);
342 
343 /**
344  * Checks if a string is a valid hex literal containing at least aNumChars
345  * digits.
346  */
347 NS_MSG_BASE bool MsgIsHex(const char* aHexString, size_t aNumChars);
348 
349 /**
350  * Convert an uint32_t to a nsMsgKey.
351  * Currently they are mostly the same but we need to preserve the notion that
352  * nsMsgKey is an opaque value that can't be treated as a generic integer
353  * (except when storing it into the database). It enables type safety checks and
354  * may prevent coding errors.
355  */
356 NS_MSG_BASE nsMsgKey msgKeyFromInt(uint32_t aValue);
357 
358 NS_MSG_BASE nsMsgKey msgKeyFromInt(uint64_t aValue);
359 
360 NS_MSG_BASE uint32_t msgKeyToInt(nsMsgKey aMsgKey);
361 
362 /**
363  * Helper function to extract query part from URL spec.
364  */
365 nsCString MsgExtractQueryPart(const nsACString& spec,
366                               const char* queryToExtract);
367 /**
368  * Helper function to remove query part from URL spec or path.
369  */
370 void MsgRemoveQueryPart(nsCString& aSpec);
371 
372 /**
373  * Helper macro for defining getter/setters. Ported from nsISupportsObsolete.h
374  */
375 #define NS_IMPL_GETSET(clazz, attr, type, member) \
376   NS_IMETHODIMP clazz::Get##attr(type* result) {  \
377     NS_ENSURE_ARG_POINTER(result);                \
378     *result = member;                             \
379     return NS_OK;                                 \
380   }                                               \
381   NS_IMETHODIMP clazz::Set##attr(type aValue) {   \
382     member = aValue;                              \
383     return NS_OK;                                 \
384   }
385 
386 /**
387  * Macro and helper function for reporting an error, warning or
388  * informational message to the Error Console
389  *
390  * This will require the inclusion of the following files in the source file
391  * #include "nsIScriptError.h"
392  * #include "nsIConsoleService.h"
393  *
394  */
395 
396 NS_MSG_BASE
397 void MsgLogToConsole4(const nsAString& aErrorText, const nsAString& aFilename,
398                       uint32_t aLine, uint32_t flags);
399 
400 // Macro with filename and line number
401 #define MSG_LOG_TO_CONSOLE(_text, _flag)                  \
402   MsgLogToConsole4(NS_LITERAL_STRING_FROM_CSTRING(_text), \
403                    NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, _flag)
404 #define MSG_LOG_ERR_TO_CONSOLE(_text) \
405   MSG_LOG_TO_CONSOLE(_text, nsIScriptError::errorFlag)
406 #define MSG_LOG_WARN_TO_CONSOLE(_text) \
407   MSG_LOG_TO_CONSOLE(_text, nsIScriptError::warningFlag)
408 #define MSG_LOG_INFO_TO_CONSOLE(_text) \
409   MSG_LOG_TO_CONSOLE(_text, nsIScriptError::infoFlag)
410 
411 // Helper macros to cope with shoddy I/O error reporting (or lack thereof)
412 #define MSG_NS_ERROR(_txt)        \
413   do {                            \
414     NS_ERROR(_txt);               \
415     MSG_LOG_ERR_TO_CONSOLE(_txt); \
416   } while (0)
417 #define MSG_NS_WARNING(_txt)       \
418   do {                             \
419     NS_WARNING(_txt);              \
420     MSG_LOG_WARN_TO_CONSOLE(_txt); \
421   } while (0)
422 #define MSG_NS_WARN_IF_FALSE(_val, _txt) \
423   do {                                   \
424     if (!(_val)) {                       \
425       NS_WARNING(_txt);                  \
426       MSG_LOG_WARN_TO_CONSOLE(_txt);     \
427     }                                    \
428   } while (0)
429 #define MSG_NS_INFO(_txt)                                             \
430   do {                                                                \
431     MSG_LOCAL_INFO_TO_CONSOLE(_txt);                                  \
432     fprintf(stderr, "(info) %s (%s:%d)\n", _txt, __FILE__, __LINE__); \
433   } while (0)
434 
435 #endif
436