summaryrefslogtreecommitdiffstats
path: root/mailnews/import/outlook/src/MapiMessage.h
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/import/outlook/src/MapiMessage.h')
-rw-r--r--mailnews/import/outlook/src/MapiMessage.h271
1 files changed, 271 insertions, 0 deletions
diff --git a/mailnews/import/outlook/src/MapiMessage.h b/mailnews/import/outlook/src/MapiMessage.h
new file mode 100644
index 000000000..dc6a6cda1
--- /dev/null
+++ b/mailnews/import/outlook/src/MapiMessage.h
@@ -0,0 +1,271 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef MapiMessage_h___
+#define MapiMessage_h___
+
+#include "nsTArray.h"
+#include "nsStringGlue.h"
+#include "nsIFile.h"
+#include "MapiApi.h"
+#include "nsIMsgSend.h"
+
+#include <vector>
+
+#ifndef PR_LAST_VERB_EXECUTED
+#define PR_LAST_VERB_EXECUTED PROP_TAG(PT_LONG, 0x1081)
+#endif
+
+#define EXCHIVERB_REPLYTOSENDER (102)
+#define EXCHIVERB_REPLYTOALL (103)
+#define EXCHIVERB_FORWARD (104)
+
+#ifndef PR_ATTACH_CONTENT_ID
+#define PR_ATTACH_CONTENT_ID PROP_TAG(PT_TSTRING, 0x3712)
+#endif
+#ifndef PR_ATTACH_CONTENT_ID_W
+#define PR_ATTACH_CONTENT_ID_W PROP_TAG(PT_UNICODE, 0x3712)
+#endif
+#ifndef PR_ATTACH_CONTENT_ID_A
+#define PR_ATTACH_CONTENT_ID_A PROP_TAG(PT_STRING8, 0x3712)
+#endif
+
+#ifndef PR_ATTACH_FLAGS
+#define PR_ATTACH_FLAGS PROP_TAG(PT_LONG, 0x3714)
+#endif
+
+#ifndef ATT_INVISIBLE_IN_HTML
+#define ATT_INVISIBLE_IN_HTML (0x1)
+#endif
+#ifndef ATT_INVISIBLE_IN_RTF
+#define ATT_INVISIBLE_IN_RTF (0x2)
+#endif
+#ifndef ATT_MHTML_REF
+#define ATT_MHTML_REF (0x4)
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+
+class CMapiMessageHeaders {
+public:
+ // Special headers that MUST appear at most once (see RFC822)
+ enum SpecialHeader { hdrNone=-1, hdrFirst = 0, // utility values
+ hdrDate=hdrFirst,
+ hdrFrom,
+ hdrSender,
+ hdrReplyTo,
+ hdrTo,
+ hdrCc,
+ hdrBcc,
+ hdrMessageID,
+ hdrSubject,
+ hdrMimeVersion,
+ hdrContentType,
+ hdrContentTransferEncoding,
+ hdrMax // utility value
+ };
+
+ CMapiMessageHeaders(const char* headers = 0) { Assign(headers); }
+ ~CMapiMessageHeaders();
+ void Assign(const char* headers);
+
+ inline bool IsEmpty() const { return m_headerFields.empty(); }
+ // if no such header exists then 0 is returned, else the first value returned
+ const char* Value(const char* name) const;
+ // if no such header exists then 0 is returned
+ const char* Value(SpecialHeader special) const;
+
+ void UnfoldValue(const char* name, nsString& dest, const char* fallbackCharset) const;
+ void UnfoldValue(SpecialHeader special, nsString& dest, const char* fallbackCharset) const;
+
+ // value must be utf-8 or 7-bit; supposed that this function will be called
+ // when the charset of the value is known
+ // TODO: if replace is set, then all headers with this name will be removed
+ // and one with this value will be added, otherwise a new header is added
+ // (Unnecessary for now)
+ int SetValue(const char* name, const char* value, bool replace = true);
+ int SetValue(SpecialHeader special, const char* value);
+
+ static const char* SpecialName(SpecialHeader special);
+
+ nsresult ToStream(nsIOutputStream *pDst) const;
+private:
+ class CHeaderField {
+ public:
+ CHeaderField(const char* begin, int len);
+ CHeaderField(const char* name, const char* body, bool utf8 = false);
+ ~CHeaderField();
+ inline bool Valid() const { return m_fname; }
+ inline const char* fname() const { return m_fname; }
+ inline const char* fbody() const { return m_fbody; }
+
+ // txt must be utf-8 or 7-bit; supposed that this function will be called
+ // when the charset of the txt is known
+ void set_fbody(const char* txt);
+
+ void GetUnfoldedString(nsString& dest, const char* fallbackCharset) const;
+ private:
+ char* m_fname;
+ char* m_fbody;
+ bool m_fbody_utf8;
+ }; //class HeaderField
+
+ class write_to_stream {
+ public:
+ write_to_stream(nsIOutputStream *pDst) : m_pDst(pDst), m_rv(NS_OK) {}
+ void operator () (const CHeaderField* f);
+ inline operator nsresult() const { return m_rv; }
+ private:
+ nsIOutputStream *m_pDst;
+ nsresult m_rv;
+ };
+
+ // Search helper
+ class fname_equals {
+ public:
+ fname_equals(const char* search) : m_search(search) {}
+ inline bool operator () (const CHeaderField* f) const { return stricmp(f->fname(), m_search) == 0; }
+ private:
+ const char* m_search;
+ }; // class fname_equals
+
+ // The common array of special headers' names
+ static const char* Specials[hdrMax];
+
+ std::vector<CHeaderField*> m_headerFields;
+ CHeaderField* m_SpecialHeaders[hdrMax]; // Pointers into the m_headerFields
+
+ void ClearHeaderFields();
+ void Add(CHeaderField* f);
+ static SpecialHeader CheckSpecialHeader(const char* fname);
+ const CHeaderField* CFind(const char* name) const;
+ inline CHeaderField* Find(const char* name) { return const_cast<CHeaderField*>(CFind(name)); }
+
+}; // class CMapiMessageHeaders
+
+//////////////////////////////////////////////////////
+
+class CMapiMessage {
+public:
+ CMapiMessage(LPMESSAGE lpMsg);
+ ~CMapiMessage();
+
+ // Attachments
+ // Ordinary (not embedded) attachments.
+ nsresult GetAttachments(nsIArray **aArray);
+ // Embedded attachments
+ size_t EmbeddedAttachmentsCount() const { return m_embattachments.size(); }
+ bool GetEmbeddedAttachmentInfo(unsigned int i, nsIURI **uri, const char **cid,
+ const char **name) const;
+ // We don't check MSGFLAG_HASATTACH, since it returns true even if there are
+ // only embedded attachmentsin the message. TB only counts the ordinary
+ // attachments when shows the message status, so here we check only for the
+ // ordinary attachments.
+ inline bool HasAttach() const { return !m_stdattachments.empty(); }
+
+ // Retrieve info for message
+ inline bool BodyIsHtml(void) const { return m_bodyIsHtml;}
+ const char *GetFromLine(int& len) const {
+ if (m_fromLine.IsEmpty())
+ return NULL;
+ else {
+ len = m_fromLine.Length();
+ return m_fromLine.get();}
+ }
+ inline CMapiMessageHeaders *GetHeaders() { return &m_headers; }
+ inline const wchar_t *GetBody(void) const { return m_body.get(); }
+ inline size_t GetBodyLen(void) const { return m_body.Length(); }
+ void GetBody(nsCString& dest) const;
+ inline const char *GetBodyCharset(void) const { return m_mimeCharset.get();}
+ inline bool IsRead() const { return m_msgFlags & MSGFLAG_READ; }
+ inline bool IsReplied() const {
+ return (m_msgLastVerb == EXCHIVERB_REPLYTOSENDER) ||
+ (m_msgLastVerb == EXCHIVERB_REPLYTOALL); }
+ inline bool IsForvarded() const {
+ return m_msgLastVerb == EXCHIVERB_FORWARD; }
+
+ bool HasContentHeader(void) const {
+ return !m_mimeContentType.IsEmpty();}
+ bool HasMimeVersion(void) const {
+ return m_headers.Value(CMapiMessageHeaders::hdrMimeVersion); }
+ const char *GetMimeContent(void) const { return m_mimeContentType.get();}
+ int32_t GetMimeContentLen(void) const { return m_mimeContentType.Length();}
+ const char *GetMimeBoundary(void) const { return m_mimeBoundary.get();}
+
+ // The only required part of a message is its header
+ inline bool ValidState() const { return !m_headers.IsEmpty(); }
+ inline bool FullMessageDownloaded() const { return !m_dldStateHeadersOnly; }
+
+private:
+ struct attach_data {
+ nsCOMPtr<nsIURI> orig_url;
+ nsCOMPtr<nsIFile> tmp_file;
+ char *type;
+ char *encoding;
+ char *real_name;
+ char *cid;
+ bool delete_file;
+ attach_data() : type(0), encoding(0), real_name(0), cid(0), delete_file(false) {}
+ };
+
+ static const nsCString m_whitespace;
+
+ LPMESSAGE m_lpMsg;
+
+ bool m_dldStateHeadersOnly; // if the message has not been downloaded yet
+ CMapiMessageHeaders m_headers;
+ nsCString m_fromLine; // utf-8
+ nsCString m_mimeContentType; // utf-8
+ nsCString m_mimeBoundary; // utf-8
+ nsCString m_mimeCharset; // utf-8
+
+ std::vector<attach_data*> m_stdattachments;
+ std::vector<attach_data*> m_embattachments; // Embedded
+
+ nsString m_body; // to be converted from UTF-16 using m_mimeCharset
+ bool m_bodyIsHtml;
+
+ uint32_t m_msgFlags;
+ uint32_t m_msgLastVerb;
+
+ nsCOMPtr<nsIIOService> m_pIOService;
+
+ void GetDownloadState();
+
+ // Headers - fetch will get PR_TRANSPORT_MESSAGE_HEADERS
+ // or if they do not exist will build a header from
+ // PR_DISPLAY_TO, _CC, _BCC
+ // PR_SUBJECT
+ // PR_MESSAGE_RECIPIENTS
+ // and PR_CREATION_TIME if needed?
+ bool FetchHeaders(void);
+ bool FetchBody(void);
+ void FetchFlags(void);
+
+ static bool GetTmpFile(/*out*/ nsIFile **aResult);
+ static bool CopyMsgAttachToFile(LPATTACH lpAttach, /*out*/ nsIFile **tmp_file);
+ static bool CopyBinAttachToFile(LPATTACH lpAttach, nsIFile **tmp_file);
+
+ static void ClearAttachment(attach_data* data);
+ void ClearAttachments();
+ bool AddAttachment(DWORD aNum);
+ bool IterateAttachTable(LPMAPITABLE tbl);
+ bool GetURL(nsIFile *aFile, nsIURI **url);
+ void ProcessAttachments();
+
+ bool EnsureHeader(CMapiMessageHeaders::SpecialHeader special, ULONG mapiTag);
+ bool EnsureDate();
+
+ void ProcessContentType();
+ bool CheckBodyInCharsetRange(const char* charset);
+ void FormatDateTime(SYSTEMTIME& tm, nsCString& s, bool includeTZ = true);
+ void BuildFromLine(void);
+
+ inline static bool IsSpace(char c) {
+ return c == ' ' || c == '\r' || c == '\n' || c == '\b' || c == '\t';}
+ inline static bool IsSpace(wchar_t c) {
+ return ((c & 0xFF) == c) && IsSpace(static_cast<char>(c)); } // Avoid false detections
+};
+
+#endif /* MapiMessage_h__ */