diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/mime/src/mimeleaf.cpp | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/comm/mailnews/mime/src/mimeleaf.cpp b/comm/mailnews/mime/src/mimeleaf.cpp new file mode 100644 index 0000000000..24d8c8989f --- /dev/null +++ b/comm/mailnews/mime/src/mimeleaf.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 2; 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/. */ + +#include "modmimee.h" +#include "mimeleaf.h" +#include "nsMimeTypes.h" +#include "prmem.h" +#include "plstr.h" +#include "prlog.h" +#include "nsMimeStringResources.h" +#include "modmimee.h" // for MimeConverterOutputCallback + +#define MIME_SUPERCLASS mimeObjectClass +MimeDefClass(MimeLeaf, MimeLeafClass, mimeLeafClass, &MIME_SUPERCLASS); + +static int MimeLeaf_initialize(MimeObject*); +static void MimeLeaf_finalize(MimeObject*); +static int MimeLeaf_parse_begin(MimeObject*); +static int MimeLeaf_parse_buffer(const char*, int32_t, MimeObject*); +static int MimeLeaf_parse_line(const char*, int32_t, MimeObject*); +static int MimeLeaf_close_decoder(MimeObject*); +static int MimeLeaf_parse_eof(MimeObject*, bool); +static bool MimeLeaf_displayable_inline_p(MimeObjectClass* clazz, + MimeHeaders* hdrs); + +static int MimeLeafClassInitialize(MimeLeafClass* clazz) { + MimeObjectClass* oclass = (MimeObjectClass*)clazz; + NS_ASSERTION(!oclass->class_initialized, + "1.1 <rhp@netscape.com> 19 Mar 1999 12:00"); + oclass->initialize = MimeLeaf_initialize; + oclass->finalize = MimeLeaf_finalize; + oclass->parse_begin = MimeLeaf_parse_begin; + oclass->parse_buffer = MimeLeaf_parse_buffer; + oclass->parse_line = MimeLeaf_parse_line; + oclass->parse_eof = MimeLeaf_parse_eof; + oclass->displayable_inline_p = MimeLeaf_displayable_inline_p; + clazz->close_decoder = MimeLeaf_close_decoder; + + /* Default `parse_buffer' method is one which line-buffers the now-decoded + data and passes it on to `parse_line'. (We snarf the implementation of + this method from our superclass's implementation of `parse_buffer', which + inherited it from MimeObject.) + */ + clazz->parse_decoded_buffer = + ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_buffer; + + return 0; +} + +static int MimeLeaf_initialize(MimeObject* obj) { + /* This is an abstract class; it shouldn't be directly instantiated. */ + NS_ASSERTION(obj->clazz != (MimeObjectClass*)&mimeLeafClass, + "1.1 <rhp@netscape.com> 19 Mar 1999 12:00"); + + // Initial size is -1 (meaning "unknown size") - we'll correct it in + // parse_buffer. + MimeLeaf* leaf = (MimeLeaf*)obj; + leaf->sizeSoFar = -1; + + return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj); +} + +static void MimeLeaf_finalize(MimeObject* object) { + MimeLeaf* leaf = (MimeLeaf*)object; + object->clazz->parse_eof(object, false); + + /* Free the decoder data, if it's still around. It was probably freed + in MimeLeaf_parse_eof(), but just in case... */ + if (leaf->decoder_data) { + MimeDecoderDestroy(leaf->decoder_data, true); + leaf->decoder_data = 0; + } + + ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object); +} + +static int MimeLeaf_parse_begin(MimeObject* obj) { + MimeLeaf* leaf = (MimeLeaf*)obj; + MimeDecoderData* (*fn)(MimeConverterOutputCallback, void*) = 0; + + /* Initialize a decoder if necessary. + */ + if (!obj->encoding || + // If we need the object as "raw" for saving or forwarding, + // don't decode attachment parts if headers are also written + // via the parent, so that the header matches the encoding. + (obj->options->format_out == nsMimeOutput::nsMimeMessageRaw && + obj->parent && obj->parent->output_p)) + /* no-op */; + else if (!PL_strcasecmp(obj->encoding, ENCODING_BASE64)) + fn = &MimeB64DecoderInit; + else if (!PL_strcasecmp(obj->encoding, ENCODING_QUOTED_PRINTABLE)) + leaf->decoder_data = MimeQPDecoderInit( + ((MimeConverterOutputCallback)((MimeLeafClass*)obj->clazz) + ->parse_decoded_buffer), + obj, obj); + else if (!PL_strcasecmp(obj->encoding, ENCODING_UUENCODE) || + !PL_strcasecmp(obj->encoding, ENCODING_UUENCODE2) || + !PL_strcasecmp(obj->encoding, ENCODING_UUENCODE3) || + !PL_strcasecmp(obj->encoding, ENCODING_UUENCODE4)) + fn = &MimeUUDecoderInit; + else if (!PL_strcasecmp(obj->encoding, ENCODING_YENCODE)) + fn = &MimeYDecoderInit; + + if (fn) { + leaf->decoder_data = + fn(/* The MimeConverterOutputCallback cast is to turn the `void' + argument into `MimeObject'. */ + ((MimeConverterOutputCallback)((MimeLeafClass*)obj->clazz) + ->parse_decoded_buffer), + obj); + + if (!leaf->decoder_data) return MIME_OUT_OF_MEMORY; + } + + return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj); +} + +static int MimeLeaf_parse_buffer(const char* buffer, int32_t size, + MimeObject* obj) { + MimeLeaf* leaf = (MimeLeaf*)obj; + + NS_ASSERTION(!obj->closed_p, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00"); + if (obj->closed_p) return -1; + + /* If we're not supposed to write this object, bug out now. + */ + if (!obj->output_p || !obj->options || !obj->options->output_fn) return 0; + + int rv; + if (leaf->sizeSoFar == -1) leaf->sizeSoFar = 0; + + if (leaf->decoder_data && obj->options && + obj->options->format_out != nsMimeOutput::nsMimeMessageDecrypt && + obj->options->format_out != nsMimeOutput::nsMimeMessageAttach) { + int outSize = 0; + rv = MimeDecoderWrite(leaf->decoder_data, buffer, size, &outSize); + leaf->sizeSoFar += outSize; + } else { + rv = ((MimeLeafClass*)obj->clazz)->parse_decoded_buffer(buffer, size, obj); + leaf->sizeSoFar += size; + } + return rv; +} + +static int MimeLeaf_parse_line(const char* line, int32_t length, + MimeObject* obj) { + NS_ERROR("MimeLeaf_parse_line shouldn't ever be called."); + return -1; +} + +static int MimeLeaf_close_decoder(MimeObject* obj) { + MimeLeaf* leaf = (MimeLeaf*)obj; + + if (leaf->decoder_data) { + int status = MimeDecoderDestroy(leaf->decoder_data, false); + leaf->decoder_data = 0; + return status; + } + + return 0; +} + +static int MimeLeaf_parse_eof(MimeObject* obj, bool abort_p) { + MimeLeaf* leaf = (MimeLeaf*)obj; + if (obj->closed_p) return 0; + + /* Close off the decoder, to cause it to give up any buffered data that + it is still holding. + */ + if (leaf->decoder_data) { + int status = MimeLeaf_close_decoder(obj); + if (status < 0) return status; + } + + /* Now run the superclass's parse_eof, which will force out the line + buffer (which we may have just repopulated, above.) + */ + return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p); +} + +static bool MimeLeaf_displayable_inline_p(MimeObjectClass* clazz, + MimeHeaders* hdrs) { + return true; +} |