Back to index

lightning-sunbird  0.9+nobinonly
mimethpl.cpp
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 libmime code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Ben Bucksch <http://www.bucksch.org/1/projects/mozilla/>.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
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 the GNU General Public License Version 2 or later (the "GPL"), or
00026  * 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 /* TODO:
00039   - If you Save As File .html with this mode, you get a total mess.
00040   - Print is untested (crashes in all modes).
00041 */
00042 /* If you fix a bug here, check, if the same is also in mimethsa, because that
00043    class is based on this class. */
00044 
00045 #include "mimethpl.h"
00046 #include "prlog.h"
00047 #include "msgCore.h"
00048 #include "mimemoz2.h"
00049 #include "nsString.h"
00050 #include "nsReadableUtils.h"
00051 #include "nsIDocumentEncoder.h" // for output flags
00052 
00053 #define MIME_SUPERCLASS mimeInlineTextPlainClass
00054 /* I should use the Flowed class as base (because our HTML->TXT converter
00055    can generate flowed, and we tell it to) - this would get a bit nicer
00056    rendering. However, that class is more picky about line endings
00057    and I currently don't feel like splitting up the generated plaintext
00058    into separate lines again. So, I just throw the whole message at once
00059    at the TextPlain_parse_line function - it happens to work *g*. */
00060 MimeDefClass(MimeInlineTextHTMLAsPlaintext, MimeInlineTextHTMLAsPlaintextClass,
00061                       mimeInlineTextHTMLAsPlaintextClass, &MIME_SUPERCLASS);
00062 
00063 static int MimeInlineTextHTMLAsPlaintext_parse_line (char *, PRInt32,
00064                                                      MimeObject *);
00065 static int MimeInlineTextHTMLAsPlaintext_parse_begin (MimeObject *obj);
00066 static int MimeInlineTextHTMLAsPlaintext_parse_eof (MimeObject *, PRBool);
00067 static void MimeInlineTextHTMLAsPlaintext_finalize (MimeObject *obj);
00068 
00069 static int
00070 MimeInlineTextHTMLAsPlaintextClassInitialize(MimeInlineTextHTMLAsPlaintextClass *clazz)
00071 {
00072   MimeObjectClass *oclass = (MimeObjectClass *) clazz;
00073   NS_ASSERTION(!oclass->class_initialized, "problem with superclass");
00074   oclass->parse_line  = MimeInlineTextHTMLAsPlaintext_parse_line;
00075   oclass->parse_begin = MimeInlineTextHTMLAsPlaintext_parse_begin;
00076   oclass->parse_eof   = MimeInlineTextHTMLAsPlaintext_parse_eof;
00077   oclass->finalize    = MimeInlineTextHTMLAsPlaintext_finalize;
00078 
00079   return 0;
00080 }
00081 
00082 static int
00083 MimeInlineTextHTMLAsPlaintext_parse_begin (MimeObject *obj)
00084 {
00085   MimeInlineTextHTMLAsPlaintext *textHTMLPlain =
00086                                        (MimeInlineTextHTMLAsPlaintext *) obj;
00087   textHTMLPlain->complete_buffer = new nsString();
00088      // Let's just hope that libmime won't have the idea to call begin twice...
00089   return ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
00090 }
00091 
00092 static int
00093 MimeInlineTextHTMLAsPlaintext_parse_eof (MimeObject *obj, PRBool abort_p)
00094 {
00095   if (obj->closed_p)
00096     return 0;
00097 
00098   // This is a hack. We need to call parse_eof() of the super class to flush out any buffered data.
00099   // We can't call it yet for our direct super class, because it would "close" the output 
00100   // (write tags such as </pre> and </div>). We'll do that after parsing the buffer.
00101   int status = ((MimeObjectClass*)&MIME_SUPERCLASS)->superclass->parse_eof(obj, abort_p);
00102   if (status < 0)
00103     return status;
00104   
00105   MimeInlineTextHTMLAsPlaintext *textHTMLPlain =
00106                                        (MimeInlineTextHTMLAsPlaintext *) obj;
00107 
00108   if (!textHTMLPlain || !textHTMLPlain->complete_buffer)
00109   {
00110     return 0;
00111   }
00112   nsString& cb = *(textHTMLPlain->complete_buffer);
00113   nsString asPlaintext;
00114   PRUint32 flags = nsIDocumentEncoder::OutputFormatted
00115     | nsIDocumentEncoder::OutputWrap
00116     | nsIDocumentEncoder::OutputFormatFlowed
00117     | nsIDocumentEncoder::OutputLFLineBreak
00118     | nsIDocumentEncoder::OutputNoScriptContent
00119     | nsIDocumentEncoder::OutputNoFramesContent
00120     | nsIDocumentEncoder::OutputBodyOnly;
00121   HTML2Plaintext(cb, asPlaintext, flags, 80);
00122 
00123   NS_ConvertUTF16toUTF8 resultCStr(asPlaintext);
00124   // TODO parse each line independently
00125   status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_line(
00126                              resultCStr.BeginWriting(),
00127                              resultCStr.Length(),
00128                              obj);
00129 
00130   cb.Truncate();
00131 
00132   if (status < 0)
00133     return status;
00134 
00135   // Second part of the flush hack. Pretend obj wasn't closed yet, so that our super class 
00136   // gets a chance to write the closing.
00137   PRBool save_closed_p = obj->closed_p;
00138   obj->closed_p = PR_FALSE;
00139   status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
00140   // Restore closed_p.
00141   obj->closed_p = save_closed_p;
00142   return status;
00143 }
00144 
00145 void
00146 MimeInlineTextHTMLAsPlaintext_finalize (MimeObject *obj)
00147 {
00148   MimeInlineTextHTMLAsPlaintext *textHTMLPlain =
00149                                         (MimeInlineTextHTMLAsPlaintext *) obj;
00150   if (textHTMLPlain && textHTMLPlain->complete_buffer)
00151   {
00152     // If there's content in the buffer, make sure that we output it.
00153     // don't care about return codes
00154     obj->clazz->parse_eof(obj, PR_FALSE);
00155 
00156     delete textHTMLPlain->complete_buffer;
00157     textHTMLPlain->complete_buffer = NULL;
00158       /* It is important to zero the pointer, so we can reliably check for
00159          the validity of it in the other functions. See above. */
00160   }
00161   ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize (obj);
00162 }
00163 
00164 static int
00165 MimeInlineTextHTMLAsPlaintext_parse_line (char *line, PRInt32 length,
00166                                           MimeObject *obj)
00167 {
00168   MimeInlineTextHTMLAsPlaintext *textHTMLPlain =
00169                                        (MimeInlineTextHTMLAsPlaintext *) obj;
00170 
00171   if (!textHTMLPlain || !(textHTMLPlain->complete_buffer))
00172   {
00173 #if DEBUG
00174 printf("Can't output: %s\n", line);
00175 #endif
00176     return -1;
00177   }
00178 
00179   /*
00180     To convert HTML->TXT syncronously, I need the full source at once,
00181     not line by line (how do you convert "<li>foo\n" to plaintext?).
00182     parse_decoded_buffer claims to give me that, but in fact also gives
00183     me single lines.
00184     It might be theoretically possible to drive this asyncronously, but
00185     I don't know, which odd circumstances might arise and how libmime
00186     will behave then. It's not worth the trouble for me to figure this all out.
00187    */
00188   nsCString linestr(line, length);
00189   NS_ConvertUTF8toUCS2 line_ucs2(linestr.get());
00190   if (length && line_ucs2.IsEmpty())
00191     line_ucs2.AssignWithConversion(linestr.get());
00192   (textHTMLPlain->complete_buffer)->Append(line_ucs2);
00193 
00194   return 0;
00195 }