diff options
Diffstat (limited to 'mailnews/mime/src/mimei.h')
-rw-r--r-- | mailnews/mime/src/mimei.h | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/mailnews/mime/src/mimei.h b/mailnews/mime/src/mimei.h new file mode 100644 index 000000000..a2d8332cd --- /dev/null +++ b/mailnews/mime/src/mimei.h @@ -0,0 +1,422 @@ +/* -*- 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/. */ + +#ifndef _MIMEI_H_ +#define _MIMEI_H_ + +/* + This module, libmime, implements a general-purpose MIME parser. + One of the methods provided by this parser is the ability to emit + an HTML representation of it. + + All Mozilla-specific code is (and should remain) isolated in the + file mimemoz.c. Generally, if the code involves images, netlib + streams it should be in mimemoz.c instead of in the main body of + the MIME parser. + + The parser is object-oriented and fully buzzword-compliant. + There is a class for each MIME type, and each class is responsible + for parsing itself, and/or handing the input data off to one of its + child objects. + + The class hierarchy is: + + MimeObject (abstract) + | + +--- MimeContainer (abstract) + | | + | +--- MimeMultipart (abstract) + | | | + | | +--- MimeMultipartMixed + | | | + | | +--- MimeMultipartDigest + | | | + | | +--- MimeMultipartParallel + | | | + | | +--- MimeMultipartAlternative + | | | + | | +--- MimeMultipartRelated + | | | + | | +--- MimeMultipartAppleDouble + | | | + | | +--- MimeSunAttachment + | | | + | | \--- MimeMultipartSigned (abstract) + | | | + | | \--- MimeMultipartSignedCMS + | | + | +--- MimeEncrypted (abstract) + | | | + | | \--- MimeEncryptedPKCS7 + | | + | +--- MimeXlateed (abstract) + | | | + | | \--- MimeXlateed + | | + | +--- MimeMessage + | | + | \--- MimeUntypedText + | + +--- MimeLeaf (abstract) + | | + | +--- MimeInlineText (abstract) + | | | + | | +--- MimeInlineTextPlain + | | | | + | | | \--- MimeInlineTextHTMLAsPlaintext + | | | + | | +--- MimeInlineTextPlainFlowed + | | | + | | +--- MimeInlineTextHTML + | | | | + | | | +--- MimeInlineTextHTMLParsed + | | | | + | | | \--- MimeInlineTextHTMLSanitized + | | | + | | +--- MimeInlineTextRichtext + | | | | + | | | \--- MimeInlineTextEnriched + | | | + | | +--- MimeInlineTextVCard + | | + | +--- MimeInlineImage + | | + | \--- MimeExternalObject + | + \--- MimeExternalBody + + + ========================================================================= + The definition of these classes is somewhat idiosyncratic, since I defined + my own small object system, instead of giving the C++ virus another foothold. + (I would have liked to have written this in Java, but our runtime isn't + quite ready for prime time yet.) + + There is one header file and one source file for each class (for example, + the MimeInlineText class is defined in "mimetext.h" and "mimetext.c".) + Each header file follows the following boiler-plate form: + + TYPEDEFS: these come first to avoid circular dependencies. + + typedef struct FoobarClass FoobarClass; + typedef struct Foobar Foobar; + + CLASS DECLARATION: + Theis structure defines the callback routines and other per-class data + of the class defined in this module. + + struct FoobarClass { + ParentClass superclass; + ...any callbacks or class-variables... + }; + + CLASS DEFINITION: + This variable holds an instance of the one-and-only class record; the + various instances of this class point to this object. (One interrogates + the type of an instance by comparing the value of its class pointer with + the address of this variable.) + + extern FoobarClass foobarClass; + + INSTANCE DECLARATION: + Theis structure defines the per-instance data of an object, and a pointer + to the corresponding class record. + + struct Foobar { + Parent parent; + ...any instance variables... + }; + + Then, in the corresponding .c file, the following structure is used: + + CLASS DEFINITION: + First we pull in the appropriate include file (which includes all necessary + include files for the parent classes) and then we define the class object + using the MimeDefClass macro: + + #include "foobar.h" + #define MIME_SUPERCLASS parentlClass + MimeDefClass(Foobar, FoobarClass, foobarClass, &MIME_SUPERCLASS); + + The definition of MIME_SUPERCLASS is just to move most of the knowlege of the + exact class hierarchy up to the file's header, instead of it being scattered + through the various methods; see below. + + METHOD DECLARATIONS: + We will be putting function pointers into the class object, so we declare + them here. They can generally all be static, since nobody outside of this + file needs to reference them by name; all references to these routines should + be through the class object. + + extern int FoobarMethod(Foobar *); + ...etc... + + CLASS INITIALIZATION FUNCTION: + The MimeDefClass macro expects us to define a function which will finish up + any initialization of the class object that needs to happen before the first + time it is instantiated. Its name must be of the form "<class>Initialize", + and it should initialize the various method slots in the class as + appropriate. Any methods or class variables which this class does not wish + to override will be automatically inherited from the parent class (by virtue + of its class-initialization function having been run first.) Each class + object will only be initialized once. + + static int + FoobarClassInitialize(FoobarClass *class) + { + clazz->method = FoobarMethod. + ...etc... + } + + METHOD DEFINITIONS: + Next come the definitions of the methods we referred to in the class-init + function. The way to access earlier methods (methods defined on the + superclass) is to simply extract them from the superclass's object. + But note that you CANNOT get at methods by indirecting through + object->clazz->superclass: that will only work to one level, and will + go into a loop if some subclass tries to continue on this method. + + The easiest way to do this is to make use of the MIME_SUPERCLASS macro that + was defined at the top of the file, as shown below. The alternative to that + involves typing the literal name of the direct superclass of the class + defined in this file, which will be a maintenance headache if the class + hierarchy changes. If you use the MIME_SUPERCLASS idiom, then a textual + change is required in only one place if this class's superclass changes. + + static void + Foobar_finalize (MimeObject *object) + { + ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object); // RIGHT + parentClass.whatnot.object.finalize(object); // (works...) + object->clazz->superclass->finalize(object); // WRONG!! + } + + If you write a libmime content type handler, libmime might create several + instances of your class at once and call e.g. the same finalize code for + 3 different objects in a row. + */ + +#include "mimehdrs.h" +#include "nsTArray.h" + +typedef struct MimeObject MimeObject; +typedef struct MimeObjectClass MimeObjectClass; + +#ifdef ENABLE_SMIME +class nsICMSMessage; +#endif // ENABLE_SMIME + +/* (I don't pretend to understand this.) */ +#define cpp_stringify_noop_helper(x)#x +#define cpp_stringify(x) cpp_stringify_noop_helper(x) + +#define MimeObjectClassInitializer(ITYPE,CSUPER) \ + cpp_stringify(ITYPE), \ + sizeof(ITYPE), \ + (MimeObjectClass *) CSUPER, \ + (int (*) (MimeObjectClass *)) ITYPE##ClassInitialize, \ + 0 + +/* Macro used for setting up class definitions. + */ +#define MimeDefClass(ITYPE,CTYPE,CVAR,CSUPER) \ + static int ITYPE##ClassInitialize(ITYPE##Class *); \ + ITYPE##Class CVAR = { ITYPE##ClassInitializer(ITYPE,CSUPER) } + + +/* Creates a new (subclass of) MimeObject of the given class, with the + given headers (which are copied.) + */ +extern MimeObject *mime_new (MimeObjectClass *clazz, MimeHeaders *hdrs, + const char *override_content_type); + + +/* Destroys a MimeObject (or subclass) and all data associated with it. + */ +extern "C" void mime_free (MimeObject *object); + +/* Given a content-type string, finds and returns an appropriate subclass + of MimeObject. A class object is returned. If `exact_match_p' is true, + then only fully-known types will be returned; that is, if it is true, + then "text/x-unknown" will return MimeInlineTextPlainType, but if it is + false, it will return NULL. + */ +extern MimeObjectClass *mime_find_class (const char *content_type, + MimeHeaders *hdrs, + MimeDisplayOptions *opts, + bool exact_match_p); + +/** Given a content-type string, creates and returns an appropriate subclass + * of MimeObject. The headers (from which the content-type was presumably + * extracted) are copied. forceInline is set to true when the caller wants + * the function to ignore opts->show_attachment_inline_p and force inline + * display, e.g., mimemalt wants the body part to be shown inline. + */ +extern MimeObject *mime_create (const char *content_type, MimeHeaders *hdrs, + MimeDisplayOptions *opts, bool forceInline = false); + + +/* Querying the type hierarchy */ +extern bool mime_subclass_p(MimeObjectClass *child, + MimeObjectClass *parent); +extern bool mime_typep(MimeObject *obj, MimeObjectClass *clazz); + +/* Returns a string describing the location of the part (like "2.5.3"). + This is not a full URL, just a part-number. + */ +extern char *mime_part_address(MimeObject *obj); + +/* Returns a string describing the location of the *IMAP* part (like "2.5.3"). + This is not a full URL, just a part-number. + This part is explicitly passed in the X-Mozilla-IMAP-Part header. + Return value must be freed by the caller. + */ +extern char *mime_imap_part_address(MimeObject *obj); + +extern char *mime_external_attachment_url(MimeObject *obj); + +/* Puts a part-number into a URL. If append_p is true, then the part number + is appended to any existing part-number already in that URL; otherwise, + it replaces it. + */ +extern char *mime_set_url_part(const char *url, const char *part, bool append_p); + +/* + cut the part of url for display a attachment as a email. +*/ +extern char *mime_get_base_url(const char *url); + +/* Puts an *IMAP* part-number into a URL. + */ +extern char *mime_set_url_imap_part(const char *url, const char *part, const char *libmimepart); + + +/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID + number matches, and returns the MimeObject (else NULL.) + (part is not a URL -- it's of the form "1.3.5".) + */ +extern MimeObject *mime_address_to_part(const char *part, MimeObject *obj); + + +/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID + number matches; if one is found, returns the Content-Name of that part. + Else returns NULL. (part is not a URL -- it's of the form "1.3.5".) + */ +extern char *mime_find_suggested_name_of_part(const char *part, + MimeObject *obj); + +/* Given a part ID, looks through the MimeObject tree for a sub-part whose ID + number matches; if one is found, returns the Content-Name of that part. + Else returns NULL. (part is not a URL -- it's of the form "1.3.5".) + */ +extern char *mime_find_content_type_of_part(const char *part, MimeObject *obj); + +/* Parse the various "?" options off the URL and into the options struct. + */ +extern int mime_parse_url_options(const char *url, MimeDisplayOptions *); + +#ifdef ENABLE_SMIME + +/* Asks whether the given object is one of the cryptographically signed + or encrypted objects that we know about. (MimeMessageClass uses this + to decide if the headers need to be presented differently.) + */ +extern bool mime_crypto_object_p(MimeHeaders *, bool clearsigned_counts, MimeDisplayOptions *); + +/* Tells whether the given MimeObject is a message which has been encrypted + or signed. (Helper for MIME_GetMessageCryptoState()). + */ +extern void mime_get_crypto_state (MimeObject *obj, + bool *signed_p, bool *encrypted_p, + bool *signed_ok, bool *encrypted_ok); + + +/* Whether the given object has written out the HTML version of its headers + in such a way that it will have a "crypto stamp" next to the headers. If + this is true, then the child must write out its HTML slightly differently + to take this into account... + */ +extern bool mime_crypto_stamped_p(MimeObject *obj); + +/* How the crypto code tells the MimeMessage object what the crypto stamp + on it says. */ +extern void mime_set_crypto_stamp(MimeObject *obj, + bool signed_p, bool encrypted_p); +#endif // ENABLE_SMIME + +class MimeParseStateObject { +public: + + MimeParseStateObject() + {root = 0; separator_queued_p = false; separator_suppressed_p = false; + first_part_written_p = false; post_header_html_run_p = false; first_data_written_p = false; + decrypted_p = false; strippingPart = false; + } + MimeObject *root; /* The outermost parser object. */ + + bool separator_queued_p; /* Whether a separator should be written out + before the next text is written (this lets + us write separators lazily, so that one + doesn't appear at the end, and so that more + than one don't appear in a row.) */ + + bool separator_suppressed_p; /* Whether the currently-queued separator + should not be printed; this is a kludge to + prevent seps from being printed just after + a header block... */ + + bool first_part_written_p; /* State used for the `Show Attachments As + Links' kludge. */ + + bool post_header_html_run_p; /* Whether we've run the + options->generate_post_header_html_fn */ + + bool first_data_written_p; /* State used for Mozilla lazy-stream- + creation evilness. */ + + bool decrypted_p; /* If options->dexlate_p is true, then this + will be set to indicate whether any + dexlateion did in fact occur. + */ + nsTArray<nsCString> partsToStrip; /* if we're stripping parts, what parts to strip */ + nsTArray<nsCString> detachToFiles; /* if we're detaching parts, where each part was detached to */ + bool strippingPart; + nsCString detachedFilePath; /* if we've detached this part, filepath of detached part */ +}; + + +/* Some output-generation utility functions... + */ +extern int MimeObject_output_init(MimeObject *obj, const char *content_type); + +/* The `user_visible_p' argument says whether the output that has just been + written will cause characters or images to show up on the screen, that + is, it should be false if the stuff being written is merely structural + HTML or whitespace ("<P>", "</TABLE>", etc.) This information is used + when making the decision of whether a separating <HR> is needed. + */ +extern int MimeObject_write(MimeObject *, const char *data, int32_t length, + bool user_visible_p); +extern int MimeOptions_write(MimeHeaders *, + MimeDisplayOptions *, + const char *data, int32_t length, + bool user_visible_p); + +/* Writes out the right kind of HR (or rather, queues it for writing.) */ +extern int MimeObject_write_separator(MimeObject *); + +extern bool MimeObjectIsMessageBody(MimeObject *obj); + +struct MimeDisplayData { /* This struct is what we hang off of + (context)->mime_data, to remember info + about the last MIME object we've + parsed and displayed. See + MimeGuessURLContentName() below. + */ + MimeObject *last_parsed_object; + char *last_parsed_url; +}; + +#endif /* _MIMEI_H_ */ |