summaryrefslogtreecommitdiffstats
path: root/mailnews/imap/src/nsIMAPBodyShell.h
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/imap/src/nsIMAPBodyShell.h')
-rw-r--r--mailnews/imap/src/nsIMAPBodyShell.h361
1 files changed, 361 insertions, 0 deletions
diff --git a/mailnews/imap/src/nsIMAPBodyShell.h b/mailnews/imap/src/nsIMAPBodyShell.h
new file mode 100644
index 000000000..1c8d58ae5
--- /dev/null
+++ b/mailnews/imap/src/nsIMAPBodyShell.h
@@ -0,0 +1,361 @@
+/* -*- Mode: C++; tab-width: 4; 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/. */
+
+/*
+nsIMAPBodyShell and associated classes
+*/
+
+#ifndef IMAPBODY_H
+#define IMAPBODY_H
+
+#include "mozilla/Attributes.h"
+#include "nsImapCore.h"
+#include "nsStringGlue.h"
+#include "nsRefPtrHashtable.h"
+#include "nsTArray.h"
+
+class nsImapProtocol;
+
+typedef enum _nsIMAPBodypartType {
+ IMAP_BODY_MESSAGE_RFC822,
+ IMAP_BODY_MESSAGE_HEADER,
+ IMAP_BODY_LEAF,
+ IMAP_BODY_MULTIPART
+} nsIMAPBodypartType;
+
+class nsIMAPBodyShell;
+class nsIMAPBodypartMessage;
+
+class nsIMAPBodypart
+{
+public:
+ // Construction
+ virtual bool GetIsValid() { return m_isValid; }
+ virtual void SetIsValid(bool valid);
+ virtual nsIMAPBodypartType GetType() = 0;
+
+ // Generation
+ // Generates an HTML representation of this part. Returns content length generated, -1 if failed.
+ virtual int32_t Generate(nsIMAPBodyShell *aShell, bool /*stream*/, bool /* prefetch */) { return -1; }
+ virtual void AdoptPartDataBuffer(char *buf); // Adopts storage for part data buffer. If NULL, sets isValid to false.
+ virtual void AdoptHeaderDataBuffer(char *buf); // Adopts storage for header data buffer. If NULL, sets isValid to false.
+ virtual bool ShouldFetchInline(nsIMAPBodyShell *aShell) { return true; } // returns true if this part should be fetched inline for generation.
+ virtual bool PreflightCheckAllInline(nsIMAPBodyShell *aShell) { return true; }
+
+ virtual bool ShouldExplicitlyFetchInline();
+ virtual bool ShouldExplicitlyNotFetchInline();
+ virtual bool IsLastTextPart(const char *partNumberString) {return true;}
+
+protected:
+ // If stream is false, simply returns the content length that will be generated
+ // the body of the part itself
+ virtual int32_t GeneratePart(nsIMAPBodyShell *aShell, bool stream, bool prefetch);
+ // the MIME headers of the part
+ virtual int32_t GenerateMIMEHeader(nsIMAPBodyShell *aShell, bool stream, bool prefetch);
+ // Generates the MIME boundary wrapper for this part.
+ virtual int32_t GenerateBoundary(nsIMAPBodyShell *aShell, bool stream, bool prefetch, bool lastBoundary);
+ // lastBoundary indicates whether or not this should be the boundary for the
+ // final MIME part of the multipart message.
+ // Generates (possibly empty) filling for a part that won't be filled in inline.
+ virtual int32_t GenerateEmptyFilling(nsIMAPBodyShell *aShell, bool stream, bool prefetch);
+
+ // Part Numbers / Hierarchy
+public:
+ virtual char *GetPartNumberString() { return m_partNumberString; }
+ virtual nsIMAPBodypart *FindPartWithNumber(const char *partNum); // Returns the part object with the given number
+ virtual nsIMAPBodypart *GetParentPart() { return m_parentPart; } // Returns the parent of this part.
+ // We will define a part of type message/rfc822 to be the
+ // parent of its body and header.
+ // A multipart is a parent of its child parts.
+ // All other leafs do not have children.
+
+ // Other / Helpers
+public:
+ virtual ~nsIMAPBodypart();
+ virtual nsIMAPBodypartMessage *GetnsIMAPBodypartMessage() { return NULL; }
+
+ const char *GetBodyType() { return m_bodyType; }
+ const char *GetBodySubType() { return m_bodySubType; }
+ void SetBoundaryData(char *boundaryData) { m_boundaryData = boundaryData; }
+
+protected:
+ virtual void QueuePrefetchMIMEHeader(nsIMAPBodyShell *aShell);
+ //virtual void PrefetchMIMEHeader(); // Initiates a prefetch for the MIME header of this part.
+ nsIMAPBodypart(char *partNumber, nsIMAPBodypart *parentPart);
+
+protected:
+ bool m_isValid; // If this part is valid.
+ char *m_partNumberString; // string representation of this part's full-hierarchy number. Define 0 to be the top-level message
+ char *m_partData; // data for this part. NULL if not filled in yet.
+ char *m_headerData; // data for this part's MIME header. NULL if not filled in yet.
+ char *m_boundaryData; // MIME boundary for this part
+ int32_t m_partLength;
+ int32_t m_contentLength; // Total content length which will be Generate()'d. -1 if not filled in yet.
+ nsIMAPBodypart *m_parentPart; // Parent of this part
+
+ // Fields - Filled in from parsed BODYSTRUCTURE response (as well as others)
+ char *m_contentType; // constructed from m_bodyType and m_bodySubType
+ char *m_bodyType;
+ char *m_bodySubType;
+ char *m_bodyID;
+ char *m_bodyDescription;
+ char *m_bodyEncoding;
+ // we ignore extension data for now
+};
+
+
+
+// Message headers
+// A special type of nsIMAPBodypart
+// These may be headers for the top-level message,
+// or any body part of type message/rfc822.
+class nsIMAPMessageHeaders : public nsIMAPBodypart
+{
+public:
+ nsIMAPMessageHeaders(char *partNum, nsIMAPBodypart *parentPart);
+ virtual nsIMAPBodypartType GetType() override;
+ // Generates an HTML representation of this part. Returns content length generated, -1 if failed.
+ virtual int32_t Generate(nsIMAPBodyShell *aShell, bool stream,
+ bool prefetch) override;
+ virtual bool ShouldFetchInline(nsIMAPBodyShell *aShell) override;
+ virtual void QueuePrefetchMessageHeaders(nsIMAPBodyShell *aShell);
+};
+
+
+class nsIMAPBodypartMultipart : public nsIMAPBodypart
+{
+public:
+ nsIMAPBodypartMultipart(char *partNum, nsIMAPBodypart *parentPart);
+ virtual nsIMAPBodypartType GetType() override;
+ virtual ~nsIMAPBodypartMultipart();
+ virtual bool ShouldFetchInline(nsIMAPBodyShell *aShell) override;
+ virtual bool PreflightCheckAllInline(nsIMAPBodyShell *aShell) override;
+ // Generates an HTML representation of this part. Returns content length generated, -1 if failed.
+ virtual int32_t Generate(nsIMAPBodyShell *aShell, bool stream,
+ bool prefetch) override;
+ // Returns the part object with the given number
+ virtual nsIMAPBodypart *FindPartWithNumber(const char *partNum
+ ) override;
+ virtual bool IsLastTextPart(const char *partNumberString) override;
+ void AppendPart(nsIMAPBodypart *part) { m_partList->AppendElement(part); }
+ void SetBodySubType(char *bodySubType);
+
+protected:
+ nsTArray<nsIMAPBodypart*> *m_partList; // An ordered list of top-level body parts for this shell
+};
+
+
+// The name "leaf" is somewhat misleading, since a part of type message/rfc822 is technically
+// a leaf, even though it can contain other parts within it.
+class nsIMAPBodypartLeaf : public nsIMAPBodypart
+{
+public:
+ nsIMAPBodypartLeaf(char *partNum, nsIMAPBodypart *parentPart, char *bodyType,
+ char *bodySubType, char *bodyID, char *bodyDescription,
+ char *bodyEncoding, int32_t partLength,
+ bool preferPlainText);
+ virtual nsIMAPBodypartType GetType() override;
+ // Generates an HTML representation of this part. Returns content length generated, -1 if failed.
+ virtual int32_t Generate(nsIMAPBodyShell *aShell, bool stream, bool prefetch) override;
+ // returns true if this part should be fetched inline for generation.
+ virtual bool ShouldFetchInline(nsIMAPBodyShell *aShell) override;
+ virtual bool PreflightCheckAllInline(nsIMAPBodyShell *aShell) override;
+private:
+ bool mPreferPlainText;
+};
+
+
+class nsIMAPBodypartMessage : public nsIMAPBodypartLeaf
+{
+public:
+ nsIMAPBodypartMessage(char *partNum, nsIMAPBodypart *parentPart,
+ bool topLevelMessage, char *bodyType,
+ char *bodySubType, char *bodyID,
+ char *bodyDescription, char *bodyEncoding,
+ int32_t partLength, bool preferPlainText);
+ void SetBody(nsIMAPBodypart *body);
+ virtual nsIMAPBodypartType GetType() override;
+ virtual ~nsIMAPBodypartMessage();
+ virtual int32_t Generate(nsIMAPBodyShell *aShell, bool stream,
+ bool prefetch) override;
+ virtual bool ShouldFetchInline(nsIMAPBodyShell *aShell) override;
+ virtual bool PreflightCheckAllInline(nsIMAPBodyShell *aShell) override;
+ // Returns the part object with the given number
+ virtual nsIMAPBodypart *FindPartWithNumber(const char *partNum
+ ) override;
+ void AdoptMessageHeaders(char *headers); // Fills in buffer (and adopts storage) for header object
+ // partNum specifies the message part number to which the
+ // headers correspond. NULL indicates the top-level message
+ virtual nsIMAPBodypartMessage *GetnsIMAPBodypartMessage() override { return this; }
+ virtual bool GetIsTopLevelMessage() { return m_topLevelMessage; }
+
+protected:
+ nsIMAPMessageHeaders *m_headers; // Every body shell should have headers
+ nsIMAPBodypart *m_body;
+ bool m_topLevelMessage; // Whether or not this is the top-level message
+
+};
+
+
+class nsIMAPMessagePartIDArray;
+
+// We will refer to a Body "Shell" as a hierarchical object representation of a parsed BODYSTRUCTURE
+// response. A shell contains representations of Shell "Parts." A Body Shell can undergo essentially
+// two operations: Construction and Generation.
+// Shell Construction occurs from a parsed a BODYSTRUCTURE response, split into empty parts.
+// Shell Generation generates a "MIME Shell" of the message and streams it to libmime for
+// display. The MIME Shell has selected (inline) parts filled in, and leaves all others
+// for on-demand retrieval through explicit part fetches.
+
+class nsIMAPBodyShell : public nsISupports
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ nsIMAPBodyShell(nsImapProtocol *protocolConnection,
+ nsIMAPBodypartMessage *message, uint32_t UID,
+ const char *folderName);
+ // To be used after a shell is uncached
+ void SetConnection(nsImapProtocol *con) { m_protocolConnection = con; }
+ virtual bool GetIsValid() { return m_isValid; }
+ virtual void SetIsValid(bool valid);
+
+ // Prefetch
+ // Adds a message body part to the queue to be prefetched
+ // in a single, pipelined command
+ void AddPrefetchToQueue(nsIMAPeFetchFields, const char *partNum);
+ // Runs a single pipelined command which fetches all of the
+ // elements in the prefetch queue
+ void FlushPrefetchQueue();
+ // Fills in buffer (and adopts storage) for header object
+ // partNum specifies the message part number to which the
+ // headers correspond. NULL indicates the top-level message
+ void AdoptMessageHeaders(char *headers, const char *partNum);
+ // Fills in buffer (and adopts storage) for MIME headers in appropriate object.
+ // If object can't be found, sets isValid to false.
+ void AdoptMimeHeader(const char *partNum, char *mimeHeader);
+
+ // Generation
+ // Streams out an HTML representation of this IMAP message, going along and
+ // fetching parts it thinks it needs, and leaving empty shells for the parts
+ // it doesn't.
+ // Returns number of bytes generated, or -1 if invalid.
+ // If partNum is not NULL, then this works to generates a MIME part that hasn't been downloaded yet
+ // and leaves out all other parts. By default, to generate a normal message, partNum should be NULL.
+ virtual int32_t Generate(char *partNum);
+
+ // Returns TRUE if the user has the pref "Show Attachments Inline" set.
+ // Returns FALSE if the setting is "Show Attachments as Links"
+ virtual bool GetShowAttachmentsInline();
+ // Returns true if all parts are inline, false otherwise. Does not generate anything.
+ bool PreflightCheckAllInline();
+
+ // Helpers
+ nsImapProtocol *GetConnection() { return m_protocolConnection; }
+ bool GetPseudoInterrupted();
+ bool DeathSignalReceived();
+ nsCString &GetUID() { return m_UID; }
+ const char *GetFolderName() { return m_folderName; }
+ char *GetGeneratingPart() { return m_generatingPart; }
+ // Returns true if this is in the process of being generated,
+ // so we don't re-enter
+ bool IsBeingGenerated() { return m_isBeingGenerated; }
+ bool IsShellCached() { return m_cached; }
+ void SetIsCached(bool isCached) { m_cached = isCached; }
+ bool GetGeneratingWholeMessage() { return m_generatingWholeMessage; }
+ IMAP_ContentModifiedType GetContentModified() { return m_contentModified; }
+ void SetContentModified(IMAP_ContentModifiedType modType) { m_contentModified = modType; }
+protected:
+ virtual ~nsIMAPBodyShell();
+
+ nsIMAPBodypartMessage *m_message;
+
+ nsIMAPMessagePartIDArray *m_prefetchQueue; // array of pipelined part prefetches. Ok, so it's not really a queue.
+
+ bool m_isValid;
+ nsImapProtocol *m_protocolConnection; // Connection, for filling in parts
+ nsCString m_UID; // UID of this message
+ char *m_folderName; // folder that contains this message
+ char *m_generatingPart; // If a specific part is being generated, this is it. Otherwise, NULL.
+ bool m_isBeingGenerated; // true if this body shell is in the process of being generated
+ bool m_gotAttachmentPref; // Whether or not m_showAttachmentsInline has been initialized
+ bool m_showAttachmentsInline; // Whether or not we should display attachment inline
+ bool m_cached; // Whether or not this shell is cached
+ bool m_generatingWholeMessage; // whether or not we are generating the whole (non-MPOD) message
+ // Set to false if we are generating by parts
+ // under what conditions the content has been modified.
+ // Either IMAP_CONTENT_MODIFIED_VIEW_INLINE or IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS
+ IMAP_ContentModifiedType m_contentModified;
+};
+
+
+
+// This class caches shells, so we don't have to always go and re-fetch them.
+// This does not cache any of the filled-in inline parts; those are cached individually
+// in the libnet memory cache. (ugh, how will we do that?)
+// Since we'll only be retrieving shells for messages over a given size, and since the
+// shells themselves won't be very large, this cache will not grow very big (relatively)
+// and should handle most common usage scenarios.
+
+// A body cache is associated with a given host, spanning folders.
+// It should pay attention to UIDVALIDITY.
+
+class nsIMAPBodyShellCache
+{
+public:
+ static nsIMAPBodyShellCache *Create();
+ virtual ~nsIMAPBodyShellCache();
+
+ // Adds shell to cache, possibly ejecting
+ // another entry based on scheme in EjectEntry().
+ bool AddShellToCache(nsIMAPBodyShell *shell);
+ // Looks up a shell in the cache given the message's UID.
+ nsIMAPBodyShell *FindShellForUID(nsCString &UID, const char *mailboxName,
+ IMAP_ContentModifiedType modType);
+ void Clear();
+
+protected:
+ nsIMAPBodyShellCache();
+ // Chooses an entry to eject; deletes that entry; and ejects it from the
+ // cache, clearing up a new space. Returns true if it found an entry
+ // to eject, false otherwise.
+ bool EjectEntry();
+ uint32_t GetSize() { return m_shellList->Length(); }
+ uint32_t GetMaxSize() { return 20; }
+ nsTArray<nsIMAPBodyShell*> *m_shellList; // For maintenance
+ // For quick lookup based on UID
+ nsRefPtrHashtable <nsCStringHashKey, nsIMAPBodyShell> m_shellHash;
+};
+
+// MessagePartID and MessagePartIDArray are used for pipelining prefetches.
+
+class nsIMAPMessagePartID
+{
+public:
+ nsIMAPMessagePartID(nsIMAPeFetchFields fields, const char *partNumberString);
+ nsIMAPeFetchFields GetFields() { return m_fields; }
+ const char *GetPartNumberString() { return m_partNumberString; }
+
+protected:
+ const char *m_partNumberString;
+ nsIMAPeFetchFields m_fields;
+};
+
+
+class nsIMAPMessagePartIDArray : public nsTArray<nsIMAPMessagePartID*> {
+public:
+ nsIMAPMessagePartIDArray();
+ ~nsIMAPMessagePartIDArray();
+
+ void RemoveAndFreeAll();
+ uint32_t GetNumParts() { return Length(); }
+ nsIMAPMessagePartID *GetPart(uint32_t i)
+ {
+ NS_ASSERTION(i < Length(), "invalid message part #");
+ return ElementAt(i);
+ }
+};
+
+
+#endif // IMAPBODY_H