Back to index

lightning-sunbird  0.9+nobinonly
nsIMAPBodyShell.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /* 
00039 nsIMAPBodyShell and associated classes
00040 */ 
00041 
00042 #ifndef IMAPBODY_H
00043 #define IMAPBODY_H
00044 
00045 #include "nsImapCore.h"
00046 #include "nsString.h"
00047 
00048 class nsImapProtocol;
00049 
00050 typedef enum _nsIMAPBodypartType {
00051        IMAP_BODY_MESSAGE_RFC822,
00052        IMAP_BODY_MESSAGE_HEADER,
00053        IMAP_BODY_LEAF,
00054        IMAP_BODY_MULTIPART
00055 } nsIMAPBodypartType;
00056 
00057 class nsIMAPBodyShell;
00058 class nsIMAPBodypartMessage;
00059 class nsHashtable;
00060 
00061 class nsIMAPBodypart
00062 {
00063 public:
00064        // Construction
00065        virtual PRBool GetIsValid() { return m_isValid; }
00066        virtual void  SetIsValid(PRBool valid);
00067        virtual nsIMAPBodypartType  GetType() = 0;
00068 
00069        // Generation
00070     // Generates an HTML representation of this part.  Returns content length generated, -1 if failed.
00071     virtual PRInt32 Generate(nsIMAPBodyShell *aShell, PRBool /*stream*/, PRBool /* prefetch */) { return -1; }
00072     virtual void AdoptPartDataBuffer(char *buf);    // Adopts storage for part data buffer.  If NULL, sets isValid to PR_FALSE.
00073     virtual void AdoptHeaderDataBuffer(char *buf);  // Adopts storage for header data buffer.  If NULL, sets isValid to PR_FALSE.
00074     virtual PRBool ShouldFetchInline(nsIMAPBodyShell *aShell) { return PR_TRUE; }  // returns PR_TRUE if this part should be fetched inline for generation.
00075     virtual PRBool PreflightCheckAllInline(nsIMAPBodyShell *aShell) { return PR_TRUE; }
00076 
00077        virtual PRBool ShouldExplicitlyFetchInline();
00078        virtual PRBool ShouldExplicitlyNotFetchInline();
00079         virtual PRBool IsLastTextPart(const char *partNumberString) {return PR_TRUE;}
00080 
00081 protected:
00082     // If stream is PR_FALSE, simply returns the content length that will be generated
00083     // the body of the part itself
00084     virtual PRInt32 GeneratePart(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00085     // the MIME headers of the part
00086     virtual PRInt32 GenerateMIMEHeader(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch); 
00087     // Generates the MIME boundary wrapper for this part.
00088     virtual PRInt32 GenerateBoundary(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch, PRBool lastBoundary);
00089     // lastBoundary indicates whether or not this should be the boundary for the
00090     // final MIME part of the multipart message.
00091     // Generates (possibly empty) filling for a part that won't be filled in inline.
00092     virtual PRInt32 GenerateEmptyFilling(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00093 
00094        // Part Numbers / Hierarchy
00095 public:
00096        virtual char  *GetPartNumberString() { return m_partNumberString; }
00097        virtual nsIMAPBodypart      *FindPartWithNumber(const char *partNum); // Returns the part object with the given number
00098        virtual nsIMAPBodypart      *GetParentPart() { return m_parentPart; } // Returns the parent of this part.
00099                                                                                                                               // We will define a part of type message/rfc822 to be the
00100                                                                                                                               // parent of its body and header.
00101                                                                                                                               // A multipart is a parent of its child parts.
00102                                                                                                                               // All other leafs do not have children.
00103 
00104        // Other / Helpers
00105 public:
00106        virtual ~nsIMAPBodypart();
00107        virtual nsIMAPBodypartMessage      *GetnsIMAPBodypartMessage() { return NULL; }
00108 
00109        const char    *GetBodyType() { return m_bodyType; }
00110        const char    *GetBodySubType() { return m_bodySubType; }
00111     void SetBoundaryData(char *boundaryData) { m_boundaryData = boundaryData; }
00112 
00113 protected:
00114     virtual void QueuePrefetchMIMEHeader(nsIMAPBodyShell *aShell);
00115        //virtual void       PrefetchMIMEHeader();                     // Initiates a prefetch for the MIME header of this part.
00116     nsIMAPBodypart(char *partNumber, nsIMAPBodypart *parentPart);
00117 
00118 protected:
00119        PRBool m_isValid;                         // If this part is valid.
00120        char   *m_partNumberString; // string representation of this part's full-hierarchy number.  Define 0 to be the top-level message
00121        char   *m_partData;                // data for this part.  NULL if not filled in yet.
00122        char   *m_headerData;                     // data for this part's MIME header.  NULL if not filled in yet.
00123        char   *m_boundaryData;            // MIME boundary for this part
00124        PRInt32       m_partLength;
00125        PRInt32       m_contentLength;            // Total content length which will be Generate()'d.  -1 if not filled in yet.
00126        nsIMAPBodypart       *m_parentPart;       // Parent of this part
00127 
00128        // Fields     - Filled in from parsed BODYSTRUCTURE response (as well as others)
00129        char   *m_contentType;                    // constructed from m_bodyType and m_bodySubType
00130        char   *m_bodyType;
00131        char   *m_bodySubType;
00132        char   *m_bodyID;
00133        char   *m_bodyDescription;
00134        char   *m_bodyEncoding;
00135        // we ignore extension data for now
00136 };
00137 
00138 
00139 
00140 // Message headers
00141 // A special type of nsIMAPBodypart
00142 // These may be headers for the top-level message,
00143 // or any body part of type message/rfc822.
00144 class nsIMAPMessageHeaders : public nsIMAPBodypart
00145 {
00146 public:
00147     nsIMAPMessageHeaders(char *partNum, nsIMAPBodypart *parentPart);
00148        virtual nsIMAPBodypartType  GetType();
00149     // Generates an HTML representation of this part.  Returns content length generated, -1 if failed.
00150     virtual PRInt32 Generate(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00151     virtual PRBool ShouldFetchInline(nsIMAPBodyShell *aShell);
00152     virtual void QueuePrefetchMessageHeaders(nsIMAPBodyShell *aShell);
00153 };
00154 
00155 
00156 class nsIMAPBodypartMultipart : public nsIMAPBodypart
00157 {
00158 public:
00159     nsIMAPBodypartMultipart(char *partNum, nsIMAPBodypart *parentPart);
00160        virtual nsIMAPBodypartType  GetType();
00161        virtual ~nsIMAPBodypartMultipart();
00162     virtual PRBool ShouldFetchInline(nsIMAPBodyShell *aShell);
00163     virtual PRBool PreflightCheckAllInline(nsIMAPBodyShell *aShell);
00164     // Generates an HTML representation of this part.  Returns content length generated, -1 if failed.
00165     virtual PRInt32 Generate(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00166        virtual nsIMAPBodypart      *FindPartWithNumber(const char *partNum); // Returns the part object with the given number
00167         virtual PRBool IsLastTextPart(const char *partNumberString);
00168     void AppendPart(nsIMAPBodypart *part)  { m_partList->AppendElement(part); }
00169     void SetBodySubType(char *bodySubType);
00170 
00171 protected:
00172        nsVoidArray                 *m_partList;                // An ordered list of top-level body parts for this shell
00173 };
00174 
00175 
00176 // The name "leaf" is somewhat misleading, since a part of type message/rfc822 is technically
00177 // a leaf, even though it can contain other parts within it.
00178 class nsIMAPBodypartLeaf : public nsIMAPBodypart
00179 {
00180 public:
00181     nsIMAPBodypartLeaf(char *partNum, nsIMAPBodypart *parentPart,
00182       char *bodyType, char *bodySubType, char *bodyID, char *bodyDescription, char *bodyEncoding, PRInt32 partLength);
00183        virtual nsIMAPBodypartType  GetType();
00184     // Generates an HTML representation of this part.  Returns content length generated, -1 if failed.
00185     virtual PRInt32 Generate(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00186     // returns PR_TRUE if this part should be fetched inline for generation.
00187     virtual PRBool ShouldFetchInline(nsIMAPBodyShell *aShell);
00188     virtual PRBool PreflightCheckAllInline(nsIMAPBodyShell *aShell);
00189 };
00190 
00191 
00192 class nsIMAPBodypartMessage : public nsIMAPBodypartLeaf
00193 {
00194 public:
00195     nsIMAPBodypartMessage(char *partNum, nsIMAPBodypart *parentPart, PRBool topLevelMessage,
00196       char *bodyType, char *bodySubType, char *bodyID, char *bodyDescription, char *bodyEncoding, PRInt32 partLength);
00197     void SetBody(nsIMAPBodypart *body);
00198        virtual nsIMAPBodypartType  GetType();
00199        virtual ~nsIMAPBodypartMessage();
00200     virtual PRInt32 Generate(nsIMAPBodyShell *aShell, PRBool stream, PRBool prefetch);
00201     virtual PRBool ShouldFetchInline(nsIMAPBodyShell *aShell);
00202     virtual PRBool PreflightCheckAllInline(nsIMAPBodyShell *aShell);
00203        virtual nsIMAPBodypart      *FindPartWithNumber(const char *partNum); // Returns the part object with the given number
00204        void   AdoptMessageHeaders(char *headers);                     // Fills in buffer (and adopts storage) for header object
00205                                                                                                   // partNum specifies the message part number to which the
00206                                                                                                   // headers correspond.  NULL indicates the top-level message
00207        virtual nsIMAPBodypartMessage      *GetnsIMAPBodypartMessage() { return this; }
00208        virtual       PRBool        GetIsTopLevelMessage() { return m_topLevelMessage; }
00209 
00210 protected:
00211        nsIMAPMessageHeaders        *m_headers;                        // Every body shell should have headers
00212        nsIMAPBodypart                     *m_body;      
00213        PRBool                             m_topLevelMessage;          // Whether or not this is the top-level message
00214 
00215 };
00216 
00217 
00218 class nsIMAPMessagePartIDArray;
00219 
00220 // We will refer to a Body "Shell" as a hierarchical object representation of a parsed BODYSTRUCTURE
00221 // response.  A shell contains representations of Shell "Parts."  A Body Shell can undergo essentially
00222 // two operations: Construction and Generation.
00223 // Shell Construction occurs from a parsed a BODYSTRUCTURE response, split into empty parts.
00224 // Shell Generation generates a "MIME Shell" of the message and streams it to libmime for
00225 // display.  The MIME Shell has selected (inline) parts filled in, and leaves all others
00226 // for on-demand retrieval through explicit part fetches.
00227 
00228 class nsIMAPBodyShell
00229 {
00230 public:
00231     nsIMAPBodyShell(nsImapProtocol *protocolConnection, nsIMAPBodypartMessage *message, PRUint32 UID, const char *folderName);
00232        virtual ~nsIMAPBodyShell();
00233        void   SetConnection(nsImapProtocol *con) { m_protocolConnection = con; }    // To be used after a shell is uncached
00234        virtual PRBool GetIsValid() { return m_isValid; }
00235        virtual void  SetIsValid(PRBool valid);
00236 
00237        // Prefetch
00238        void   AddPrefetchToQueue(nsIMAPeFetchFields, const char *partNum);   // Adds a message body part to the queue to be prefetched
00239                                                                // in a single, pipelined command
00240        void   FlushPrefetchQueue();       // Runs a single pipelined command which fetches all of the
00241                                                                // elements in the prefetch queue
00242        void   AdoptMessageHeaders(char *headers, const char *partNum);       // Fills in buffer (and adopts storage) for header object
00243                                                                                                                               // partNum specifies the message part number to which the
00244                                                                                                                               // headers correspond.  NULL indicates the top-level message
00245        void   AdoptMimeHeader(const char *partNum, char *mimeHeader); // Fills in buffer (and adopts storage) for MIME headers in appropriate object.
00246                                                                                                                               // If object can't be found, sets isValid to PR_FALSE.
00247 
00248        // Generation
00249        virtual PRInt32 Generate(char *partNum);  // Streams out an HTML representation of this IMAP message, going along and
00250                                                                // fetching parts it thinks it needs, and leaving empty shells for the parts
00251                                                                // it doesn't.
00252                                                                // Returns number of bytes generated, or -1 if invalid.
00253                                                                // If partNum is not NULL, then this works to generates a MIME part that hasn't been downloaded yet
00254                                                                // and leaves out all other parts.  By default, to generate a normal message, partNum should be NULL.
00255 
00256   virtual PRBool GetShowAttachmentsInline();  // Returns TRUE if the user has the pref "Show Attachments Inline" set.
00257                                               // Returns FALSE if the setting is "Show Attachments as Links"
00258   PRBool      PreflightCheckAllInline();           // Returns PR_TRUE if all parts are inline, PR_FALSE otherwise.  Does not generate anything.
00259 
00260   // Helpers
00261   nsImapProtocol *GetConnection() { return m_protocolConnection; }
00262   PRBool      GetPseudoInterrupted();
00263   PRBool DeathSignalReceived();
00264   nsCString &GetUID() { return m_UID; }
00265   const char  *GetFolderName() { return m_folderName; }
00266   char *GetGeneratingPart() { return m_generatingPart; }
00267   PRBool      IsBeingGenerated() { return m_isBeingGenerated; }       // Returns PR_TRUE if this is in the process of being
00268                                                                                                            // generated, so we don't re-enter
00269   PRBool IsShellCached() { return m_cached; }
00270   void SetIsCached(PRBool isCached) { m_cached = isCached; }
00271   PRBool      GetGeneratingWholeMessage() { return m_generatingWholeMessage; }
00272   IMAP_ContentModifiedType  GetContentModified() { return m_contentModified; }
00273   void SetContentModified(IMAP_ContentModifiedType modType) { m_contentModified = modType; }
00274 
00275 protected:
00276 
00277   nsIMAPBodypartMessage     *m_message;
00278 
00279   nsIMAPMessagePartIDArray        *m_prefetchQueue;     // array of pipelined part prefetches.  Ok, so it's not really a queue.
00280 
00281   PRBool                          m_isValid;
00282   nsImapProtocol                  *m_protocolConnection;  // Connection, for filling in parts
00283   nsCString                       m_UID;                  // UID of this message
00284   char                            *m_folderName;          // folder that contains this message
00285   char                            *m_generatingPart;      // If a specific part is being generated, this is it.  Otherwise, NULL.
00286   PRBool                          m_isBeingGenerated;     // PR_TRUE if this body shell is in the process of being generated
00287   PRBool                          m_gotAttachmentPref;    // Whether or not m_showAttachmentsInline has been initialized 
00288   PRBool                          m_showAttachmentsInline; // Whether or not we should display attachment inline
00289   PRBool                          m_cached;                 // Whether or not this shell is cached
00290   PRBool                          m_generatingWholeMessage; // whether or not we are generating the whole (non-MPOD) message
00291                                                           // Set to PR_FALSE if we are generating by parts
00292   IMAP_ContentModifiedType        m_contentModified;    // under what conditions the content has been modified.
00293                                                         // Either IMAP_CONTENT_MODIFIED_VIEW_INLINE or IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS
00294 };
00295 
00296 
00297 
00298 // This class caches shells, so we don't have to always go and re-fetch them.
00299 // This does not cache any of the filled-in inline parts;  those are cached individually
00300 // in the libnet memory cache.  (ugh, how will we do that?)
00301 // Since we'll only be retrieving shells for messages over a given size, and since the
00302 // shells themselves won't be very large, this cache will not grow very big (relatively)
00303 // and should handle most common usage scenarios.
00304 
00305 // A body cache is associated with a given host, spanning folders.
00306 // It should pay attention to UIDVALIDITY.
00307 
00308 class nsIMAPBodyShellCache
00309 {
00310 
00311 public:
00312        static nsIMAPBodyShellCache *Create();
00313        virtual ~nsIMAPBodyShellCache();
00314 
00315        PRBool               AddShellToCache(nsIMAPBodyShell *shell);         // Adds shell to cache, possibly ejecting
00316                                                                                                                 // another entry based on scheme in EjectEntry().
00317        nsIMAPBodyShell      *FindShellForUID(nsCString &UID, const char *mailboxName, IMAP_ContentModifiedType modType);      // Looks up a shell in the cache given the message's UID.
00318        nsIMAPBodyShell      *FindShellForUID(PRUint32 UID, const char *mailboxName, IMAP_ContentModifiedType modType); // Looks up a shell in the cache given the message's UID.
00319                                                                                                          // Returns the shell if found, NULL if not found.
00320 
00321 protected:
00322        nsIMAPBodyShellCache();
00323        PRBool EjectEntry(); // Chooses an entry to eject;  deletes that entry;  and ejects it from the cache,
00324                                                  // clearing up a new space.  Returns PR_TRUE if it found an entry to eject, PR_FALSE otherwise.
00325        PRUint32      GetSize() { return m_shellList->Count(); }
00326        PRUint32      GetMaxSize() { return 20; }
00327 
00328 
00329 protected:
00330        nsVoidArray          *m_shellList; // For maintenance
00331        nsHashtable          *m_shellHash; // For quick lookup based on UID
00332 
00333 };
00334 
00335 
00336 
00337 
00338 // MessagePartID and MessagePartIDArray are used for pipelining prefetches.
00339 
00340 class nsIMAPMessagePartID
00341 {
00342 public:
00343        nsIMAPMessagePartID(nsIMAPeFetchFields fields, const char *partNumberString);
00344        nsIMAPeFetchFields          GetFields() { return m_fields; }
00345        const char           *GetPartNumberString() { return m_partNumberString; }
00346 
00347 
00348 protected:
00349        const char *m_partNumberString;
00350        nsIMAPeFetchFields m_fields;
00351 };
00352 
00353 
00354 class nsIMAPMessagePartIDArray : public nsVoidArray {
00355 public:
00356        nsIMAPMessagePartIDArray();
00357        ~nsIMAPMessagePartIDArray();
00358 
00359        void                        RemoveAndFreeAll();
00360        int                                GetNumParts() {return Count();}
00361        nsIMAPMessagePartID  *GetPart(int i) 
00362        {
00363               NS_ASSERTION(i >= 0 && i < Count(), "invalid message part #");
00364               return (nsIMAPMessagePartID *) ElementAt(i);
00365        }
00366 };
00367 
00368 
00369 #endif // IMAPBODY_H