diff options
author | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
commit | 302bf1b523012e11b60425d6eee1221ebc2724eb (patch) | |
tree | b191a895f8716efcbe42f454f37597a545a6f421 /mailnews/imap/src/nsIMAPBodyShell.h | |
parent | 21b3f6247403c06f85e1f45d219f87549862198f (diff) | |
download | UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip |
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/imap/src/nsIMAPBodyShell.h')
-rw-r--r-- | mailnews/imap/src/nsIMAPBodyShell.h | 361 |
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 |