1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _LIBMIME_H_
7 #define _LIBMIME_H_
8 
9 #ifdef XP_UNIX
10 #  undef Bool
11 #endif
12 
13 #include "nsString.h"
14 #include "nsMailHeaders.h"
15 #include "nsIMimeStreamConverter.h"
16 #include "mozilla/Encoding.h"
17 #include "nsIPrefBranch.h"
18 #include "mozITXTToHTMLConv.h"
19 #include "nsCOMPtr.h"
20 #include "modmimee.h"  // for MimeConverterOutputCallback
21 
22 #define MIME_DRAFTS
23 
24 /* Opaque object describing a block of message headers, and a couple of
25    routines for extracting data from one.
26  */
27 
28 typedef struct MimeHeaders {
29   char* all_headers;        /* A char* of the entire header section. */
30   int32_t all_headers_fp;   /* The length (it is not NULL-terminated.) */
31   int32_t all_headers_size; /* The size of the allocated block. */
32 
33   bool done_p; /* Whether we've read the end-of-headers marker
34                  (the terminating blank line.) */
35 
36   char** heads;       /* An array of length heads_size which points
37                         to the beginning of each distinct header:
38                         just after the newline which terminated
39                         the previous one.  This is to speed search.
40                         This is not initialized until all the
41                         headers have been read.
42                       */
43   int32_t heads_size; /* The number of entries (pointers) in the heads
44                          array (and consequently, how many
45                          distinct headers are in here.) */
46 
47   char* obuffer; /* This buffer is used for output. */
48   int32_t obuffer_size;
49   int32_t obuffer_fp;
50 
51   char* munged_subject; /* What a hack.  This is a place to write down
52                            the subject header, after it's been
53                            charset-ified and stuff.  Remembered so that
54                            we can later use it to generate the
55                            <TITLE> tag. (Also works for giving names to
56                            RFC822 attachments) */
57 } MimeHeaders;
58 
59 class MimeDisplayOptions;
60 class MimeParseStateObject;
61 typedef struct MSG_AttachmentData MSG_AttachmentData;
62 
63 /* Given the name of a header, returns the contents of that header as
64    a newly-allocated string (which the caller must free.)  If the header
65    is not present, or has no contents, NULL is returned.
66 
67    If `strip_p' is true, then the data returned will be the first token
68    of the header; else it will be the full text of the header.  (This is
69    useful for getting just "text/plain" from "text/plain; name=foo".)
70 
71    If `all_p' is false, then the first header encountered is used, and
72    any subsequent headers of the same name are ignored.  If true, then
73    all headers of the same name are appended together (this is useful
74    for gathering up all CC headers into one, for example.)
75  */
76 extern char* MimeHeaders_get(MimeHeaders* hdrs, const char* header_name,
77                              bool strip_p, bool all_p);
78 
79 // clang-format off
80 /* Given a header of the form of the MIME "Content-" headers, extracts a
81    named parameter from it, if it exists.  For example,
82    MimeHeaders_get_parameter("text/plain; charset=us-ascii", "charset")
83    would return "us-ascii".
84 
85    Returns NULL if there is no match, or if there is an allocation failure.
86 
87    RFC2231 - MIME Parameter Value and Encoded Word Extensions: Character Sets,
88    Languages, and Continuations
89 
90    RFC2231 has added the character sets, languages, and continuations mechanism.
91    charset, and language information may also be returned to the caller.
92    Note that charset and language should be free()'d while
93    the return value (parameter) has to be PR_FREE'd.
94 
95    For example,
96    MimeHeaders_get_parameter("text/plain; name*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A", "name")
97    MimeHeaders_get_parameter("text/plain; name*0*=us-ascii'en-us'This%20is%20; CRLFLWSPname*1*=%2A%2A%2Afun%2A%2A%2A", "name") would return "This is ***fun***" and *charset = "us-ascii", *language = "en-us"
98  */
99 // clang-format on
100 
101 extern char* MimeHeaders_get_parameter(const char* header_value,
102                                        const char* parm_name, char** charset,
103                                        char** language);
104 
105 extern MimeHeaders* MimeHeaders_copy(MimeHeaders* srcHeaders);
106 
107 extern void MimeHeaders_free(MimeHeaders* hdrs);
108 
109 typedef enum {
110   MimeHeadersAll,       /* Show all headers */
111   MimeHeadersSome,      /* Show all "interesting" headers */
112   MimeHeadersSomeNoRef, /* Same, but suppress the `References' header
113                           (for when we're printing this message.) */
114   MimeHeadersMicro,     /* Show a one-line header summary */
115   MimeHeadersMicroPlus, /* Same, but show the full recipient list as
116                            well (To, CC, etc.) */
117   MimeHeadersCitation,  /* A one-line summary geared toward use in a
118                            reply citation ("So-and-so wrote:") */
119   MimeHeadersOnly,      /* Just parse and output headers...nothing else! */
120   MimeHeadersNone       /* Skip showing any headers */
121 } MimeHeadersState;
122 
123 /* The signature for various callbacks in the MimeDisplayOptions structure.
124  */
125 typedef char* (*MimeHTMLGeneratorFunction)(const char* data, void* closure,
126                                            MimeHeaders* headers);
127 
128 class MimeDisplayOptions {
129  public:
130   MimeDisplayOptions();
131   virtual ~MimeDisplayOptions();
132   mozITXTToHTMLConv* conv;              // For text conversion...
133   nsCOMPtr<nsIPrefBranch> m_prefBranch; /* prefBranch-service */
134   nsMimeOutputType format_out;          // The format out type
135 
136   const char* url; /* Base URL for the document.  This string should
137             be freed by the caller, after the parser
138             completes (possibly at the same time as the
139             MimeDisplayOptions itself.) */
140 
141   MimeHeadersState headers; /* How headers should be displayed. */
142   bool fancy_headers_p;     /* Whether to do clever formatting of headers
143                                using tables, instead of spaces. */
144 
145   bool output_vcard_buttons_p; /* Whether to output the buttons */
146                                /* on vcards. */
147 
148   bool variable_width_plaintext_p; /* Whether text/plain messages should
149                                       be in variable width, or fixed. */
150   bool wrap_long_lines_p;          /* Whether to wrap long lines in text/plain
151                                       messages. */
152 
153   bool rot13_p;       /* Whether text/plain parts should be rotated
154                          Set by "?rot13=true" */
155   char* part_to_load; /* The particular part of the multipart which
156                          we are extracting.  Set by "?part=3.2.4" */
157 
158   bool no_output_p; /* Will never write output when this is true.
159                        (When false, output or not may depend on other things.)
160                        This needs to be in the options, because the method
161                        MimeObject_parse_begin is controlling the property
162                        "output_p" (on the MimeObject) so we need a way for other
163                        functions to override it and tell that we do not want
164                        output. */
165 
166   bool write_html_p; /* Whether the output should be HTML, or raw. */
167 
168   bool decrypt_p; /* Whether all traces of xlateion should be
169                      eradicated -- this is only meaningful when
170                      write_html_p is false; we set this when
171                      attaching a message for forwarding, since
172                      forwarding someone else a message that wasn't
173                      xlated for them doesn't work.  We have to
174                      dexlate it before sending it.
175                    */
176 
177   /* Whether this MIME part is a child of another part (and not top level). */
178   bool is_child = false;
179 
180   uint32_t whattodo; /* from the prefs, we'll get if the user wants to do glyph
181                         or structure substitutions and set this member variable.
182                       */
183 
184   char* default_charset;   /* If this is non-NULL, then it is the charset to
185                               assume when no other one is specified via a
186                               `charset' parameter.
187                             */
188   bool override_charset;   /* If this is true, then we will assume that
189                               all data is in the default_charset, regardless
190                               of what the `charset' parameter of that part
191                               says. (This is to cope with the fact that, in
192                               the real world, many messages are mislabelled
193                               with the wrong charset.)
194                             */
195   bool force_user_charset; /* this is the new strategy to deal with incorrectly
196                               labeled attachments */
197 
198   /* =======================================================================
199    Stream-related callbacks; for these functions, the `closure' argument
200    is what is found in `options->stream_closure'.  (One possible exception
201    is for output_fn; see "output_closure" below.)
202    */
203   void* stream_closure;
204 
205   /* For setting up the display stream, so that the MIME parser can inform
206    the caller of the type of the data it will be getting. */
207   int (*output_init_fn)(const char* type, const char* charset, const char* name,
208                         const char* x_mac_type, const char* x_mac_creator,
209                         void* stream_closure);
210 
211   /* How the MIME parser feeds its output (HTML or raw) back to the caller. */
212   MimeConverterOutputCallback output_fn;
213 
214   /* Closure to pass to the above output_fn.  If NULL, then the
215    stream_closure is used. */
216   void* output_closure;
217 
218   /* A hook for the caller to perform charset-conversion before HTML is
219    returned.  Each set of characters which originated in a mail message
220    (body or headers) will be run through this filter before being converted
221    into HTML.  (This should return bytes which may appear in an HTML file,
222    ie, we must be able to scan through the string to search for "<" and
223    turn it in to "&lt;", and so on.)
224 
225    `input' is a non-NULL-terminated string of a single line from the message.
226    `input_length' is how long it is.
227    `input_charset' is a string representing the charset of this string (as
228      specified by MIME headers.)
229    The conversion is always to UTF-8.
230    `output_ret' is where a newly-malloced string is returned.  It may be
231      NULL if no translation is needed.
232    `output_size_ret' is how long the returned string is (it need not be
233      NULL-terminated.).
234    */
235   int (*charset_conversion_fn)(const char* input_line, int32_t input_length,
236                                const char* input_charset,
237                                nsACString& output_ret, void* stream_closure);
238 
239   /* If true, perform both charset-conversion and decoding of
240    MIME-2 header fields (using RFC-1522 encoding.)
241    */
242   bool rfc1522_conversion_p;
243 
244   /* A hook for the caller to turn a file name into a content-type. */
245   char* (*file_type_fn)(const char* filename, void* stream_closure);
246 
247   /* A hook by which the user may be prompted for a password by the security
248    library.  (This is really of type `SECKEYGetPasswordKey'; see sec.h.) */
249   void* (*passwd_prompt_fn)(void* arg1, void* arg2);
250 
251   /* =======================================================================
252    Various callbacks; for all of these functions, the `closure' argument
253    is what is found in `html_closure'.
254    */
255   void* html_closure;
256 
257   /* For emitting some HTML before the start of the outermost message
258    (this is called before any HTML is written to layout.) */
259   MimeHTMLGeneratorFunction generate_header_html_fn;
260 
261   /* For emitting some HTML after the outermost header block, but before
262    the body of the first message. */
263   MimeHTMLGeneratorFunction generate_post_header_html_fn;
264 
265   /* For emitting some HTML at the very end (this is called after libmime
266    has written everything it's going to write.) */
267   MimeHTMLGeneratorFunction generate_footer_html_fn;
268 
269   /* For turning a message ID into a loadable URL. */
270   MimeHTMLGeneratorFunction generate_reference_url_fn;
271 
272   /* For turning a mail address into a mailto URL. */
273   MimeHTMLGeneratorFunction generate_mailto_url_fn;
274 
275   /* For turning a newsgroup name into a news URL. */
276   MimeHTMLGeneratorFunction generate_news_url_fn;
277 
278   /* =======================================================================
279    Callbacks to handle the backend-specific inlined image display
280    (internal-external-reconnect junk.)  For `image_begin', the `closure'
281    argument is what is found in `stream_closure'; but for all of the
282    others, the `closure' argument is the data that `image_begin' returned.
283    */
284 
285   /* Begins processing an embedded image; the URL and content_type are of the
286    image itself. */
287   void* (*image_begin)(const char* image_url, const char* content_type,
288                        void* stream_closure);
289 
290   /* Stop processing an image. */
291   void (*image_end)(void* image_closure, int status);
292 
293   /* Dump some raw image data down the stream. */
294   int (*image_write_buffer)(const char* buf, int32_t size, void* image_closure);
295 
296   /* What HTML should be dumped out for this image. */
297   char* (*make_image_html)(void* image_closure);
298 
299   /* =======================================================================
300    Other random opaque state.
301    */
302   MimeParseStateObject* state; /* Some state used by libmime internals;
303                   initialize this to 0 and leave it alone.
304                 */
305 
306 #ifdef MIME_DRAFTS
307   /* =======================================================================
308   Mail Draft hooks -- 09-19-1996
309    */
310   bool decompose_file_p;           /* are we decomposing a mime msg
311                                       into separate files */
312   bool done_parsing_outer_headers; /* are we done parsing the outer message
313                                       headers; this is really useful when
314                                       we have multiple Message/RFC822
315                                       headers */
316   bool is_multipart_msg;           /* are we decomposing a multipart
317                                       message */
318 
319   int decompose_init_count; /* used for non multipart message only */
320 
321   bool signed_p; /* to tell draft this is a signed message */
322 
323   bool caller_need_root_headers; /* set it to true to receive the message main
324                                     headers through the callback
325                                     decompose_headers_info_fn */
326 
327   /* Callback to gather the outer most headers so we could use the
328    information to initialize the addressing/subject/newsgroups fields
329    for the composition window. */
330   int (*decompose_headers_info_fn)(void* closure, MimeHeaders* headers);
331 
332   /* Callbacks to create temporary files for drafts attachments. */
333   int (*decompose_file_init_fn)(void* stream_closure, MimeHeaders* headers);
334 
335   MimeConverterOutputCallback decompose_file_output_fn;
336 
337   int (*decompose_file_close_fn)(void* stream_closure);
338 #endif /* MIME_DRAFTS */
339 
340   int32_t attachment_icon_layer_id; /* Hackhackhack.  This is zero if we have
341                                        not yet emitted the attachment layer
342                                        stuff.  If we have, then this is the
343                                        id number for that layer, which is a
344                                        unique random number every time, to keep
345                                        evil people from writing javascript code
346                                        to hack it. */
347 
348   bool missing_parts; /* Whether or not this message is going to contain
349                          missing parts (from IMAP Mime Parts On Demand) */
350 
351   bool show_attachment_inline_p; /* Whether or not we should display attachment
352                                     inline (whatever say the
353                                     content-disposition) */
354 
355   bool show_attachment_inline_text; /* Whether or not we should display text
356                                        attachment inline (whatever the
357                                        content-disposition says) */
358 
359   bool quote_attachment_inline_p; /* Whether or not we should include inlined
360                                      attachments in quotes of replies) */
361 
362   int32_t html_as_p; /* How we should display HTML, which allows us to know if
363                         we should display all body parts */
364 
365   /**
366    * Should StartBody/EndBody events be generated for nested MimeMessages.  If
367    *  false (the default value), the events are only generated for the outermost
368    *  MimeMessage.
369    */
370   bool notify_nested_bodies;
371 
372   /**
373    * When true, compels mime parts to only write the actual body
374    *  payload and not display-gunk like links to attachments. This was
375    *  primarily introduced for the benefit of the javascript emitter.
376    */
377   bool write_pure_bodies;
378 
379   /**
380    * When true, only processes metadata (i.e. size) for streamed attachments.
381    *  Mime emitters that expect any attachment data (including inline text and
382    *  image attachments) should leave this as false (the default value).  At
383    *  the moment, only the JS mime emitter uses this.
384    */
385   bool metadata_only;
386 };
387 
388 #endif /* _MODLMIME_H_ */
389