From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/mailnews/mime/src/mimethpl.cpp | 151 ++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 comm/mailnews/mime/src/mimethpl.cpp (limited to 'comm/mailnews/mime/src/mimethpl.cpp') diff --git a/comm/mailnews/mime/src/mimethpl.cpp b/comm/mailnews/mime/src/mimethpl.cpp new file mode 100644 index 0000000000..d21efb82bb --- /dev/null +++ b/comm/mailnews/mime/src/mimethpl.cpp @@ -0,0 +1,151 @@ +/* -*- 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/. */ + +/* TODO: + - If you Save As File .html with this mode, you get a total mess. + - Print is untested (crashes in all modes). +*/ +/* If you fix a bug here, check, if the same is also in mimethsa, because that + class is based on this class. */ + +#include "mimethpl.h" +#include "prlog.h" +#include "msgCore.h" +#include "mimemoz2.h" +#include "nsString.h" +#include "nsIDocumentEncoder.h" // for output flags + +#define MIME_SUPERCLASS mimeInlineTextPlainClass +/* I should use the Flowed class as base (because our HTML->TXT converter + can generate flowed, and we tell it to) - this would get a bit nicer + rendering. However, that class is more picky about line endings + and I currently don't feel like splitting up the generated plaintext + into separate lines again. So, I just throw the whole message at once + at the TextPlain_parse_line function - it happens to work *g*. */ +MimeDefClass(MimeInlineTextHTMLAsPlaintext, MimeInlineTextHTMLAsPlaintextClass, + mimeInlineTextHTMLAsPlaintextClass, &MIME_SUPERCLASS); + +static int MimeInlineTextHTMLAsPlaintext_parse_line(const char*, int32_t, + MimeObject*); +static int MimeInlineTextHTMLAsPlaintext_parse_begin(MimeObject* obj); +static int MimeInlineTextHTMLAsPlaintext_parse_eof(MimeObject*, bool); +static void MimeInlineTextHTMLAsPlaintext_finalize(MimeObject* obj); + +static int MimeInlineTextHTMLAsPlaintextClassInitialize( + MimeInlineTextHTMLAsPlaintextClass* clazz) { + MimeObjectClass* oclass = (MimeObjectClass*)clazz; + NS_ASSERTION(!oclass->class_initialized, "problem with superclass"); + oclass->parse_line = MimeInlineTextHTMLAsPlaintext_parse_line; + oclass->parse_begin = MimeInlineTextHTMLAsPlaintext_parse_begin; + oclass->parse_eof = MimeInlineTextHTMLAsPlaintext_parse_eof; + oclass->finalize = MimeInlineTextHTMLAsPlaintext_finalize; + + return 0; +} + +static int MimeInlineTextHTMLAsPlaintext_parse_begin(MimeObject* obj) { + MimeInlineTextHTMLAsPlaintext* textHTMLPlain = + (MimeInlineTextHTMLAsPlaintext*)obj; + textHTMLPlain->complete_buffer = new nsString(); + // Let's just hope that libmime won't have the idea to call begin twice... + return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj); +} + +static int MimeInlineTextHTMLAsPlaintext_parse_eof(MimeObject* obj, + bool abort_p) { + if (obj->closed_p) return 0; + + // This is a hack. We need to call parse_eof() of the super class to flush out + // any buffered data. We can't call it yet for our direct super class, because + // it would "close" the output (write tags such as and ). We'll + // do that after parsing the buffer. + int status = + ((MimeObjectClass*)&MIME_SUPERCLASS)->superclass->parse_eof(obj, abort_p); + if (status < 0) return status; + + MimeInlineTextHTMLAsPlaintext* textHTMLPlain = + (MimeInlineTextHTMLAsPlaintext*)obj; + + if (!textHTMLPlain || !textHTMLPlain->complete_buffer) return 0; + + nsString& cb = *(textHTMLPlain->complete_buffer); + + // could be empty, e.g., if part isn't actually being displayed + if (cb.Length()) { + nsString asPlaintext; + uint32_t flags = nsIDocumentEncoder::OutputFormatted | + nsIDocumentEncoder::OutputWrap | + nsIDocumentEncoder::OutputFormatFlowed | + nsIDocumentEncoder::OutputLFLineBreak | + nsIDocumentEncoder::OutputNoScriptContent | + nsIDocumentEncoder::OutputNoFramesContent | + nsIDocumentEncoder::OutputBodyOnly; + HTML2Plaintext(cb, asPlaintext, flags, 80); + + NS_ConvertUTF16toUTF8 resultCStr(asPlaintext); + // TODO parse each line independently + status = + ((MimeObjectClass*)&MIME_SUPERCLASS) + ->parse_line(resultCStr.BeginWriting(), resultCStr.Length(), obj); + cb.Truncate(); + } + + if (status < 0) return status; + + // Second part of the flush hack. Pretend obj wasn't closed yet, so that our + // super class gets a chance to write the closing. + bool save_closed_p = obj->closed_p; + obj->closed_p = false; + status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p); + // Restore closed_p. + obj->closed_p = save_closed_p; + return status; +} + +void MimeInlineTextHTMLAsPlaintext_finalize(MimeObject* obj) { + MimeInlineTextHTMLAsPlaintext* textHTMLPlain = + (MimeInlineTextHTMLAsPlaintext*)obj; + if (textHTMLPlain && textHTMLPlain->complete_buffer) { + // If there's content in the buffer, make sure that we output it. + // don't care about return codes + obj->clazz->parse_eof(obj, false); + + delete textHTMLPlain->complete_buffer; + textHTMLPlain->complete_buffer = NULL; + /* It is important to zero the pointer, so we can reliably check for + the validity of it in the other functions. See above. */ + } + ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(obj); +} + +static int MimeInlineTextHTMLAsPlaintext_parse_line(const char* line, + int32_t length, + MimeObject* obj) { + MimeInlineTextHTMLAsPlaintext* textHTMLPlain = + (MimeInlineTextHTMLAsPlaintext*)obj; + + if (!textHTMLPlain || !(textHTMLPlain->complete_buffer)) { +#if DEBUG + printf("Can't output: %s\n", line); +#endif + return -1; + } + + /* + To convert HTML->TXT synchronously, I need the full source at once, + not line by line (how do you convert "
  • foo\n" to plaintext?). + parse_decoded_buffer claims to give me that, but in fact also gives + me single lines. + It might be theoretically possible to drive this asynchronously, but + I don't know, which odd circumstances might arise and how libmime + will behave then. It's not worth the trouble for me to figure this all out. + */ + nsCString linestr(line, length); + NS_ConvertUTF8toUTF16 line_ucs2(linestr.get()); + if (length && line_ucs2.IsEmpty()) CopyASCIItoUTF16(linestr, line_ucs2); + (textHTMLPlain->complete_buffer)->Append(line_ucs2); + + return 0; +} -- cgit v1.2.3