Back to index

lightning-sunbird  0.9+nobinonly
mimedrft.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK *****
00038  * This Original Code has been modified by IBM Corporation. Modifications made by IBM 
00039  * described herein are Copyright (c) International Business Machines Corporation, 2000.
00040  * Modifications to Mozilla code or documentation identified per MPL Section 3.3
00041  *
00042  * Date             Modified by     Description of modification
00043  * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
00044  */
00045 #include "nsCOMPtr.h"
00046 #include "modmimee.h"
00047 #include "mimeobj.h"
00048 #include "modlmime.h"
00049 #include "mimei.h"
00050 #include "mimebuf.h"
00051 #include "mimemoz2.h"
00052 #include "mimemsg.h"
00053 #include "nsMimeTypes.h"
00054 
00055 #include "prmem.h"
00056 #include "plstr.h"
00057 #include "prprf.h"
00058 #include "prio.h"
00059 #include "nsIPrefService.h"
00060 #include "nsIPrefBranch.h"
00061 #include "msgCore.h"
00062 #include "nsCRT.h"
00063 #include "nsEscape.h"
00064 #include "nsIFileSpec.h"
00065 #include "nsIMsgSend.h"
00066 #include "nsFileStream.h"
00067 #include "nsMimeStringResources.h"
00068 #include "nsIIOService.h"
00069 #include "nsNetUtil.h"
00070 #include "comi18n.h"
00071 #include "nsIMsgCompFields.h"
00072 #include "nsMsgCompCID.h"
00073 #include "nsIMsgComposeService.h"
00074 #include "nsMsgI18N.h"
00075 #include "nsNativeCharsetUtils.h"
00076 #include "nsSpecialSystemDirectory.h"
00077 #include "nsIMsgMessageService.h"
00078 #include "nsMsgUtils.h"
00079 #include "nsXPIDLString.h"
00080 #include "nsReadableUtils.h"
00081 #include "nsCExternalHandlerService.h"
00082 #include "nsIMIMEService.h"
00083 #include "nsIMsgHeaderParser.h"
00084 #include "nsIMsgAccountManager.h"
00085 #include "nsMsgBaseCID.h"
00086 
00087 //
00088 // Header strings...
00089 //
00090 #define HEADER_NNTP_POSTING_HOST      "NNTP-Posting-Host"
00091 #define MIME_HEADER_TABLE             "<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0 class=\"moz-email-headers-table\">"
00092 #define HEADER_START_JUNK             "<TR><TH VALIGN=BASELINE ALIGN=RIGHT NOWRAP>"
00093 #define HEADER_MIDDLE_JUNK            ": </TH><TD>"
00094 #define HEADER_END_JUNK               "</TD></TR>"
00095 
00096 //
00097 // Forward declarations...
00098 //
00099 extern "C" char     *MIME_StripContinuations(char *original);
00100 nsresult            mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers );
00101 nsresult            mime_decompose_file_output_fn ( const char *buf, PRInt32 size, void *stream_closure );
00102 nsresult            mime_decompose_file_close_fn ( void *stream_closure );
00103 extern int          MimeHeaders_build_heads_list(MimeHeaders *hdrs);
00104 
00105 // CID's
00106 static NS_DEFINE_CID(kCMsgComposeServiceCID,  NS_MSGCOMPOSESERVICE_CID);       
00107 
00110 // THIS SHOULD ALL MOVE TO ANOTHER FILE AFTER LANDING!
00113 
00114 // safe filename for all OSes
00115 #define SAFE_TMP_FILENAME "nsmime.tmp"
00116 
00117 //
00118 // Create a file spec for the a unique temp file
00119 // on the local machine. Caller must free memory
00120 //
00121 nsFileSpec * 
00122 nsMsgCreateTempFileSpec(const char *tFileName)
00123 {
00124   //Calling NS_MsgHashIfNecessary so that when Replies are forwarded - the ':' in the subject line doesn't cause problems
00125   nsFileSpec *tmpSpec = new nsFileSpec(nsSpecialSystemDirectory(nsSpecialSystemDirectory::OS_TemporaryDirectory));
00126   NS_ASSERTION(tmpSpec, "out of memory");
00127   if (!tmpSpec)
00128     return nsnull;
00129 
00130   nsresult rv = NS_OK;
00131   nsCAutoString tempName;
00132   if ((!tFileName) || (!*tFileName)) {
00133     tempName = SAFE_TMP_FILENAME;
00134   }
00135   else {
00136     nsAutoString tempNameUni; 
00137     if (NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(tFileName),
00138                                          tempNameUni))) {
00139       tempName = SAFE_TMP_FILENAME;
00140       goto fallback;
00141     }
00142 
00143     PRInt32 dotChar = tempNameUni.RFindChar('.');
00144     if (dotChar == kNotFound) {
00145        rv = NS_MsgHashIfNecessary(tempNameUni);
00146     }
00147     else {
00148       // this scary code will not lose any 3 or 4 character normal extensions, 
00149       // like foo.eml, foo.txt, foo.html
00150       // this code is to turn arbitrary attachment file names to ones 
00151       // that are safe for the underlying OS 
00152       // eventually, this code will go away once bug #86089 is fixed
00153       nsAutoString extension;
00154       tempNameUni.Right(extension, tempNameUni.Length() - dotChar - 1);
00155       tempNameUni.Truncate(dotChar);
00156       rv = NS_MsgHashIfNecessary(tempNameUni);
00157       if (NS_SUCCEEDED(rv)) {
00158         rv = NS_MsgHashIfNecessary(extension);    // should be a NOOP for normal 3 or 4 char extension
00159         if (NS_SUCCEEDED(rv)) {
00160           tempNameUni += '.';
00161           tempNameUni += extension;
00162           // hash the combinded string, so that filenames like "<giant string>.<giant string>" are made safe
00163           rv = NS_MsgHashIfNecessary(tempNameUni);   
00164         }
00165       }
00166     } 
00167     rv = NS_CopyUnicodeToNative(tempNameUni, tempName);
00168     NS_ASSERTION(NS_SUCCEEDED(rv), "UTF-16 to native filename failed"); 
00169   }
00170 
00171 fallback:
00172   NS_ASSERTION(NS_SUCCEEDED(rv), "hash failed");
00173   if (NS_FAILED(rv)) {
00174     tempName = SAFE_TMP_FILENAME;
00175   }
00176   // we are guaranteed that tempName is safe for the underlying OS
00177   *tmpSpec += tempName.get();
00178 
00179   tmpSpec->MakeUnique();
00180   return tmpSpec;
00181 }
00182 
00185 // END OF - THIS SHOULD ALL MOVE TO ANOTHER FILE AFTER LANDING!
00188 
00189 typedef enum {
00190   nsMsg_RETURN_RECEIPT_BOOL_HEADER_MASK = 0,
00191   nsMsg_ENCRYPTED_BOOL_HEADER_MASK,
00192   nsMsg_SIGNED_BOOL_HEADER_MASK,
00193   nsMsg_UUENCODE_BINARY_BOOL_HEADER_MASK,
00194   nsMsg_ATTACH_VCARD_BOOL_HEADER_MASK,
00195   nsMsg_LAST_BOOL_HEADER_MASK     // last boolean header mask; must be the last one 
00196                                   // DON'T remove.
00197 } nsMsgBoolHeaderSet;
00198 
00199 #ifdef NS_DEBUG
00200 extern "C" void
00201 mime_dump_attachments ( nsMsgAttachmentData *attachData )
00202 {
00203   PRInt32     i = 0;
00204   struct nsMsgAttachmentData  *tmp = attachData;
00205 
00206   while ( (tmp) && (tmp->real_name) )
00207   {
00208     printf("Real Name         : %s\n", tmp->real_name);
00209 
00210     if ( tmp->url ) 
00211     {
00212       nsCAutoString spec;
00213       tmp->url->GetSpec(spec);
00214       printf("URL               : %s\n", spec.get());
00215     }
00216 
00217     printf("Desired Type      : %s\n", tmp->desired_type ? tmp->desired_type : "nsnull");
00218     printf("Real Type         : %s\n", tmp->real_type ? tmp->real_type : "nsnull");
00219     printf("Real Encoding     : %s\n", tmp->real_encoding ? tmp->real_encoding : "nsnull"); 
00220     printf("Description       : %s\n", tmp->description) ? tmp->description : "nsnull";
00221     printf("Mac Type          : %s\n", tmp->x_mac_type ? tmp->x_mac_type : "nsnull");
00222     printf("Mac Creator       : %s\n", tmp->x_mac_creator ? tmp->x_mac_creator : "nsnull");
00223     i++;
00224     tmp++;
00225   }
00226 }
00227 #endif
00228 
00229 nsresult
00230 CreateTheComposeWindow(nsIMsgCompFields *   compFields,
00231                        nsMsgAttachmentData *attachmentList,
00232                        MSG_ComposeType      composeType,
00233                        MSG_ComposeFormat    composeFormat,
00234                        nsIMsgIdentity *     identity,
00235                        const char *         originalMsgURI
00236                        )
00237 {
00238   nsresult            rv;
00239   MSG_ComposeFormat   format = nsIMsgCompFormat::Default;
00240 
00241 #ifdef NS_DEBUG
00242   mime_dump_attachments ( attachmentList );
00243 #endif
00244 
00245   nsMsgAttachmentData *curAttachment = attachmentList;
00246   if (curAttachment)
00247   {
00248     nsCAutoString spec;
00249 
00250     while (curAttachment && curAttachment->real_name) //JFD: Why do we check for real_name?
00251     {
00252       rv = curAttachment->url->GetSpec(spec);
00253       if (NS_SUCCEEDED(rv))
00254       {
00255         nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
00256         if (NS_SUCCEEDED(rv) && attachment)
00257         {
00258           nsAutoString nameStr;
00259           rv = ConvertToUnicode("UTF-8", curAttachment->real_name, nameStr);
00260           if (NS_FAILED(rv))
00261             CopyASCIItoUTF16(curAttachment->real_name, nameStr);
00262           attachment->SetName(nameStr);
00263           attachment->SetUrl(spec.get());
00264           attachment->SetTemporary(PR_TRUE);
00265           attachment->SetContentType(curAttachment->real_type);
00266           attachment->SetMacType(curAttachment->x_mac_type);
00267           attachment->SetMacCreator(curAttachment->x_mac_creator);
00268           compFields->AddAttachment(attachment);
00269         }
00270       }
00271       curAttachment++;
00272     }
00273   }
00274 
00275   nsCOMPtr<nsIMsgComposeService> msgComposeService = 
00276            do_GetService(kCMsgComposeServiceCID, &rv);
00277   if ((NS_FAILED(rv)) || (!msgComposeService))
00278     return rv; 
00279   
00280   if (identity && composeType == nsIMsgCompType::ForwardInline)
00281   {
00282     PRBool composeHtml = PR_FALSE;
00283     identity->GetComposeHtml(&composeHtml);
00284     if (composeHtml)
00285       format = nsIMsgCompFormat::HTML;
00286     else
00287     {
00288       format = nsIMsgCompFormat::PlainText;
00289       /* do we we need to convert the HTML body to plain text? */
00290       if (composeFormat == nsIMsgCompFormat::HTML)
00291         compFields->ConvertBodyToPlainText();
00292     }
00293   }
00294   else
00295     format = composeFormat;
00296   
00297   nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
00298   if (NS_SUCCEEDED(rv) && pMsgComposeParams)
00299   {
00300     pMsgComposeParams->SetType(composeType);
00301     pMsgComposeParams->SetFormat(format);
00302     pMsgComposeParams->SetIdentity(identity);
00303     pMsgComposeParams->SetComposeFields(compFields);
00304     if (originalMsgURI)
00305       pMsgComposeParams->SetOriginalMsgURI(originalMsgURI);
00306     
00307     rv = msgComposeService->OpenComposeWindowWithParams(nsnull /* default chrome */, pMsgComposeParams);
00308   }
00309   return rv;
00310 }
00311 
00312 nsresult
00313 CreateCompositionFields(const char        *from,
00314                         const char        *reply_to,
00315                         const char        *to,
00316                         const char        *cc,
00317                         const char        *bcc,
00318                         const char        *fcc,
00319                         const char        *newsgroups,
00320                         const char        *followup_to,
00321                         const char        *organization,
00322                         const char        *subject,
00323                         const char        *references,
00324                         const char        *other_random_headers,
00325                         const char        *priority,
00326                         const char        *newspost_url,
00327                         PRBool            xlate_p,
00328                         PRBool            sign_p,
00329                         char              *charset,
00330                         nsIMsgCompFields  **_retval)
00331 {
00332   NS_ENSURE_ARG_POINTER(_retval);
00333   
00334   nsresult rv;
00335   *_retval = nsnull;
00336   
00337   nsCOMPtr<nsIMsgCompFields> cFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv);
00338   NS_ENSURE_SUCCESS(rv, rv);
00339   NS_ENSURE_TRUE(cFields, NS_ERROR_OUT_OF_MEMORY);
00340   
00341   // Now set all of the passed in stuff...
00342   cFields->SetCharacterSet(!nsCRT::strcasecmp("us-ascii", charset) ? "ISO-8859-1" : charset);
00343   
00344   char *val;
00345   
00346   if (from) {
00347     val = MIME_DecodeMimeHeader(from, charset, PR_FALSE, PR_TRUE);
00348     cFields->SetFrom(NS_ConvertUTF8toUTF16(val ? val : from));
00349     PR_FREEIF(val);
00350   }
00351   
00352   if (subject) {
00353     val = MIME_DecodeMimeHeader(subject, charset, PR_FALSE, PR_TRUE);
00354     cFields->SetSubject(NS_ConvertUTF8toUTF16(val ? val : subject));
00355     PR_FREEIF(val);
00356   }
00357   
00358   if (reply_to) {
00359     val = MIME_DecodeMimeHeader(reply_to, charset, PR_FALSE, PR_TRUE);
00360     cFields->SetReplyTo(NS_ConvertUTF8toUTF16(val ? val : reply_to));
00361     PR_FREEIF(val);
00362   }
00363   
00364   if (to) {
00365     val = MIME_DecodeMimeHeader(to, charset, PR_FALSE, PR_TRUE);
00366     cFields->SetTo(NS_ConvertUTF8toUTF16(val ? val : to));
00367     PR_FREEIF(val);
00368   }
00369   
00370   if (cc) {
00371     val = MIME_DecodeMimeHeader(cc, charset, PR_FALSE, PR_TRUE);
00372     cFields->SetCc(NS_ConvertUTF8toUTF16(val ? val : cc));
00373     PR_FREEIF(val);
00374   }
00375   
00376   if (bcc) {
00377     val = MIME_DecodeMimeHeader(bcc, charset, PR_FALSE, PR_TRUE);
00378     cFields->SetBcc(NS_ConvertUTF8toUTF16(val ? val : bcc));
00379     PR_FREEIF(val);
00380   }
00381   
00382   if (fcc) {
00383     val = MIME_DecodeMimeHeader(fcc, charset, PR_FALSE, PR_TRUE);
00384     cFields->SetFcc(NS_ConvertUTF8toUTF16(val ? val : fcc));
00385     PR_FREEIF(val);
00386   }
00387   
00388   if (newsgroups) {
00389     // fixme: the newsgroups header had better be decoded using the server-side
00390     // character encoding,but this |charset| might be different from it.
00391     val = MIME_DecodeMimeHeader(newsgroups, charset, PR_FALSE, PR_TRUE);
00392     cFields->SetNewsgroups(NS_ConvertUTF8toUTF16(val ? val : newsgroups));
00393     PR_FREEIF(val);
00394   }
00395   
00396   if (followup_to) {
00397     val = MIME_DecodeMimeHeader(followup_to, charset, PR_FALSE, PR_TRUE);
00398     cFields->SetFollowupTo(val ? val : followup_to);
00399     PR_FREEIF(val);
00400   }
00401   
00402   if (organization) {
00403     val = MIME_DecodeMimeHeader(organization, charset, PR_FALSE, PR_TRUE);
00404     cFields->SetOrganization(NS_ConvertUTF8toUTF16(val ? val : organization));
00405     PR_FREEIF(val);
00406   }
00407   
00408   if (references) {
00409     val = MIME_DecodeMimeHeader(references, charset, PR_FALSE, PR_TRUE);
00410     cFields->SetReferences(val ? val : references);
00411     PR_FREEIF(val);
00412   }
00413   
00414   if (other_random_headers) {
00415     val = MIME_DecodeMimeHeader(other_random_headers, charset, PR_FALSE, PR_TRUE);
00416     cFields->SetOtherRandomHeaders(NS_ConvertUTF8toUTF16(val ? val : other_random_headers));
00417     PR_FREEIF(val);
00418   }
00419   
00420   if (priority) {
00421     val = MIME_DecodeMimeHeader(priority, charset, PR_FALSE, PR_TRUE);
00422     nsMsgPriorityValue priorityValue;
00423     NS_MsgGetPriorityFromString(val ? val : priority, priorityValue);
00424     PR_FREEIF(val);
00425     nsCAutoString priorityName;
00426     NS_MsgGetUntranslatedPriorityName(priorityValue, priorityName);
00427     cFields->SetPriority(priorityName.get());
00428   }
00429   
00430   if (newspost_url) {
00431     val = MIME_DecodeMimeHeader(newspost_url, charset, PR_FALSE, PR_TRUE);
00432     cFields->SetNewspostUrl(val ? val : newspost_url);
00433     PR_FREEIF(val);
00434   }
00435   
00436   *_retval = cFields;
00437   NS_IF_ADDREF(*_retval);
00438   
00439   return rv;
00440 }
00441 
00442 // RICHIE:
00443 // Not sure what this preference is in the new world.
00444 PRBool
00445 GetMailXlateionPreference(void)
00446 {
00447   nsresult res;
00448   PRBool   xlate = PR_FALSE;
00449 
00450   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
00451   if(NS_SUCCEEDED(res))
00452     prefBranch->GetBoolPref("mail.unknown", &xlate);
00453 
00454   return xlate;
00455 }
00456 
00457 // RICHIE:
00458 // Not sure what this preference is in the new world.
00459 PRBool
00460 GetMailSigningPreference(void)
00461 {
00462   nsresult  res;
00463   PRBool    signit = PR_FALSE;
00464 
00465   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
00466   if(NS_SUCCEEDED(res))
00467     prefBranch->GetBoolPref("mail.unknown", &signit);
00468 
00469   return signit;
00470 }
00471   
00472 static int
00473 dummy_file_write( char *buf, PRInt32 size, void *fileHandle )
00474 {
00475   if (!fileHandle)
00476     return NS_ERROR_FAILURE;
00477 
00478   nsOutputFileStream  *tStream = (nsOutputFileStream *) fileHandle;
00479   return tStream->write(buf, size);
00480 }
00481 
00482 static int PR_CALLBACK
00483 mime_parse_stream_write ( nsMIMESession *stream, const char *buf, PRInt32 size )
00484 {
00485   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;  
00486   NS_ASSERTION ( mdd, "null mime draft data!" );
00487 
00488   if ( !mdd || !mdd->obj ) 
00489     return -1;
00490 
00491   return mdd->obj->clazz->parse_buffer ((char *) buf, size, mdd->obj);
00492 }
00493 
00494 static void
00495 mime_free_attach_data ( nsMsgAttachmentData *attachData)
00496 {
00497   struct nsMsgAttachmentData  *tmp = attachData;
00498 
00499   while (tmp && tmp->real_name) 
00500   {
00501     if (tmp->url)
00502     {
00503       delete tmp->url;
00504       tmp->url = nsnull;
00505     }
00506     PR_FREEIF(tmp->real_name);
00507 
00508     PR_FREEIF(tmp->desired_type);
00509     PR_FREEIF(tmp->real_type);
00510     PR_FREEIF(tmp->real_encoding); 
00511     PR_FREEIF(tmp->description);
00512     PR_FREEIF(tmp->x_mac_type);
00513     PR_FREEIF(tmp->x_mac_creator);
00514 
00515     tmp++;
00516   }
00517 }
00518 
00519 static void
00520 mime_free_attachments ( nsMsgAttachedFile *attachments, int count )
00521 {
00522   int               i;
00523   nsMsgAttachedFile *cur = attachments;
00524 
00525   NS_ASSERTION ( attachments && count > 0, "freeing attachments but there aren't any");
00526   if ( !attachments || count <= 0 ) 
00527     return;
00528 
00529   for ( i = 0; i < count; i++, cur++ ) 
00530   {
00531     cur->orig_url=nsnull;
00532 
00533     PR_FREEIF ( cur->type );
00534     PR_FREEIF ( cur->encoding );
00535     PR_FREEIF ( cur->description );
00536     PR_FREEIF ( cur->x_mac_type );
00537     PR_FREEIF ( cur->x_mac_creator );
00538     if ( cur->file_spec ) 
00539     {
00540       cur->file_spec->Delete(PR_FALSE);
00541       delete ( cur->file_spec );
00542     }
00543   }
00544 
00545   PR_FREEIF( attachments );
00546 }
00547 
00548 static nsMsgAttachmentData *
00549 mime_draft_process_attachments(mime_draft_data *mdd) 
00550 {
00551   if (!mdd)
00552     return nsnull;
00553 
00554   nsMsgAttachmentData         *attachData = NULL, *tmp = NULL;
00555   nsMsgAttachedFile           *tmpFile = NULL;
00556   int                         i;
00557 
00558   //It's possible we must treat the message body as attachment!
00559   PRBool bodyAsAttachment = PR_FALSE;
00560   if (  mdd->messageBody &&
00561         mdd->messageBody->type && *mdd->messageBody->type &&
00562         ( PL_strcasestr(mdd->messageBody->type, "text/html") == nsnull ) &&
00563         ( PL_strcasestr(mdd->messageBody->type, "text/plain") == nsnull ) &&
00564         ( PL_strcasecmp(mdd->messageBody->type, "text") != 0 )
00565      )
00566      bodyAsAttachment = PR_TRUE;
00567 
00568   if ( (!mdd->attachments || !mdd->attachments_count) && !bodyAsAttachment)
00569     return nsnull;
00570 
00571   PRInt32 totalCount = mdd->attachments_count;
00572   if (bodyAsAttachment)
00573     totalCount ++;
00574   attachData = (nsMsgAttachmentData *) PR_CALLOC( ( (totalCount + 1) * sizeof (nsMsgAttachmentData) ) );
00575   if ( !attachData ) 
00576     return nsnull;
00577 
00578   //mdd->messageBody and mdd->attachments are the same type!
00579   if (bodyAsAttachment)
00580     tmpFile = mdd->messageBody;
00581   else
00582     tmpFile = mdd->attachments;
00583   tmp = attachData;
00584 
00585   for ( i=0; i < totalCount; i++, tmp++) 
00586   {
00587     if (tmpFile->type) 
00588     {
00589       if (nsCRT::strcasecmp ( tmpFile->type, "text/x-vcard") == 0)
00590         NS_MsgSACopy (&(tmp->real_name), tmpFile->description);
00591     }
00592 
00593     if ( tmpFile->orig_url ) 
00594     {
00595       nsCAutoString tmpSpec;
00596       if (NS_FAILED(tmpFile->orig_url->GetSpec(tmpSpec)))
00597         goto FAIL;
00598 
00599       if (NS_FAILED(nsMimeNewURI(&(tmp->url), tmpSpec.get(), nsnull)))
00600       {
00601         goto FAIL; 
00602       }
00603 
00604       NS_ADDREF(tmp->url);
00605       if (!tmp->real_name)
00606       {
00607         if (tmpFile->real_name)
00608           NS_MsgSACopy ( &(tmp->real_name), tmpFile->real_name );
00609         else {
00610           if (PL_strstr(tmpFile->type, MESSAGE_RFC822))
00611             // we have the odd case of processing an e-mail that had an unnamed
00612             // eml message attached
00613             NS_MsgSACopy( &(tmp->real_name), "ForwardedMessage.eml" );
00614 
00615           else
00616             NS_MsgSACopy ( &(tmp->real_name), tmpSpec.get() );
00617         }
00618       }
00619     }
00620 
00621     if ( tmpFile->type ) 
00622     {
00623       NS_MsgSACopy ( &(tmp->desired_type), tmpFile->type );
00624       NS_MsgSACopy ( &(tmp->real_type), tmpFile->type );
00625     }
00626 
00627     if ( tmpFile->encoding ) 
00628     {
00629       NS_MsgSACopy ( &(tmp->real_encoding), tmpFile->encoding );
00630     }
00631 
00632     if ( tmpFile->description ) 
00633     {
00634       NS_MsgSACopy ( &(tmp->description), tmpFile->description );
00635     }
00636 
00637     if ( tmpFile->x_mac_type ) 
00638     {
00639       NS_MsgSACopy ( &(tmp->x_mac_type), tmpFile->x_mac_type );
00640     }
00641 
00642     if ( tmpFile->x_mac_creator ) 
00643     {
00644       NS_MsgSACopy ( &(tmp->x_mac_creator), tmpFile->x_mac_creator );
00645     }
00646 
00647     if (bodyAsAttachment && (i == 0))
00648       tmpFile = mdd->attachments;
00649     else
00650       tmpFile++;
00651   }
00652 
00653   return (attachData);
00654 
00655 FAIL:
00656   mime_free_attach_data (attachData);
00657   PR_FREEIF(attachData);
00658   return nsnull;
00659 }
00660 
00661 static void 
00662 mime_fix_up_html_address( char **addr)
00663 {
00664   //
00665   // We need to replace paired <> they are treated as HTML tag 
00666   //
00667   if (addr && *addr && PL_strchr(*addr, '<') && PL_strchr(*addr, '>'))
00668   {
00669     char *lt = NULL;
00670     PRInt32 newLen = 0;
00671     do 
00672     {
00673       newLen = strlen(*addr) + 3 + 1;
00674       *addr = (char *) PR_REALLOC(*addr, newLen);
00675       NS_ASSERTION (*addr, "out of memory fixing up html address");
00676       lt = PL_strchr(*addr, '<');
00677       NS_ASSERTION(lt, "couldn't find < char in address");
00678       memmove(lt+4, lt+1, newLen - 4 - (lt - *addr));
00679       *lt++ = '&';
00680       *lt++ = 'l';
00681       *lt++ = 't';
00682       *lt = ';';
00683     } while (PL_strchr(*addr, '<'));
00684   }
00685 }
00686 
00687 static void 
00688 mime_intl_insert_message_header_1(char        **body, 
00689                                   char        **hdr_value,
00690                                   char        *hdr_str, 
00691                                   const char  *html_hdr_str,
00692                                   char        *mailcharset,
00693                                   PRBool      htmlEdit)
00694 {
00695   if (!body || !hdr_value || !hdr_str)
00696     return;
00697 
00698   if (htmlEdit)
00699   {
00700     NS_MsgSACat(body, HEADER_START_JUNK);
00701   }
00702   else
00703   {
00704     NS_MsgSACat(body, MSG_LINEBREAK);
00705   }
00706   if (!html_hdr_str)
00707     html_hdr_str = hdr_str;
00708   NS_MsgSACat(body, html_hdr_str);
00709   if (htmlEdit)
00710   {
00711     NS_MsgSACat(body, HEADER_MIDDLE_JUNK);
00712   }
00713   else
00714     NS_MsgSACat(body, ": ");
00715 
00716     // MIME decode header
00717     char* utf8 = MIME_DecodeMimeHeader(*hdr_value, mailcharset, PR_FALSE,
00718                                        PR_TRUE);
00719     if (NULL != utf8) {
00720         NS_MsgSACat(body, utf8);
00721         PR_Free(utf8);
00722     } else {
00723         NS_MsgSACat(body, *hdr_value); // raw MIME encoded string
00724     }
00725 
00726   if (htmlEdit)
00727     NS_MsgSACat(body, HEADER_END_JUNK);
00728 }
00729 
00730 char *
00731 MimeGetNamedString(PRInt32 id)
00732 {
00733   static char   retString[256];
00734 
00735   retString[0] = '\0';
00736   char *tString = MimeGetStringByID(id);
00737   if (tString)
00738   {
00739     PL_strncpy(retString, tString, sizeof(retString)); 
00740     PR_Free(tString);
00741   }
00742   return retString;
00743 }
00744 
00745 /* given an address string passed though parameter "address", this one will be converted
00746    and returned through the same parameter. The original string will be destroyed
00747 */
00748 static void UnquoteMimeAddress(nsIMsgHeaderParser* parser, char** address)
00749 {
00750   if (parser && address && *address && **address)
00751   {
00752     char *result;
00753     if (NS_SUCCEEDED(parser->UnquotePhraseOrAddr(*address, PR_FALSE, &result)))
00754     {
00755       if (result && *result)
00756       {
00757         PR_Free(*address);
00758         *address = result;
00759         return;
00760       }
00761       PR_FREEIF(result);
00762     }
00763   }
00764 
00765   return;
00766 }
00767 
00768 static void 
00769 mime_insert_all_headers(char            **body,
00770                         MimeHeaders     *headers,
00771                         MSG_ComposeFormat composeFormat,
00772                         char            *mailcharset)
00773 {
00774   nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
00775 
00776   PRBool htmlEdit = (composeFormat == nsIMsgCompFormat::HTML);
00777   char *newBody = NULL;
00778   char *html_tag = nsnull;
00779   if (*body)
00780     html_tag = PL_strcasestr(*body, "<HTML>");
00781   int i;
00782 
00783   if (!headers->done_p)
00784   {
00785     MimeHeaders_build_heads_list(headers);
00786     headers->done_p = PR_TRUE;
00787   }
00788 
00789   if (htmlEdit)
00790   {
00791     NS_MsgSACopy(&(newBody), "<HTML><BODY><BR><BR>");
00792 
00793     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
00794     NS_MsgSACat(&newBody, MIME_HEADER_TABLE);
00795   }
00796   else
00797   {
00798     NS_MsgSACopy(&(newBody), MSG_LINEBREAK MSG_LINEBREAK);
00799     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
00800   }
00801 
00802   for (i = 0; i < headers->heads_size; i++)
00803   {
00804     char *head = headers->heads[i];
00805     char *end = (i == headers->heads_size-1
00806            ? headers->all_headers + headers->all_headers_fp
00807            : headers->heads[i+1]);
00808     char *colon, *ocolon;
00809     char *contents;
00810     char *name = 0;
00811     char *c2 = 0;
00812 
00813     // Hack for BSD Mailbox delimiter. 
00814     if (i == 0 && head[0] == 'F' && !strncmp(head, "From ", 5))
00815     {
00816       colon = head + 4;
00817       contents = colon + 1;
00818     }
00819     else
00820     {
00821       /* Find the colon. */
00822       for (colon = head; colon < end; colon++)
00823       if (*colon == ':') break;
00824 
00825       if (colon >= end) continue;   /* junk */
00826 
00827       /* Back up over whitespace before the colon. */
00828       ocolon = colon;
00829       for (; colon > head && nsCRT::IsAsciiSpace(colon[-1]); colon--)
00830       ;
00831 
00832       contents = ocolon + 1;
00833     }
00834 
00835     /* Skip over whitespace after colon. */
00836     while (contents <= end && nsCRT::IsAsciiSpace(*contents))
00837     contents++;
00838 
00839     /* Take off trailing whitespace... */
00840     while (end > contents && nsCRT::IsAsciiSpace(end[-1]))
00841     end--;
00842 
00843     name = (char *)PR_MALLOC(colon - head + 1);
00844     if (!name) 
00845       return /* MIME_OUT_OF_MEMORY */;
00846     memcpy(name, head, colon - head);
00847     name[colon - head] = 0;
00848 
00849     c2 = (char *)PR_MALLOC(end - contents + 1);
00850     if (!c2)
00851     {
00852       PR_Free(name);
00853       return /* MIME_OUT_OF_MEMORY */;
00854     }
00855     memcpy(c2, contents, end - contents);
00856     c2[end - contents] = 0;
00857     
00858     /* Do not reveal bcc recipients when forwarding a message!
00859        See http://bugzilla.mozilla.org/show_bug.cgi?id=41150
00860     */
00861     if (nsCRT::strcasecmp(name, "bcc") != 0)
00862     {
00863       if (htmlEdit)
00864         mime_fix_up_html_address(&c2);
00865         
00866       if (!nsCRT::strcasecmp(name, "resent-from") || !nsCRT::strcasecmp(name, "from") ||
00867           !nsCRT::strcasecmp(name, "resent-to") || !nsCRT::strcasecmp(name, "to") ||
00868           !nsCRT::strcasecmp(name, "resent-cc") || !nsCRT::strcasecmp(name, "cc") ||
00869           !nsCRT::strcasecmp(name, "reply-to"))
00870         UnquoteMimeAddress(parser, &c2);
00871 
00872       mime_intl_insert_message_header_1(&newBody, &c2, name, name, mailcharset, htmlEdit);
00873     }
00874     PR_Free(name);
00875     PR_Free(c2);
00876   }
00877 
00878   if (htmlEdit)
00879   {
00880     NS_MsgSACat(&newBody, "</TABLE>");
00881     NS_MsgSACat(&newBody, MSG_LINEBREAK "<BR><BR>");
00882     if (html_tag)
00883       NS_MsgSACat(&newBody, html_tag+6);
00884     else if (*body)
00885         NS_MsgSACat(&newBody, *body);
00886   }
00887   else
00888   {
00889     NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
00890     if (*body)
00891       NS_MsgSACat(&newBody, *body);
00892   }
00893 
00894   if (newBody)
00895   {
00896     PR_FREEIF(*body);
00897     *body = newBody;
00898   }
00899 }
00900 
00901 static void 
00902 mime_insert_normal_headers(char             **body,
00903                            MimeHeaders      *headers,
00904                            MSG_ComposeFormat  composeFormat,
00905                            char             *mailcharset)
00906 {
00907   char *newBody = nsnull;
00908   char *subject = MimeHeaders_get(headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
00909   char *resent_comments = MimeHeaders_get(headers, HEADER_RESENT_COMMENTS, PR_FALSE, PR_FALSE);
00910   char *resent_date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE); 
00911   char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE, PR_TRUE);
00912   char *resent_to = MimeHeaders_get(headers, HEADER_RESENT_TO, PR_FALSE, PR_TRUE);
00913   char *resent_cc = MimeHeaders_get(headers, HEADER_RESENT_CC, PR_FALSE, PR_TRUE);
00914   char *date = MimeHeaders_get(headers, HEADER_DATE, PR_FALSE, PR_TRUE);
00915   char *from = MimeHeaders_get(headers, HEADER_FROM, PR_FALSE, PR_TRUE);
00916   char *reply_to = MimeHeaders_get(headers, HEADER_REPLY_TO, PR_FALSE, PR_TRUE);
00917   char *organization = MimeHeaders_get(headers, HEADER_ORGANIZATION, PR_FALSE, PR_FALSE);
00918   char *to = MimeHeaders_get(headers, HEADER_TO, PR_FALSE, PR_TRUE);
00919   char *cc = MimeHeaders_get(headers, HEADER_CC, PR_FALSE, PR_TRUE);
00920   char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE, PR_TRUE);
00921   char *followup_to = MimeHeaders_get(headers, HEADER_FOLLOWUP_TO, PR_FALSE, PR_TRUE);
00922   char *references = MimeHeaders_get(headers, HEADER_REFERENCES, PR_FALSE, PR_TRUE);
00923   const char *html_tag = nsnull;
00924   if (*body)
00925     html_tag = PL_strcasestr(*body, "<HTML>");
00926   PRBool htmlEdit = composeFormat == nsIMsgCompFormat::HTML;
00927   
00928   if (!from)
00929     from = MimeHeaders_get(headers, HEADER_SENDER, PR_FALSE, PR_TRUE);
00930   if (!resent_from)
00931     resent_from = MimeHeaders_get(headers, HEADER_RESENT_SENDER, PR_FALSE,
00932                     PR_TRUE); 
00933   
00934   nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
00935   UnquoteMimeAddress(parser, &resent_from);
00936   UnquoteMimeAddress(parser, &resent_to);
00937   UnquoteMimeAddress(parser, &resent_cc);
00938   UnquoteMimeAddress(parser, &reply_to);
00939   UnquoteMimeAddress(parser, &from);
00940   UnquoteMimeAddress(parser, &to);
00941   UnquoteMimeAddress(parser, &cc);
00942 
00943   if (htmlEdit)
00944   {
00945     NS_MsgSACopy(&(newBody), "<HTML><BODY><BR><BR>");
00946     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
00947     NS_MsgSACat(&newBody, MIME_HEADER_TABLE);
00948   }
00949   else
00950   {
00951     NS_MsgSACopy(&(newBody), MSG_LINEBREAK MSG_LINEBREAK);
00952     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
00953   }
00954   if (subject)
00955     mime_intl_insert_message_header_1(&newBody, &subject, HEADER_SUBJECT,
00956                       MimeGetNamedString(MIME_MHTML_SUBJECT),
00957                       mailcharset, htmlEdit);
00958   if (resent_comments)
00959     mime_intl_insert_message_header_1(&newBody, &resent_comments,
00960                       HEADER_RESENT_COMMENTS, 
00961                       MimeGetNamedString(MIME_MHTML_RESENT_COMMENTS),
00962                       mailcharset, htmlEdit);
00963   if (resent_date)
00964     mime_intl_insert_message_header_1(&newBody, &resent_date,
00965                       HEADER_RESENT_DATE,
00966                       MimeGetNamedString(MIME_MHTML_RESENT_DATE),
00967                       mailcharset, htmlEdit);
00968   if (resent_from)
00969   {
00970     if (htmlEdit) mime_fix_up_html_address(&resent_from);
00971     mime_intl_insert_message_header_1(&newBody, &resent_from,
00972                       HEADER_RESENT_FROM,
00973                       MimeGetNamedString(MIME_MHTML_RESENT_FROM),
00974                       mailcharset, htmlEdit);
00975   }
00976   if (resent_to)
00977   {
00978     if (htmlEdit) mime_fix_up_html_address(&resent_to);
00979     mime_intl_insert_message_header_1(&newBody, &resent_to,
00980                       HEADER_RESENT_TO,
00981                       MimeGetNamedString(MIME_MHTML_RESENT_TO),
00982                       mailcharset, htmlEdit);
00983   }
00984   if (resent_cc)
00985   {
00986     if (htmlEdit) mime_fix_up_html_address(&resent_cc);
00987     mime_intl_insert_message_header_1(&newBody, &resent_cc,
00988                       HEADER_RESENT_CC,
00989                       MimeGetNamedString(MIME_MHTML_RESENT_CC),
00990                       mailcharset, htmlEdit);
00991   }
00992   if (date)
00993     mime_intl_insert_message_header_1(&newBody, &date, HEADER_DATE,
00994                       MimeGetNamedString(MIME_MHTML_DATE),
00995                       mailcharset, htmlEdit);
00996   if (from)
00997   {
00998     if (htmlEdit) mime_fix_up_html_address(&from);
00999     mime_intl_insert_message_header_1(&newBody, &from, HEADER_FROM,
01000                       MimeGetNamedString(MIME_MHTML_FROM),
01001                       mailcharset, htmlEdit);
01002   }
01003   if (reply_to)
01004   {
01005     if (htmlEdit) mime_fix_up_html_address(&reply_to);
01006     mime_intl_insert_message_header_1(&newBody, &reply_to, HEADER_REPLY_TO,
01007                       MimeGetNamedString(MIME_MHTML_REPLY_TO),
01008                       mailcharset, htmlEdit);
01009   }
01010   if (organization)
01011     mime_intl_insert_message_header_1(&newBody, &organization,
01012                       HEADER_ORGANIZATION,
01013                       MimeGetNamedString(MIME_MHTML_ORGANIZATION),
01014                       mailcharset, htmlEdit);
01015   if (to)
01016   {
01017     if (htmlEdit) mime_fix_up_html_address(&to);
01018     mime_intl_insert_message_header_1(&newBody, &to, HEADER_TO,
01019                       MimeGetNamedString(MIME_MHTML_TO),
01020                       mailcharset, htmlEdit);
01021   }
01022   if (cc)
01023   {
01024     if (htmlEdit) mime_fix_up_html_address(&cc);
01025     mime_intl_insert_message_header_1(&newBody, &cc, HEADER_CC,
01026                       MimeGetNamedString(MIME_MHTML_CC),
01027                       mailcharset, htmlEdit);
01028   }
01029     /*
01030       Do not reveal bcc recipients when forwarding a message!
01031       See http://bugzilla.mozilla.org/show_bug.cgi?id=41150
01032     */
01033     if (newsgroups)
01034     mime_intl_insert_message_header_1(&newBody, &newsgroups, HEADER_NEWSGROUPS,
01035                       MimeGetNamedString(MIME_MHTML_NEWSGROUPS),
01036                       mailcharset, htmlEdit);
01037   if (followup_to)
01038   {
01039     if (htmlEdit) mime_fix_up_html_address(&followup_to);
01040     mime_intl_insert_message_header_1(&newBody, &followup_to,
01041                       HEADER_FOLLOWUP_TO,
01042                       MimeGetNamedString(MIME_MHTML_FOLLOWUP_TO),
01043                       mailcharset, htmlEdit);
01044   }
01045   if (references)
01046   {
01047     if (htmlEdit) mime_fix_up_html_address(&references);
01048     mime_intl_insert_message_header_1(&newBody, &references,
01049                       HEADER_REFERENCES,
01050                       MimeGetNamedString(MIME_MHTML_REFERENCES),
01051                       mailcharset, htmlEdit);
01052   }
01053   if (htmlEdit)
01054   {
01055     NS_MsgSACat(&newBody, "</TABLE>");
01056     NS_MsgSACat(&newBody, MSG_LINEBREAK "<BR><BR>");
01057     if (html_tag)
01058       NS_MsgSACat(&newBody, html_tag+6);
01059     else if (*body)
01060         NS_MsgSACat(&newBody, *body);
01061   }
01062   else
01063   {
01064     NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
01065     if (*body)
01066       NS_MsgSACat(&newBody, *body);
01067   }
01068   if (newBody)
01069   {
01070     PR_FREEIF(*body);
01071     *body = newBody;
01072   }
01073   PR_FREEIF(subject);
01074   PR_FREEIF(resent_comments);
01075   PR_FREEIF(resent_date);
01076   PR_FREEIF(resent_from);
01077   PR_FREEIF(resent_to);
01078   PR_FREEIF(resent_cc);
01079   PR_FREEIF(date);
01080   PR_FREEIF(from);
01081   PR_FREEIF(reply_to);
01082   PR_FREEIF(organization);
01083   PR_FREEIF(to);
01084   PR_FREEIF(cc);
01085   PR_FREEIF(newsgroups);
01086   PR_FREEIF(followup_to);
01087   PR_FREEIF(references);
01088 }
01089 
01090 static void 
01091 mime_insert_micro_headers(char            **body,
01092                           MimeHeaders     *headers,
01093                           MSG_ComposeFormat composeFormat,
01094                           char            *mailcharset)
01095 {
01096   char *newBody = NULL;
01097   char *subject = MimeHeaders_get(headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
01098   char *from = MimeHeaders_get(headers, HEADER_FROM, PR_FALSE, PR_TRUE);
01099   char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE,
01100                     PR_TRUE); 
01101   char *date = MimeHeaders_get(headers, HEADER_DATE, PR_FALSE, PR_TRUE);
01102   char *to = MimeHeaders_get(headers, HEADER_TO, PR_FALSE, PR_TRUE);
01103   char *cc = MimeHeaders_get(headers, HEADER_CC, PR_FALSE, PR_TRUE);
01104   char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE,
01105                      PR_TRUE);
01106   const char *html_tag = nsnull;
01107   if (*body)
01108     html_tag = PL_strcasestr(*body, "<HTML>");
01109   PRBool htmlEdit = composeFormat == nsIMsgCompFormat::HTML;
01110   
01111   if (!from)
01112     from = MimeHeaders_get(headers, HEADER_SENDER, PR_FALSE, PR_TRUE);
01113   if (!resent_from)
01114     resent_from = MimeHeaders_get(headers, HEADER_RESENT_SENDER, PR_FALSE,
01115                     PR_TRUE); 
01116   if (!date)
01117     date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE);
01118   
01119   nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
01120   UnquoteMimeAddress(parser, &resent_from);
01121   UnquoteMimeAddress(parser, &from);
01122   UnquoteMimeAddress(parser, &to);
01123   UnquoteMimeAddress(parser, &cc);
01124 
01125   if (htmlEdit)
01126   {
01127     NS_MsgSACopy(&(newBody), "<HTML><BODY><BR><BR>");
01128     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
01129     NS_MsgSACat(&newBody, MIME_HEADER_TABLE);
01130   }
01131   else
01132   {
01133     NS_MsgSACopy(&(newBody), MSG_LINEBREAK MSG_LINEBREAK);
01134     NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
01135   }
01136 
01137   if (from)
01138   {
01139     if (htmlEdit) 
01140       mime_fix_up_html_address(&from);
01141     mime_intl_insert_message_header_1(&newBody, &from, HEADER_FROM,
01142                     MimeGetNamedString(MIME_MHTML_FROM),
01143                     mailcharset, htmlEdit);
01144   }
01145   if (subject)
01146     mime_intl_insert_message_header_1(&newBody, &subject, HEADER_SUBJECT,
01147                     MimeGetNamedString(MIME_MHTML_SUBJECT),
01148                       mailcharset, htmlEdit);
01149 /*
01150   if (date)
01151     mime_intl_insert_message_header_1(&newBody, &date, HEADER_DATE,
01152                     MimeGetNamedString(MIME_MHTML_DATE),
01153                     mailcharset, htmlEdit);
01154 */
01155   if (resent_from)
01156   {
01157     if (htmlEdit) mime_fix_up_html_address(&resent_from);
01158     mime_intl_insert_message_header_1(&newBody, &resent_from,
01159                     HEADER_RESENT_FROM,
01160                     MimeGetNamedString(MIME_MHTML_RESENT_FROM),
01161                     mailcharset, htmlEdit);
01162   }
01163   if (to)
01164   {
01165     if (htmlEdit) mime_fix_up_html_address(&to);
01166     mime_intl_insert_message_header_1(&newBody, &to, HEADER_TO,
01167                     MimeGetNamedString(MIME_MHTML_TO),
01168                     mailcharset, htmlEdit);
01169   }
01170   if (cc)
01171   {
01172     if (htmlEdit) mime_fix_up_html_address(&cc);
01173     mime_intl_insert_message_header_1(&newBody, &cc, HEADER_CC,
01174                     MimeGetNamedString(MIME_MHTML_CC),
01175                     mailcharset, htmlEdit);
01176   }
01177   /*
01178     Do not reveal bcc recipients when forwarding a message!
01179     See http://bugzilla.mozilla.org/show_bug.cgi?id=41150
01180   */
01181   if (newsgroups)
01182     mime_intl_insert_message_header_1(&newBody, &newsgroups, HEADER_NEWSGROUPS,
01183                     MimeGetNamedString(MIME_MHTML_NEWSGROUPS),
01184                     mailcharset, htmlEdit);
01185   if (htmlEdit)
01186   {
01187     NS_MsgSACat(&newBody, "</TABLE>");
01188     NS_MsgSACat(&newBody, MSG_LINEBREAK "<BR><BR>");
01189     if (html_tag)
01190       NS_MsgSACat(&newBody, html_tag+6);
01191     else if (*body)
01192         NS_MsgSACat(&newBody, *body);
01193   }
01194   else
01195   {
01196     NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
01197     if (*body)
01198       NS_MsgSACat(&newBody, *body);
01199   }
01200   if (newBody)
01201   {
01202     PR_FREEIF(*body);
01203     *body = newBody;
01204   }
01205   PR_FREEIF(subject);
01206   PR_FREEIF(from);
01207   PR_FREEIF(resent_from);
01208   PR_FREEIF(date);
01209   PR_FREEIF(to);
01210   PR_FREEIF(cc);
01211   PR_FREEIF(newsgroups);
01212 
01213 }
01214 
01215 // body has to be encoded in UTF-8
01216 static void 
01217 mime_insert_forwarded_message_headers(char            **body, 
01218                                       MimeHeaders     *headers,
01219                                       MSG_ComposeFormat composeFormat,
01220                                       char            *mailcharset)
01221 {
01222   if (!body || !headers)
01223     return;
01224 
01225   PRInt32     show_headers = 0;
01226   nsresult    res;
01227 
01228   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
01229   if (NS_SUCCEEDED(res))
01230     prefBranch->GetIntPref("mail.show_headers", &show_headers);
01231 
01232   switch (show_headers)
01233   {
01234   case 0:
01235     mime_insert_micro_headers(body, headers, composeFormat, mailcharset);
01236     break;
01237   default:
01238   case 1:
01239     mime_insert_normal_headers(body, headers, composeFormat, mailcharset);
01240     break;
01241   case 2:
01242     mime_insert_all_headers(body, headers, composeFormat, mailcharset);
01243     break;
01244   }
01245 }
01246 
01247 static void PR_CALLBACK
01248 mime_parse_stream_complete (nsMIMESession *stream)
01249 {
01250   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
01251   nsCOMPtr<nsIMsgCompFields> fields;
01252   int htmlAction = 0;
01253   int lineWidth = 0;
01254   
01255   char *host = 0;
01256   char *news_host = 0;
01257   char *to_and_cc = 0;
01258   char *re_subject = 0;
01259   char *new_refs = 0;
01260   char *from = 0;
01261   char *repl = 0;
01262   char *subj = 0;
01263   char *id = 0;
01264   char *refs = 0;
01265   char *to = 0;
01266   char *cc = 0;
01267   char *bcc = 0; 
01268   char *fcc = 0; 
01269   char *org = 0; 
01270   char *grps = 0;
01271   char *foll = 0;
01272   char *priority = 0;
01273   char *draftInfo = 0;
01274   char *identityKey = 0;
01275   
01276   PRBool xlate_p = PR_FALSE;  /* #### how do we determine this? */
01277   PRBool sign_p = PR_FALSE;   /* #### how do we determine this? */
01278   PRBool forward_inline = PR_FALSE;
01279   PRBool bodyAsAttachment = PR_FALSE;
01280   PRBool charsetOverride = PR_FALSE;
01281   
01282   NS_ASSERTION (mdd, "null mime draft data");
01283   
01284   if (!mdd) return;
01285   
01286   if (mdd->obj) 
01287   {
01288     int status;
01289     
01290     status = mdd->obj->clazz->parse_eof ( mdd->obj, PR_FALSE );
01291     mdd->obj->clazz->parse_end( mdd->obj, status < 0 ? PR_TRUE : PR_FALSE );
01292     
01293     xlate_p = mdd->options->decrypt_p;
01294     sign_p = mdd->options->signed_p;
01295     
01296     // RICHIE
01297     // We need to figure out how to pass the forwarded flag along with this
01298     // operation.
01299     
01300     //forward_inline = (mdd->format_out != FO_CMDLINE_ATTACHMENTS);    
01301     forward_inline = mdd->forwardInline;
01302     if (forward_inline)
01303     {
01304 #ifdef MOZ_SECURITY
01305       HG88890
01306 #endif
01307     }
01308     
01309     NS_ASSERTION ( mdd->options == mdd->obj->options, "mime draft options not same as obj->options" );
01310     mime_free (mdd->obj);
01311     mdd->obj = 0;
01312     if (mdd->options) 
01313     {
01314       // save the override flag before it's unavailable
01315       charsetOverride = mdd->options->override_charset;
01316       if ((!mdd->mailcharset || charsetOverride) && mdd->options->default_charset) 
01317       {
01318         PR_Free(mdd->mailcharset);
01319         mdd->mailcharset = nsCRT::strdup(mdd->options->default_charset);
01320       }
01321 
01322       // mscott: aren't we leaking a bunch of strings here like the charset strings and such?
01323       delete mdd->options;
01324       mdd->options = 0;
01325     }
01326     if (mdd->stream) 
01327     {
01328       mdd->stream->complete ((nsMIMESession *)mdd->stream->data_object);
01329       PR_Free( mdd->stream );
01330       mdd->stream = 0;
01331     }
01332   }
01333   
01334   //
01335   // Now, process the attachments that we have gathered from the message
01336   // on disk
01337   //
01338   nsMsgAttachmentData *newAttachData = mime_draft_process_attachments(mdd);
01339   
01340   //
01341   // time to bring up the compose windows with all the info gathered 
01342   //
01343   if ( mdd->headers )
01344   {
01345     subj = MimeHeaders_get(mdd->headers, HEADER_SUBJECT,  PR_FALSE, PR_FALSE);
01346     if (forward_inline)
01347     {
01348       if (subj)
01349       {
01350         char *newSubj = PR_smprintf("[Fwd: %s]", subj);
01351         if (newSubj)
01352         {
01353           PR_Free(subj);
01354           subj = newSubj;
01355         }
01356       }
01357     } 
01358     else
01359     {
01360       repl = MimeHeaders_get(mdd->headers, HEADER_REPLY_TO, PR_FALSE, PR_FALSE);
01361       to   = MimeHeaders_get(mdd->headers, HEADER_TO,       PR_FALSE, PR_TRUE);
01362       cc   = MimeHeaders_get(mdd->headers, HEADER_CC,       PR_FALSE, PR_TRUE);
01363       bcc   = MimeHeaders_get(mdd->headers, HEADER_BCC,       PR_FALSE, PR_TRUE);
01364       
01365       /* These headers should not be RFC-1522-decoded. */
01366       grps = MimeHeaders_get(mdd->headers, HEADER_NEWSGROUPS,  PR_FALSE, PR_TRUE);
01367       foll = MimeHeaders_get(mdd->headers, HEADER_FOLLOWUP_TO, PR_FALSE, PR_TRUE);
01368       
01369       host = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_NEWSHOST, PR_FALSE, PR_FALSE);
01370       if (!host)
01371         host = MimeHeaders_get(mdd->headers, HEADER_NNTP_POSTING_HOST, PR_FALSE, PR_FALSE);
01372       
01373       id   = MimeHeaders_get(mdd->headers, HEADER_MESSAGE_ID,  PR_FALSE, PR_FALSE);
01374       refs = MimeHeaders_get(mdd->headers, HEADER_REFERENCES,  PR_FALSE, PR_TRUE);
01375       priority = MimeHeaders_get(mdd->headers, HEADER_X_PRIORITY, PR_FALSE, PR_FALSE);
01376       
01377       
01378       if (host) 
01379       {
01380         char *secure = NULL;
01381         
01382         secure = PL_strcasestr(host, "secure");
01383         if (secure) 
01384         {
01385           *secure = 0;
01386           news_host = PR_smprintf ("snews://%s", host);
01387         }
01388         else 
01389         {
01390           news_host = PR_smprintf ("news://%s", host);
01391         }
01392       }
01393     }
01394     
01395     
01396     CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
01397       org, subj, refs, 0, priority, news_host,
01398       xlate_p, sign_p, mdd->mailcharset,
01399       getter_AddRefs(fields));
01400     
01401     draftInfo = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_DRAFT_INFO, PR_FALSE, PR_FALSE);
01402     if (draftInfo && fields && !forward_inline) 
01403     {
01404       char *parm = 0;
01405       parm = MimeHeaders_get_parameter(draftInfo, "vcard", NULL, NULL);
01406       fields->SetAttachVCard(parm && !nsCRT::strcmp(parm, "1"));
01407    
01408       fields->SetMessageId(id); // keep same message id for editing template.
01409       PR_FREEIF(parm);
01410       parm = MimeHeaders_get_parameter(draftInfo, "receipt", NULL, NULL);
01411       if (parm && !nsCRT::strcmp(parm, "0"))
01412         fields->SetReturnReceipt(PR_FALSE); 
01413       else
01414       {
01415         int receiptType = 0;
01416         fields->SetReturnReceipt(PR_TRUE); 
01417         sscanf(parm, "%d", &receiptType);
01418         // slight change compared to 4.x; we used to use receipt= to tell
01419         // whether the draft/template has request for either MDN or DNS or both
01420         // return receipt; since the DNS is out of the picture we now use the
01421         // header type - 1 to tell whether user has requested the return receipt
01422         fields->SetReceiptHeaderType(((PRInt32)receiptType) - 1);
01423       }
01424       PR_FREEIF(parm);
01425       parm = MimeHeaders_get_parameter(draftInfo, "uuencode", NULL, NULL);
01426       fields->SetUuEncodeAttachments(parm && !nsCRT::strcmp(parm, "1"));
01427       PR_FREEIF(parm);
01428       parm = MimeHeaders_get_parameter(draftInfo, "html", NULL, NULL);
01429       if (parm)
01430         sscanf(parm, "%d", &htmlAction);
01431       PR_FREEIF(parm);
01432       parm = MimeHeaders_get_parameter(draftInfo, "linewidth", NULL, NULL);
01433       if (parm)
01434         sscanf(parm, "%d", &lineWidth);
01435       PR_FREEIF(parm);
01436       
01437     }
01438     
01439        // identity to prefer when opening the message in the compose window?
01440     identityKey = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_IDENTITY_KEY, PR_FALSE, PR_FALSE);
01441     if ( identityKey && *identityKey )
01442     {
01443         nsresult rv = NS_OK;
01444         nsCOMPtr< nsIMsgAccountManager > accountManager = 
01445                 do_GetService( NS_MSGACCOUNTMANAGER_CONTRACTID, &rv );
01446         if ( NS_SUCCEEDED(rv) && accountManager )
01447         {
01448             nsCOMPtr< nsIMsgIdentity > overrulingIdentity;
01449             rv = accountManager->GetIdentity( identityKey, getter_AddRefs( overrulingIdentity ) );
01450 
01451             if ( NS_SUCCEEDED(rv) && overrulingIdentity )
01452                 mdd->identity = overrulingIdentity;
01453         }
01454     }
01455 
01456     if (mdd->messageBody) 
01457     {
01458       MSG_ComposeFormat composeFormat = nsIMsgCompFormat::Default;
01459       if (mdd->messageBody->type && *mdd->messageBody->type)
01460       {
01461         if( PL_strcasestr(mdd->messageBody->type, "text/html"))
01462           composeFormat = nsIMsgCompFormat::HTML;
01463         else if ( PL_strcasestr(mdd->messageBody->type, "text/plain") ||
01464                   !PL_strcasecmp(mdd->messageBody->type, "text") )
01465           composeFormat = nsIMsgCompFormat::PlainText;
01466         else
01467         {
01468           //We cannot use this kind of data for the message body! Therefore, move it as attachment
01469           bodyAsAttachment = PR_TRUE;
01470         }
01471       }
01472       else
01473         composeFormat = nsIMsgCompFormat::PlainText;
01474 
01475       char *body = nsnull;
01476       PRUint32 bodyLen = 0;
01477       
01478       if (!bodyAsAttachment)
01479       {
01480         bodyLen = mdd->messageBody->file_spec->GetFileSize();
01481         body = (char *)PR_MALLOC (bodyLen + 1);
01482         if (body)
01483         {
01484           memset (body, 0, bodyLen+1);
01485         
01486           nsInputFileStream inputFile(*(mdd->messageBody->file_spec));
01487           if (inputFile.is_open())
01488             inputFile.read(body, bodyLen);
01489         
01490           inputFile.close();
01491 
01492           // Convert the body to UTF-8
01493           char *mimeCharset = nsnull;
01494           // Get a charset from the header if no override is set.
01495           if (!charsetOverride)
01496             mimeCharset = MimeHeaders_get_parameter (mdd->messageBody->type, "charset", nsnull, nsnull);
01497           // If no charset is specified in the header then use the default.
01498           char *bodyCharset = mimeCharset ? mimeCharset : mdd->mailcharset;
01499           if (bodyCharset)
01500           {
01501             nsAutoString tempUnicodeString;
01502             if (NS_SUCCEEDED(ConvertToUnicode(bodyCharset, body, tempUnicodeString)))
01503             {
01504               char *newBody = ToNewUTF8String(tempUnicodeString);
01505               if (newBody) 
01506               {
01507                 PR_Free(body);
01508                 body = newBody;
01509                 bodyLen = strlen(newBody);
01510               }
01511             }
01512           }
01513           PR_FREEIF(mimeCharset);
01514         }
01515       }
01516 
01517       // Since we have body text, then we should set the compose fields with
01518       // this data.      
01519       //       if (composeFormat == nsIMsgCompFormat::PlainText)
01520       //         fields->SetTheForcePlainText(PR_TRUE);
01521       
01522       if (forward_inline)
01523       {
01524         if (mdd->identity)
01525         {
01526           PRBool bFormat;
01527           mdd->identity->GetComposeHtml(&bFormat);
01528           if (bFormat)
01529           {
01530             if (body && composeFormat == nsIMsgCompFormat::PlainText)
01531             {
01532               //We need to convert the plain/text to HTML in order to escape any HTML markup
01533               char *escapedBody = nsEscapeHTML(body);
01534               if (escapedBody)
01535               {
01536                 PR_Free(body);
01537                 body = escapedBody;
01538                 bodyLen = strlen(body);
01539               }
01540 
01541               PRUint32 newbodylen = bodyLen + 12; //+11 chars for <pre> & </pre> tags
01542               char* newbody = (char *)PR_MALLOC (newbodylen);
01543               if (newbody)
01544               {
01545                 *newbody = 0;
01546                 PL_strcatn(newbody, newbodylen, "<PRE>");
01547                 PL_strcatn(newbody, newbodylen, body);
01548                 PL_strcatn(newbody, newbodylen, "</PRE>");
01549                 PR_Free(body);
01550                 body = newbody;
01551               }
01552             }
01553             composeFormat = nsIMsgCompFormat::HTML;
01554           }
01555         }
01556         
01557         mime_insert_forwarded_message_headers(&body, mdd->headers, composeFormat,
01558           mdd->mailcharset);
01559       }
01560       // setting the charset while we are creating the composition fields
01561       //fields->SetCharacterSet(NS_ConvertASCIItoUCS2(mdd->mailcharset));
01562 
01563       // convert from UTF-8 to UTF-16
01564       if (body)
01565       {
01566         fields->SetBody(NS_ConvertUTF8toUTF16(body));
01567         PR_Free(body);
01568       }
01569 
01570       //
01571       // At this point, we need to create a message compose window or editor
01572       // window via XP-COM with the information that we have retrieved from 
01573       // the message store.
01574       //
01575       if (mdd->format_out == nsMimeOutput::nsMimeMessageEditorTemplate)
01576       {
01577         fields->SetDraftId(mdd->url_name);
01578         CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Template, composeFormat, mdd->identity, mdd->originalMsgURI);
01579       }
01580       else
01581       {
01582         if (mdd->forwardInline)
01583           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, composeFormat, mdd->identity, mdd->originalMsgURI);
01584           else
01585         {
01586           fields->SetDraftId(mdd->url_name);
01587           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, composeFormat, mdd->identity, mdd->originalMsgURI);
01588         }
01589       }
01590     }
01591     else
01592     {
01593       //
01594       // At this point, we need to create a message compose window via
01595       // XP-COM with the information that we have retrieved from the message store.
01596       //
01597       if (mdd->format_out == nsMimeOutput::nsMimeMessageEditorTemplate)
01598       {
01599 #ifdef NS_DEBUG
01600         printf("RICHIE: Time to create the EDITOR with this template - NO body!!!!\n");
01601 #endif
01602         CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Template, nsIMsgCompFormat::Default, mdd->identity, nsnull);
01603       }
01604       else
01605       {
01606 #ifdef NS_DEBUG
01607         printf("Time to create the composition window WITHOUT a body!!!!\n");
01608 #endif
01609         if (mdd->forwardInline)
01610           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, nsIMsgCompFormat::Default, mdd->identity, mdd->originalMsgURI);
01611         else
01612         {
01613           fields->SetDraftId(mdd->url_name);
01614           CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, nsIMsgCompFormat::Default, mdd->identity, nsnull);
01615         }
01616       }
01617     }    
01618   }
01619   else
01620   {
01621     CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
01622       org, subj, refs, 0, priority, news_host,
01623       GetMailXlateionPreference(), 
01624       GetMailSigningPreference(),
01625       mdd->mailcharset,
01626       getter_AddRefs(fields));
01627     if (fields)
01628       CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::New, nsIMsgCompFormat::Default, mdd->identity, nsnull);
01629   }
01630   
01631   if ( mdd->headers )
01632     MimeHeaders_free ( mdd->headers );
01633   
01634   // 
01635   // Free the original attachment structure...
01636   // Make sure we only cleanup the local copy of the memory and not kill 
01637   // files we need on disk
01638   //
01639   if (bodyAsAttachment)
01640   {
01641     if ( mdd->messageBody->file_spec ) 
01642     {
01643       delete ( mdd->messageBody->file_spec );
01644       mdd->messageBody->file_spec = nsnull;
01645     }
01646   }
01647   mime_free_attachments (mdd->messageBody, 1);
01648 
01649   if (mdd->attachments)
01650   {
01651     int               i;
01652     nsMsgAttachedFile *cur = mdd->attachments;
01653     
01654     for ( i = 0; i < mdd->attachments_count; i++, cur++ ) 
01655     {
01656       if ( cur->file_spec ) 
01657       {
01658         delete ( cur->file_spec );
01659         cur->file_spec = nsnull;
01660       }
01661     }
01662     
01663     mime_free_attachments( mdd->attachments, mdd->attachments_count );
01664   }
01665   PR_FREEIF(mdd->mailcharset);
01666   
01667   mdd->identity = nsnull;
01668   PR_Free(mdd->url_name);
01669   PR_Free(mdd->originalMsgURI);
01670   PR_Free(mdd);
01671   
01672   PR_FREEIF(host);
01673   PR_FREEIF(to_and_cc);
01674   PR_FREEIF(re_subject);
01675   PR_FREEIF(new_refs);
01676   PR_FREEIF(from);
01677   PR_FREEIF(repl);
01678   PR_FREEIF(subj);
01679   PR_FREEIF(id);
01680   PR_FREEIF(refs);
01681   PR_FREEIF(to);
01682   PR_FREEIF(cc);
01683   PR_FREEIF(grps);
01684   PR_FREEIF(foll);
01685   PR_FREEIF(priority);
01686   PR_FREEIF(draftInfo);
01687   PR_Free(identityKey);
01688 
01689   mime_free_attach_data(newAttachData);
01690 }
01691 
01692 static void PR_CALLBACK
01693 mime_parse_stream_abort (nsMIMESession *stream, int status )
01694 {
01695   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;  
01696   NS_ASSERTION (mdd, "null mime draft data");
01697 
01698   if (!mdd) 
01699     return;
01700   
01701   if (mdd->obj) 
01702   {
01703     int status=0;
01704 
01705     if ( !mdd->obj->closed_p )
01706       status = mdd->obj->clazz->parse_eof ( mdd->obj, PR_TRUE );
01707     if ( !mdd->obj->parsed_p )
01708       mdd->obj->clazz->parse_end( mdd->obj, PR_TRUE );
01709     
01710     NS_ASSERTION ( mdd->options == mdd->obj->options, "draft display options not same as mime obj" );
01711     mime_free (mdd->obj);
01712     mdd->obj = 0;
01713     if (mdd->options) 
01714     {
01715       delete mdd->options;
01716       mdd->options = 0;
01717     }
01718 
01719     if (mdd->stream) 
01720     {
01721       mdd->stream->abort ((nsMIMESession *)mdd->stream->data_object, status);
01722       PR_Free( mdd->stream );
01723       mdd->stream = 0;
01724     }
01725   }
01726 
01727   if ( mdd->headers )
01728     MimeHeaders_free (mdd->headers);
01729 
01730 
01731   if (mdd->attachments)
01732     mime_free_attachments( mdd->attachments, mdd->attachments_count );
01733 
01734   PR_FREEIF(mdd->mailcharset);
01735 
01736   PR_Free (mdd);
01737 }
01738 
01739 static int
01740 make_mime_headers_copy ( void *closure, MimeHeaders *headers )
01741 {
01742   struct mime_draft_data *mdd = (struct mime_draft_data *) closure;
01743 
01744   NS_ASSERTION ( mdd && headers, "null mime draft data and/or headers" );
01745   
01746   if ( !mdd || ! headers ) 
01747     return 0;
01748 
01749   NS_ASSERTION ( mdd->headers == NULL , "non null mime draft data headers");
01750 
01751   mdd->headers = MimeHeaders_copy ( headers );
01752   mdd->options->done_parsing_outer_headers = PR_TRUE;
01753 
01754   return 0;
01755 }
01756 
01757 nsresult 
01758 mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers )
01759 {
01760   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
01761   nsMsgAttachedFile *attachments = 0, *newAttachment = 0;
01762   int nAttachments = 0;
01763   //char *hdr_value = NULL;
01764   char *parm_value = NULL;
01765   PRBool needURL = PR_FALSE;
01766   PRBool creatingMsgBody = PR_TRUE;
01767   PRBool bodyPart = PR_FALSE;
01768   
01769   NS_ASSERTION (mdd && headers, "null mime draft data and/or headers");
01770   if (!mdd || !headers) 
01771     return -1;
01772 
01773   if (mdd->options->decompose_init_count) 
01774   {
01775     mdd->options->decompose_init_count++;
01776     NS_ASSERTION(mdd->curAttachment, "missing attachment in mime_decompose_file_init_fn");
01777     if (mdd->curAttachment) {
01778       char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
01779       if (ct)
01780         NS_MsgSACopy(&(mdd->curAttachment->type), ct);
01781       PR_FREEIF(ct);
01782     }
01783     return 0;
01784   }
01785   else
01786     mdd->options->decompose_init_count++;
01787 
01788   nAttachments = mdd->attachments_count;
01789 
01790   if (!nAttachments && !mdd->messageBody) 
01791   {
01792     // if we've been told to use an override charset then do so....otherwise use the charset
01793     // inside the message header...
01794     if (mdd->options && mdd->options->override_charset)
01795         mdd->mailcharset = nsCRT::strdup(mdd->options->default_charset);
01796     else
01797     {
01798       char *contentType = NULL;
01799       contentType = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
01800       if (contentType) 
01801       {
01802         mdd->mailcharset = MimeHeaders_get_parameter(contentType, "charset", NULL, NULL);
01803         PR_FREEIF(contentType);
01804       }
01805     }
01806     
01807     mdd->messageBody = PR_NEWZAP (nsMsgAttachedFile);
01808     NS_ASSERTION (mdd->messageBody, "missing messageBody in mime_decompose_file_init_fn");
01809     if (!mdd->messageBody) 
01810       return MIME_OUT_OF_MEMORY;
01811     newAttachment = mdd->messageBody;
01812     creatingMsgBody = PR_TRUE;
01813     bodyPart = PR_TRUE;
01814   }
01815   else 
01816   {
01817     /* always allocate one more extra; don't ask me why */
01818     needURL = PR_TRUE;
01819     if ( nAttachments ) 
01820     {
01821       NS_ASSERTION (mdd->attachments, "no attachments");
01822       
01823       attachments = (nsMsgAttachedFile *)PR_REALLOC(mdd->attachments, 
01824                                                     sizeof (nsMsgAttachedFile) * 
01825                                                     (nAttachments + 2));
01826     if (!attachments)
01827         return MIME_OUT_OF_MEMORY;
01828       mdd->attachments = attachments;
01829       mdd->attachments_count++;
01830     }
01831     else {
01832       NS_ASSERTION (!mdd->attachments, "have attachments but count is 0");
01833       
01834       attachments = (nsMsgAttachedFile *) PR_MALLOC ( sizeof (nsMsgAttachedFile) * 2);
01835       if (!attachments) 
01836         return MIME_OUT_OF_MEMORY;
01837       mdd->attachments_count++;
01838       mdd->attachments = attachments;
01839     }
01840     
01841     newAttachment = attachments + nAttachments;
01842     memset ( newAttachment, 0, sizeof (nsMsgAttachedFile) * 2 );
01843   }
01844 
01845   char *workURLSpec = nsnull;
01846   char *contLoc = nsnull;
01847 
01848   newAttachment->real_name = MimeHeaders_get_name ( headers, mdd->options );
01849   contLoc = MimeHeaders_get( headers, HEADER_CONTENT_LOCATION, PR_FALSE, PR_FALSE );
01850   if (!contLoc)
01851       contLoc = MimeHeaders_get( headers, HEADER_CONTENT_BASE, PR_FALSE, PR_FALSE );
01852 
01853   if ( (!contLoc) && (newAttachment->real_name) )
01854     workURLSpec = nsCRT::strdup(newAttachment->real_name);
01855   if ( (contLoc) && (!workURLSpec) )
01856     workURLSpec = nsCRT::strdup(contLoc);
01857 
01858   PR_FREEIF(contLoc);
01859 
01860   mdd->curAttachment = newAttachment;  
01861   newAttachment->type =  MimeHeaders_get ( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE );
01862 
01863   //
01864   // This is to handle the degenerated Apple Double attachment.
01865   //
01866   parm_value = MimeHeaders_get( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE );
01867   if (parm_value) 
01868   {
01869     char *boundary = NULL;
01870     char *tmp_value = NULL;
01871     boundary = MimeHeaders_get_parameter(parm_value, "boundary", NULL, NULL);
01872     if (boundary)
01873       tmp_value = PR_smprintf("; boundary=\"%s\"", boundary);
01874     if (tmp_value)
01875       NS_MsgSACat(&(newAttachment->type), tmp_value);
01876     newAttachment->x_mac_type = MimeHeaders_get_parameter(parm_value, "x-mac-type", NULL, NULL);
01877     newAttachment->x_mac_creator = MimeHeaders_get_parameter(parm_value, "x-mac-creator", NULL, NULL);
01878     PR_FREEIF(parm_value);
01879     PR_FREEIF(boundary);
01880     PR_FREEIF(tmp_value);
01881   }
01882   newAttachment->encoding = MimeHeaders_get ( headers, HEADER_CONTENT_TRANSFER_ENCODING,
01883                                               PR_FALSE, PR_FALSE );
01884   newAttachment->description = MimeHeaders_get( headers, HEADER_CONTENT_DESCRIPTION,
01885                                                 PR_FALSE, PR_FALSE );
01886   // 
01887   // If we came up empty for description or the orig URL, we should do something about it.
01888   //
01889   if  ( ( (!newAttachment->description) || (!*newAttachment->description) ) && (workURLSpec) )
01890     newAttachment->description = nsCRT::strdup(workURLSpec);
01891 
01892   nsFileSpec *tmpSpec = nsnull;
01893   {
01894     // Let's build a temp file with an extension based on the content-type: nsmail.<extension>
01895 
01896     nsCAutoString  newAttachName ("nsmail");
01897     PRBool extensionAdded = PR_FALSE;
01898     // the content type may contain a charset. i.e. text/html; ISO-2022-JP...we want to strip off the charset
01899     // before we ask the mime service for a mime info for this content type.
01900     nsCAutoString contentType (newAttachment->type);
01901     PRInt32 pos = contentType.FindChar(';');
01902     if (pos > 0)
01903       contentType.Truncate(pos);
01904     nsresult  rv = NS_OK;
01905     nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
01906     if (NS_SUCCEEDED(rv) && mimeFinder) 
01907     {
01908       nsCAutoString fileExtension;
01909       rv = mimeFinder->GetPrimaryExtension(contentType, EmptyCString(), fileExtension);
01910 
01911       if (NS_SUCCEEDED(rv) && !fileExtension.IsEmpty())
01912       {
01913         newAttachName.Append(".");
01914         newAttachName.Append(fileExtension);
01915         extensionAdded = PR_TRUE;
01916       }
01917     }
01918 
01919     if (!extensionAdded)
01920     {
01921       newAttachName.Append(".tmp");
01922     }
01923 
01924     tmpSpec = nsMsgCreateTempFileSpec(newAttachName.get());
01925   }
01926 
01927   // This needs to be done so the attachment structure has a handle 
01928   // on the temp file for this attachment...
01929   // if ( (tmpSpec) && (!bodyPart) )
01930   if (tmpSpec)
01931   {
01932     nsCOMPtr<nsILocalFile> lf = do_CreateInstance("@mozilla.org/file/local;1");
01933     if (!lf)
01934       return MIME_OUT_OF_MEMORY;
01935     nsresult rv =
01936       lf->InitWithNativePath(nsDependentCString(tmpSpec->GetCString()));
01937     if (NS_SUCCEEDED(rv))
01938     {
01939       nsCAutoString fileURL;
01940       rv = NS_GetURLSpecFromFile(lf, fileURL);
01941       if (NS_SUCCEEDED(rv))
01942         nsMimeNewURI(getter_AddRefs(newAttachment->orig_url),
01943                      fileURL.get(), nsnull);
01944     }
01945   }
01946 
01947   PR_FREEIF(workURLSpec);
01948   if (!tmpSpec)
01949     return MIME_OUT_OF_MEMORY;
01950 
01951   NS_NewFileSpecWithSpec(*tmpSpec, &mdd->tmpFileSpec);
01952   if (!mdd->tmpFileSpec)
01953     return MIME_OUT_OF_MEMORY;
01954   
01955   newAttachment->file_spec = tmpSpec;
01956 
01957   mdd->tmpFileStream = new nsOutputFileStream(*tmpSpec, PR_WRONLY | PR_CREATE_FILE, 00600);
01958   if (!mdd->tmpFileStream)
01959     return MIME_UNABLE_TO_OPEN_TMP_FILE;
01960     
01961   // For now, we are always going to decode all of the attachments 
01962   // for the message. This way, we have native data 
01963   if (creatingMsgBody) 
01964   {
01965     MimeDecoderData *(*fn) (nsresult (*) (const char*, PRInt32, void*), void*) = 0;
01966     
01967     //
01968     // Initialize a decoder if necessary.
01969     //
01970     if (!newAttachment->encoding)
01971       ;
01972     else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_BASE64))
01973       fn = &MimeB64DecoderInit;
01974     else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_QUOTED_PRINTABLE))
01975     {
01976       mdd->decoder_data = MimeQPDecoderInit (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
01977                               ((nsresult (*) (const char *, PRInt32, void *))
01978                               dummy_file_write), mdd->tmpFileStream);
01979       if (!mdd->decoder_data)
01980         return MIME_OUT_OF_MEMORY;
01981     }
01982     else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE) ||
01983              !nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE2) ||
01984              !nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE3) ||
01985              !nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE4))
01986       fn = &MimeUUDecoderInit;
01987     else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_YENCODE))
01988       fn = &MimeYDecoderInit;
01989     
01990     if (fn) 
01991     {
01992       mdd->decoder_data = fn (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
01993                               ((nsresult (*) (const char *, PRInt32, void *))
01994                               dummy_file_write), mdd->tmpFileStream);
01995       if (!mdd->decoder_data)
01996         return MIME_OUT_OF_MEMORY;
01997     }
01998   }
01999 
02000   return 0;
02001 }
02002 
02003 nsresult 
02004 mime_decompose_file_output_fn (const char     *buf,
02005                                PRInt32  size,
02006                                void     *stream_closure )
02007 {
02008   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
02009   int ret = 0;
02010   
02011   NS_ASSERTION (mdd && buf, "missing mime draft data and/or buf");
02012   if (!mdd || !buf) return -1;
02013   if (!size) return NS_OK;
02014   
02015   if ( !mdd->tmpFileStream ) 
02016     return NS_OK;
02017   
02018   if (mdd->decoder_data) {
02019     ret = MimeDecoderWrite(mdd->decoder_data, buf, size);
02020     if (ret == -1) return -1;
02021   }
02022   else 
02023   {
02024     ret = mdd->tmpFileStream->write(buf, size);
02025     if (ret < size)
02026       return MIME_ERROR_WRITING_FILE;
02027   }
02028   
02029   return NS_OK;
02030 }
02031 
02032 nsresult
02033 mime_decompose_file_close_fn ( void *stream_closure )
02034 {
02035   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
02036   
02037   if ( !mdd || !mdd->tmpFileStream )
02038     return -1;
02039   
02040   if ( --mdd->options->decompose_init_count > 0 )
02041       return 0;
02042   
02043   if (mdd->decoder_data) {
02044     MimeDecoderDestroy(mdd->decoder_data, PR_FALSE);
02045     mdd->decoder_data = 0;
02046   }
02047 
02048   if (mdd->tmpFileStream->GetIStream())
02049     mdd->tmpFileStream->close();
02050 
02051   delete mdd->tmpFileStream;
02052   mdd->tmpFileStream = nsnull;
02053 
02054   delete mdd->tmpFileSpec;
02055   mdd->tmpFileSpec = nsnull;
02056   
02057   return 0;
02058 }
02059 
02060 extern "C" void  *
02061 mime_bridge_create_draft_stream(
02062                           nsIMimeEmitter      *newEmitter,
02063                           nsStreamConverter   *newPluginObj2,
02064                           nsIURI              *uri,
02065                           nsMimeOutputType    format_out)
02066 {
02067   int                     status = 0;
02068   nsMIMESession           *stream = nsnull;
02069   struct mime_draft_data  *mdd = nsnull;
02070   MimeObject              *obj = nsnull;
02071 
02072   if ( !uri ) 
02073     return nsnull;
02074 
02075   mdd = PR_NEWZAP(struct mime_draft_data);
02076   if (!mdd) 
02077     return nsnull;
02078 
02079   nsCAutoString turl;
02080   nsCOMPtr <nsIMsgMessageService> msgService;
02081   nsCOMPtr<nsIURI> aURL;
02082   nsCAutoString urlString;
02083   nsresult rv;
02084 
02085   // first, convert the rdf msg uri into a url that represents the message...
02086   if (NS_FAILED(uri->GetSpec(turl)))
02087     goto FAIL;
02088 
02089   rv = GetMessageServiceFromURI(turl.get(), getter_AddRefs(msgService));
02090   if (NS_FAILED(rv)) 
02091     goto FAIL;
02092 
02093   rv = msgService->GetUrlForUri(turl.get(), getter_AddRefs(aURL), nsnull);
02094   if (NS_FAILED(rv)) 
02095     goto FAIL;
02096 
02097   if (NS_SUCCEEDED(aURL->GetSpec(urlString)))
02098   {
02099     PRInt32 typeIndex = urlString.Find("&type=application/x-message-display");
02100     if (typeIndex != kNotFound)
02101       urlString.Cut(typeIndex, sizeof("&type=application/x-message-display") - 1);
02102 
02103     mdd->url_name = ToNewCString(urlString);
02104     if (!(mdd->url_name))
02105       goto FAIL;
02106   }
02107 
02108   newPluginObj2->GetForwardInline(&mdd->forwardInline);
02109   newPluginObj2->GetIdentity(getter_AddRefs(mdd->identity));
02110   newPluginObj2->GetOriginalMsgURI(&mdd->originalMsgURI);
02111   mdd->format_out = format_out;
02112   mdd->options = new  MimeDisplayOptions ;
02113   if (!mdd->options)
02114     goto FAIL;
02115 
02116   mdd->options->url = nsCRT::strdup(mdd->url_name);
02117   mdd->options->format_out = format_out;     // output format
02118   mdd->options->decompose_file_p = PR_TRUE; /* new field in MimeDisplayOptions */
02119   mdd->options->stream_closure = mdd;
02120   mdd->options->html_closure = mdd;
02121   mdd->options->decompose_headers_info_fn = make_mime_headers_copy;
02122   mdd->options->decompose_file_init_fn = mime_decompose_file_init_fn;
02123   mdd->options->decompose_file_output_fn = mime_decompose_file_output_fn;
02124   mdd->options->decompose_file_close_fn = mime_decompose_file_close_fn;
02125 
02126   mdd->options->m_prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
02127   if (NS_FAILED(rv))
02128     goto FAIL;
02129 
02130 #ifdef ENABLE_SMIME
02131   /* If we're attaching a message (for forwarding) then we must eradicate all
02132    traces of xlateion from it, since forwarding someone else a message
02133    that wasn't xlated for them doesn't work.  We have to dexlate it
02134    before sending it.
02135    */
02136   mdd->options->decrypt_p = PR_TRUE;
02137 #endif /* ENABLE_SMIME */
02138 
02139   obj = mime_new ( (MimeObjectClass *) &mimeMessageClass, (MimeHeaders *) NULL, MESSAGE_RFC822 );
02140   if ( !obj ) 
02141     goto FAIL;
02142   
02143   obj->options = mdd->options;
02144   mdd->obj = obj;
02145 
02146   stream = PR_NEWZAP ( nsMIMESession );
02147   if ( !stream ) 
02148     goto FAIL;
02149 
02150   stream->name = "MIME To Draft Converter Stream";
02151   stream->complete = mime_parse_stream_complete;
02152   stream->abort = mime_parse_stream_abort;
02153   stream->put_block = mime_parse_stream_write;
02154   stream->data_object = mdd;
02155 
02156   status = obj->clazz->initialize ( obj );
02157   if ( status >= 0 )
02158     status = obj->clazz->parse_begin ( obj );
02159   if ( status < 0 )
02160     goto FAIL;
02161 
02162   return stream;
02163 
02164 FAIL:
02165   if (mdd)
02166   {
02167     PR_Free(mdd->url_name);
02168     PR_Free(mdd->originalMsgURI);
02169     if (mdd->options)
02170       delete mdd->options;
02171     PR_Free ( mdd );
02172   }
02173   PR_Free ( stream );
02174   PR_Free ( obj );
02175 
02176   return nsnull;
02177 }