home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmime / mimedrft.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  25.1 KB  |  903 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "xp.h"
  20. #include "libi18n.h"
  21. #include "xp_time.h"
  22. #include "msgcom.h"
  23. #include "mimeobj.h"
  24. #include "mimemsg.h"
  25. #include "mimeenc.h" /* jrm - needed to make it build 97/02/21 */
  26.  
  27. #define HEADER_NNTP_POSTING_HOST             "NNTP-Posting-Host"
  28.  
  29. extern int MK_UNABLE_TO_OPEN_TMP_FILE;
  30. extern int MK_MIME_ERROR_WRITING_FILE;
  31.  
  32.  
  33. int 
  34. mime_decompose_file_init_fn ( void *stream_closure,
  35.                               MimeHeaders *headers );
  36.  
  37.  
  38. int 
  39. mime_decompose_file_output_fn ( char *buf,
  40.                                 int32 size,
  41.                                 void *stream_closure );
  42.  
  43. int
  44. mime_decompose_file_close_fn ( void *stream_closure );
  45.  
  46. /* This struct is the state we used in MIME_ToDraftConverter() */
  47. struct mime_draft_data {
  48.   URL_Struct *url;                         /* original url */
  49.   int format_out;                          /* intended output format; 
  50.                                               should be FO_OPEN_DRAFT */
  51.   MWContext *context;
  52.   NET_StreamClass *stream;                 /* not used for now */
  53.   MimeObject *obj;                         /* The root */
  54.   MimeDisplayOptions *options;             /* data for communicating with libmime.a */
  55.   MimeHeaders *headers;                    /* copy of outer most mime header */
  56.   int attachments_count;                   /* how many attachments we have */
  57.   MSG_AttachedFile *attachments;           /* attachments */
  58.   MSG_AttachedFile *messageBody;           /* message body */
  59.   MSG_AttachedFile *curAttachment;           /* temp */
  60.   char *tmp_file_name;                     /* current opened file for output */
  61.   XP_File tmp_file;                        /* output file handle */
  62.   MimeDecoderData *decoder_data;
  63.   int16    mailcsid;                            /* get it from CHARSET of Content-Type and convert to csid */
  64. };
  65.  
  66.  
  67. static int
  68. dummy_file_write( char *buf, int32 size, void *fileHandle )
  69. {
  70.   return XP_FileWrite(buf, size, (XP_File) fileHandle);
  71. }
  72.  
  73. static int
  74. mime_parse_stream_write ( NET_StreamClass *stream,
  75.               const char *buf,
  76.               int32 size )
  77. {
  78.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;  
  79.   XP_ASSERT ( mdd );
  80.  
  81.   if ( !mdd || !mdd->obj ) return -1;
  82.  
  83.   return mdd->obj->class->parse_buffer ((char *) buf, size, mdd->obj);
  84. }
  85.  
  86. static unsigned int
  87. mime_parse_stream_write_ready ( NET_StreamClass *stream )
  88. {
  89.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;  
  90.   XP_ASSERT (mdd);
  91.  
  92.   if (!mdd) return MAX_WRITE_READY;
  93.   if (mdd->stream)
  94.     return mdd->stream->is_write_ready ( mdd->stream );
  95.   else
  96.     return MAX_WRITE_READY;
  97. }
  98.  
  99. static void
  100. mime_free_attachments ( MSG_AttachedFile *attachments,
  101.                         int count )
  102. {
  103.   int i;
  104.   MSG_AttachedFile *cur = attachments;
  105.  
  106.   XP_ASSERT ( attachments && count > 0 );
  107.   if ( !attachments || count <= 0 ) return;
  108.  
  109.   for ( i = 0; i < count; i++, cur++ ) {
  110.     FREEIF ( cur->orig_url );
  111.     FREEIF ( cur->type );
  112.     FREEIF ( cur->encoding );
  113.     FREEIF ( cur->description );
  114.     FREEIF ( cur->x_mac_type );
  115.     FREEIF ( cur->x_mac_creator );
  116.     if ( cur->file_name ) {
  117.       XP_FileRemove( cur->file_name, xpFileToPost );
  118.       FREEIF ( cur->file_name );
  119.     }
  120.   }
  121.   XP_FREE ( attachments );
  122. }
  123.  
  124. static int
  125. mime_draft_process_attachments ( struct mime_draft_data *mdd,
  126.                                  MSG_Pane *cpane )
  127. {
  128.   struct MSG_AttachmentData *attachData = NULL, *tmp = NULL;
  129.   struct MSG_AttachedFile *tmpFile = NULL;
  130.   int i;
  131.  
  132.   XP_ASSERT ( mdd->attachments_count && mdd->attachments );
  133.  
  134.   if ( !mdd->attachments || !mdd->attachments_count )
  135.     return -1;
  136.  
  137.   attachData = XP_ALLOC( ( (mdd->attachments_count+1) * sizeof (MSG_AttachmentData) ) );
  138.   if ( !attachData ) return MK_OUT_OF_MEMORY;
  139.  
  140.   XP_MEMSET ( attachData, 0, (mdd->attachments_count+1) * sizeof (MSG_AttachmentData) );
  141.  
  142.   tmpFile = mdd->attachments;
  143.   tmp = attachData;
  144.  
  145.   for ( i=0; i < mdd->attachments_count; i++, tmp++, tmpFile++ ) {
  146.     if (tmpFile->type) {
  147.         if (strcasecomp ( tmpFile->type, "text/x-vcard") == 0)
  148.             StrAllocCopy (tmp->real_name, tmpFile->description);
  149.     }
  150.     if ( tmpFile->orig_url ) {
  151.       StrAllocCopy ( tmp->url, tmpFile->orig_url );
  152.       if (!tmp->real_name)
  153.       StrAllocCopy ( tmp->real_name, tmpFile->orig_url );
  154.     }
  155.     if ( tmpFile->type ) {
  156.       StrAllocCopy ( tmp->desired_type, tmpFile->type );
  157.       StrAllocCopy ( tmp->real_type, tmpFile->type );
  158.     }
  159.     if ( tmpFile->encoding ) {
  160.       StrAllocCopy ( tmp->real_encoding, tmpFile->encoding );
  161.     }
  162.     if ( tmpFile->description ) {
  163.       StrAllocCopy ( tmp->description, tmpFile->description );
  164.     }
  165.     if ( tmpFile->x_mac_type ) {
  166.       StrAllocCopy ( tmp->x_mac_type, tmpFile->x_mac_type );
  167.     }
  168.     if ( tmpFile->x_mac_creator ) {
  169.       StrAllocCopy ( tmp->x_mac_creator, tmpFile->x_mac_creator );
  170.     }
  171.   }
  172.  
  173.   MSG_SetPreloadedAttachments ( cpane, MSG_GetContext (cpane), attachData,
  174.                                 mdd->attachments, mdd->attachments_count );
  175.  
  176.   XP_FREE (attachData);
  177.  
  178.   return 0;
  179.  
  180. }
  181.  
  182. static void
  183. mime_parse_stream_complete (NET_StreamClass *stream)
  184. {
  185.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
  186.   MSG_Pane * cpane = NULL;
  187.   MSG_CompositionFields *fields = NULL;
  188.   int htmlAction = 0;
  189.   int lineWidth = 0;
  190.  
  191.   char *host = 0;
  192.   char *news_host = 0;
  193.   char *to_and_cc = 0;
  194.   char *re_subject = 0;
  195.   char *new_refs = 0;
  196.   char *from = 0;
  197.   char *repl = 0;
  198.   char *subj = 0;
  199.   char *id = 0;
  200.   char *refs = 0;
  201.   char *to = 0;
  202.   char *cc = 0;
  203.   char *bcc = 0; 
  204.   char *fcc = 0; 
  205.   char *org = 0; 
  206.   char *grps = 0;
  207.   char *foll = 0;
  208.   char *priority = 0;
  209.   char *draftInfo = 0;
  210.  
  211.   XP_Bool encrypt_p = FALSE;    /* #### how do we determine this? */
  212.   XP_Bool sign_p = FALSE;        /* #### how do we determine this? */
  213.   
  214.   XP_ASSERT (mdd);
  215.  
  216.   if (!mdd) return;
  217.  
  218.   if (mdd->obj) {
  219.     int status;
  220.  
  221.     status = mdd->obj->class->parse_eof ( mdd->obj, FALSE );
  222.     mdd->obj->class->parse_end( mdd->obj, status < 0 ? TRUE : FALSE );
  223.     
  224.     encrypt_p = mdd->options->decrypt_p;
  225.     sign_p = mdd->options->signed_p;
  226.  
  227.     XP_ASSERT ( mdd->options == mdd->obj->options );
  228.     mime_free (mdd->obj);
  229.     mdd->obj = 0;
  230.     if (mdd->options) {
  231.       FREEIF (mdd->options->part_to_load);
  232.       XP_FREE(mdd->options);
  233.       mdd->options = 0;
  234.     }
  235.     if (mdd->stream) {
  236.       mdd->stream->complete (mdd->stream);
  237.       XP_FREE( mdd->stream );
  238.       mdd->stream = 0;
  239.     }
  240.   }
  241.  
  242.   /* time to bring up the compose windows with all the info gathered */
  243.  
  244.   if ( mdd->headers ) {
  245.     char *newString = NULL;
  246.  
  247.     repl = MimeHeaders_get(mdd->headers, HEADER_REPLY_TO, FALSE, FALSE);
  248.     subj = MimeHeaders_get(mdd->headers, HEADER_SUBJECT,  FALSE, FALSE);
  249.     to   = MimeHeaders_get(mdd->headers, HEADER_TO,       FALSE, TRUE);
  250.     cc   = MimeHeaders_get(mdd->headers, HEADER_CC,       FALSE, TRUE);
  251.     bcc   = MimeHeaders_get(mdd->headers, HEADER_BCC,       FALSE, TRUE);
  252.  
  253.     /* These headers should not be RFC-1522-decoded. */
  254.     grps = MimeHeaders_get(mdd->headers, HEADER_NEWSGROUPS,  FALSE, TRUE);
  255.     foll = MimeHeaders_get(mdd->headers, HEADER_FOLLOWUP_TO, FALSE, TRUE);
  256.     id   = MimeHeaders_get(mdd->headers, HEADER_MESSAGE_ID,  FALSE, FALSE);
  257.     refs = MimeHeaders_get(mdd->headers, HEADER_REFERENCES,  FALSE, TRUE);
  258.     priority = MimeHeaders_get(mdd->headers, HEADER_X_PRIORITY, FALSE, FALSE);
  259.  
  260.     host = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_NEWSHOST, FALSE, FALSE);
  261.     if (!host)
  262.       host = MimeHeaders_get(mdd->headers, HEADER_NNTP_POSTING_HOST, FALSE, FALSE);
  263.  
  264.     {
  265.         if (repl) 
  266.         {
  267.             newString = (char *)IntlDecodeMimePartIIStr(
  268.                              repl, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  269.             if (newString && newString != repl) 
  270.             {
  271.                 FREEIF (repl);
  272.                 repl = newString;
  273.             }
  274.         }
  275.         if (subj)
  276.         {
  277.             newString = (char *)IntlDecodeMimePartIIStr(
  278.                             subj, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  279.             if (newString && newString != repl) 
  280.             {
  281.                 FREEIF (subj);
  282.                 subj = newString;
  283.             }
  284.         }
  285.         if (to)
  286.         {
  287.             newString = (char *)IntlDecodeMimePartIIStr(
  288.                             to, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  289.             if (newString && newString != repl) 
  290.             {
  291.                 FREEIF (to);
  292.                 to = newString;
  293.             }
  294.         }
  295.         if (cc)
  296.         {
  297.             newString = (char *)IntlDecodeMimePartIIStr(
  298.                             cc, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  299.             if (newString && newString != cc) 
  300.             {
  301.                 FREEIF (cc);
  302.                 cc = newString;
  303.             }
  304.         }
  305.         if (bcc)
  306.         {
  307.             newString = (char *)IntlDecodeMimePartIIStr(
  308.                             bcc, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  309.             if (newString && newString != bcc) 
  310.             {
  311.                 FREEIF (bcc);
  312.                 bcc = newString;
  313.             }
  314.         }
  315.         if (grps)
  316.         {
  317.             newString = (char *)IntlDecodeMimePartIIStr(
  318.                             grps, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  319.             if (newString && newString != grps) 
  320.             {
  321.                 FREEIF (grps);
  322.                 grps = newString;
  323.             }
  324.         }
  325.         if (foll)
  326.         {
  327.             newString = (char *)IntlDecodeMimePartIIStr(
  328.                             foll, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  329.             if (newString && newString != foll) 
  330.             {
  331.                 FREEIF (foll);
  332.                 foll = newString;
  333.             }
  334.         }
  335.         if (host)
  336.         {
  337.             newString = (char *)IntlDecodeMimePartIIStr(
  338.                             host, INTL_DocToWinCharSetID(mdd->mailcsid), FALSE);
  339.             if (newString && newString != host) 
  340.             {
  341.                 FREEIF (host);
  342.                 repl = newString;
  343.             }
  344.         }
  345.     }
  346.  
  347.     if (host) {
  348.         char *secure = NULL;
  349.  
  350.         secure = strcasestr(host, "secure");
  351.         if (secure) {
  352.             *secure = 0;
  353.             news_host = PR_smprintf ("snews://%s", host);
  354.         }
  355.         else {
  356.             news_host = PR_smprintf ("news://%s", host);
  357.         }
  358.     }
  359.       
  360.  
  361.     fields = MSG_CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
  362.                                           org, subj, refs, 0, priority, 0, news_host,
  363.                                           encrypt_p, sign_p);
  364.  
  365.     draftInfo = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_DRAFT_INFO, FALSE, FALSE);
  366.     if (draftInfo && fields) {
  367.         char *parm = 0;
  368.         parm = MimeHeaders_get_parameter(draftInfo, "vcard");
  369.         if (parm && !XP_STRCMP(parm, "1"))
  370.             MSG_SetCompFieldsBoolHeader(fields, MSG_ATTACH_VCARD_BOOL_HEADER_MASK, TRUE);
  371.         else
  372.             MSG_SetCompFieldsBoolHeader(fields, MSG_ATTACH_VCARD_BOOL_HEADER_MASK, FALSE);
  373.         FREEIF(parm);
  374.         parm = MimeHeaders_get_parameter(draftInfo, "receipt");
  375.         if (parm && !XP_STRCMP(parm, "0"))
  376.             MSG_SetCompFieldsBoolHeader(fields,
  377.                                         MSG_RETURN_RECEIPT_BOOL_HEADER_MASK,
  378.                                         FALSE); 
  379.         else
  380.         {
  381.             int receiptType = 0;
  382.             MSG_SetCompFieldsBoolHeader(fields,
  383.                                         MSG_RETURN_RECEIPT_BOOL_HEADER_MASK,
  384.                                         TRUE); 
  385.             sscanf(parm, "%d", &receiptType);
  386.             MSG_SetCompFieldsReceiptType(fields, (int32) receiptType);
  387.         }
  388.         FREEIF(parm);
  389.         parm = MimeHeaders_get_parameter(draftInfo, "uuencode");
  390.         if (parm && !XP_STRCMP(parm, "1"))
  391.             MSG_SetCompFieldsBoolHeader(fields, MSG_UUENCODE_BINARY_BOOL_HEADER_MASK, TRUE);
  392.         else
  393.             MSG_SetCompFieldsBoolHeader(fields, MSG_UUENCODE_BINARY_BOOL_HEADER_MASK, FALSE);
  394.         FREEIF(parm);
  395.         parm = MimeHeaders_get_parameter(draftInfo, "html");
  396.         if (parm)
  397.             sscanf(parm, "%d", &htmlAction);
  398.         FREEIF(parm);
  399.         parm = MimeHeaders_get_parameter(draftInfo, "linewidth");
  400.         if (parm)
  401.             sscanf(parm, "%d", &lineWidth);
  402.         FREEIF(parm);
  403.  
  404.     }
  405.  
  406.     if (mdd->messageBody) {
  407.       char *body;
  408.       XP_StatStruct st;
  409.       XP_File file;
  410.       MSG_EditorType editorType = MSG_DEFAULT;
  411.  
  412.       st.st_size = 0;
  413.       XP_Stat (mdd->messageBody->file_name, &st, xpFileToPost);
  414.       body = XP_ALLOC (st.st_size + 1);
  415.       XP_MEMSET (body, 0, st.st_size+1);
  416.  
  417.       file = XP_FileOpen (mdd->messageBody->file_name, xpFileToPost, XP_FILE_READ_BIN);
  418.       XP_FileRead (body, st.st_size+1, file);
  419.       XP_FileClose(file);
  420.  
  421.       if (mdd->messageBody->type && *mdd->messageBody->type)
  422.       {
  423.           if( XP_STRSTR(mdd->messageBody->type, "text/html") != NULL )
  424.               editorType = MSG_HTML_EDITOR;
  425.           else if ( XP_STRSTR(mdd->messageBody->type, "text/plain") != NULL )
  426.               editorType = MSG_PLAINTEXT_EDITOR;
  427.       }
  428.  
  429.       {
  430.         CCCDataObject conv = INTL_CreateCharCodeConverter();
  431.         if(conv) {
  432.             if (INTL_GetCharCodeConverter(mdd->mailcsid, INTL_DocToWinCharSetID(mdd->mailcsid), conv)) {
  433.                 char *newBody = NULL;
  434.                 newBody = (char *)INTL_CallCharCodeConverter(
  435.                     conv, (unsigned char *) body, (int32) st.st_size+1);
  436.                 if (newBody) {
  437.                 /* CharCodeConverter return the char* to the orginal string
  438.                    we don't want to free body in that case */
  439.                     if( newBody != body)
  440.                         FREEIF(body);
  441.                     body = newBody;
  442.                 }
  443.             }
  444.             INTL_DestroyCharCodeConverter(conv);
  445.         }
  446.       }
  447.  
  448.       cpane = FE_CreateCompositionPane (mdd->context, fields, body, editorType);
  449.  
  450.       XP_FREE (body);
  451.       mime_free_attachments (mdd->messageBody, 1);
  452.     }
  453.     else
  454.     {
  455.         cpane = FE_CreateCompositionPane(mdd->context, fields, NULL, MSG_DEFAULT);
  456.     }
  457.  
  458.     if (cpane)
  459.     {
  460.         /* clear the message body in case someone store the signature string in it */
  461.         MSG_SetCompBody(cpane, "");
  462.         MSG_SetHTMLAction(cpane, (MSG_HTMLComposeAction) htmlAction);
  463.         if (lineWidth > 0)
  464.             MSG_SetLineWidth(cpane, lineWidth);
  465.  
  466.         if ( mdd->attachments_count) 
  467.           mime_draft_process_attachments (mdd, cpane);
  468.     }
  469.   }
  470.   else
  471.   {
  472.       fields = MSG_CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
  473.                                             org, subj, refs, 0, priority, 0, news_host,
  474.                                             MSG_GetMailEncryptionPreference(), 
  475.                                             MSG_GetMailSigningPreference());
  476.       if (fields)
  477.         cpane = FE_CreateCompositionPane(mdd->context, fields, NULL, MSG_DEFAULT);
  478.   }
  479.  
  480.   if (cpane) {
  481.       if ( mdd->url->fe_data && (mdd->format_out != FO_CMDLINE_ATTACHMENTS) ) 
  482.       {
  483.           MSG_SetPostDeliveryActionInfo (cpane, mdd->url->fe_data);
  484.       }
  485.       else
  486.       {
  487.           MSG_SetAttachmentList ( cpane, (MSG_AttachmentData*)(mdd->url->fe_data));
  488.       }
  489.   }
  490.  
  491.  
  492.   if ( mdd->headers )
  493.      MimeHeaders_free ( mdd->headers );
  494.  
  495.   if (mdd->attachments)
  496.     /* do not call mime_free_attachments just use FREEIF()  */
  497.     FREEIF ( mdd->attachments );
  498.  
  499.   if (fields)
  500.       MSG_DestroyCompositionFields(fields);
  501.  
  502.   XP_FREE (mdd);
  503.  
  504.   FREEIF(host);
  505.   FREEIF(to_and_cc);
  506.   FREEIF(re_subject);
  507.   FREEIF(new_refs);
  508.   FREEIF(from);
  509.   FREEIF(repl);
  510.   FREEIF(subj);
  511.   FREEIF(id);
  512.   FREEIF(refs);
  513.   FREEIF(to);
  514.   FREEIF(cc);
  515.   FREEIF(grps);
  516.   FREEIF(foll);
  517.   FREEIF(priority);
  518.   FREEIF(draftInfo);
  519.  
  520. }
  521.  
  522. static void
  523. mime_parse_stream_abort (NET_StreamClass *stream, int status )
  524. {
  525.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;  
  526.   XP_ASSERT (mdd);
  527.  
  528.   if (!mdd) return;
  529.   
  530.   if (mdd->obj) {
  531.     int status;
  532.  
  533.     if ( !mdd->obj->closed_p )
  534.       status = mdd->obj->class->parse_eof ( mdd->obj, TRUE );
  535.     if ( !mdd->obj->parsed_p )
  536.       mdd->obj->class->parse_end( mdd->obj, TRUE );
  537.     
  538.     XP_ASSERT ( mdd->options == mdd->obj->options );
  539.     mime_free (mdd->obj);
  540.     mdd->obj = 0;
  541.     if (mdd->options) {
  542.       FREEIF (mdd->options->part_to_load);
  543.       XP_FREE(mdd->options);
  544.       mdd->options = 0;
  545.     }
  546.     if (mdd->stream) {
  547.       mdd->stream->abort (mdd->stream, status);
  548.       XP_FREE( mdd->stream );
  549.       mdd->stream = 0;
  550.     }
  551.   }
  552.  
  553.   if ( mdd->headers )
  554.     MimeHeaders_free (mdd->headers);
  555.   if (mdd->attachments)
  556.     mime_free_attachments( mdd->attachments, mdd->attachments_count );
  557.  
  558.   XP_FREE (mdd);
  559. }
  560.  
  561. static int
  562. make_mime_headers_copy ( void *closure,
  563.                          MimeHeaders *headers )
  564. {
  565.   struct mime_draft_data *mdd = (struct mime_draft_data *) closure;
  566.  
  567.   XP_ASSERT ( mdd && headers );
  568.   
  569.   if ( !mdd || ! headers ) return 0;
  570.  
  571.   XP_ASSERT ( mdd->headers == NULL );
  572.  
  573.   mdd->headers = MimeHeaders_copy ( headers );
  574.  
  575.   mdd->options->done_parsing_outer_headers = TRUE;
  576.  
  577.   return 0;
  578. }
  579.  
  580. int 
  581. mime_decompose_file_init_fn ( void *stream_closure,
  582.                                 MimeHeaders *headers )
  583. {
  584.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
  585.   MSG_AttachedFile *attachments = 0, *newAttachment = 0;
  586.   int nAttachments = 0;
  587.   char *hdr_value = NULL, *parm_value = NULL;
  588.   XP_Bool needURL = FALSE;
  589.   XP_Bool creatingMsgBody = FALSE;
  590.   
  591.   XP_ASSERT (mdd && headers);
  592.   if (!mdd || !headers) return -1;
  593.  
  594.   if ( !mdd->options->is_multipart_msg ) {
  595.     if (mdd->options->decompose_init_count) {
  596.       mdd->options->decompose_init_count++;
  597.       XP_ASSERT(mdd->curAttachment);
  598.       if (mdd->curAttachment) {
  599.           char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, TRUE, FALSE);
  600.         if (ct)
  601.             StrAllocCopy(mdd->curAttachment->type, ct);
  602.         FREEIF(ct);
  603.       }
  604.       return 0;
  605.     }
  606.     else {
  607.       mdd->options->decompose_init_count++;
  608.     }
  609.   }
  610.  
  611.   nAttachments = mdd->attachments_count;
  612.  
  613.   if (!nAttachments && !mdd->messageBody) {
  614.     char *charset = NULL, *contentType = NULL;
  615.     contentType = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
  616.     if (contentType) {
  617.         charset = MimeHeaders_get_parameter(contentType, "charset");
  618.         mdd->mailcsid = INTL_CharSetNameToID(charset);
  619.         FREEIF(charset);
  620.         FREEIF(contentType);
  621.     }
  622.  
  623.     mdd->messageBody = XP_NEW_ZAP (MSG_AttachedFile);
  624.     XP_ASSERT (mdd->messageBody);
  625.     if (!mdd->messageBody) 
  626.       return MK_OUT_OF_MEMORY;
  627.     newAttachment = mdd->messageBody;
  628.     creatingMsgBody = TRUE;
  629.   }
  630.   else {
  631.     /* always allocate one more extra; don't ask me why */
  632.     needURL = TRUE;
  633.     if ( nAttachments ) {
  634.       XP_ASSERT (mdd->attachments);
  635.         
  636.       attachments = XP_REALLOC (mdd->attachments, 
  637.                                 sizeof (MSG_AttachedFile) * 
  638.                                 (nAttachments + 2));
  639.       if (!attachments)
  640.         return MK_OUT_OF_MEMORY;
  641.       mdd->attachments = attachments;
  642.       mdd->attachments_count++;
  643.     }
  644.     else {
  645.       XP_ASSERT (!mdd->attachments);
  646.       
  647.       attachments = XP_ALLOC ( sizeof (MSG_AttachedFile) * 2);
  648.       if (!attachments) 
  649.         return MK_OUT_OF_MEMORY;
  650.       mdd->attachments_count++;
  651.       mdd->attachments = attachments;
  652.     }
  653.  
  654.     newAttachment = attachments + nAttachments;
  655.     XP_MEMSET ( newAttachment, 0, sizeof (MSG_AttachedFile) * 2 );
  656.   }
  657.  
  658.   newAttachment->orig_url = MimeHeaders_get_name ( headers );
  659.  
  660.   if (!newAttachment->orig_url) {
  661.     parm_value = MimeHeaders_get( headers, HEADER_CONTENT_BASE, FALSE, FALSE );
  662.     if (parm_value) {
  663.       char *cp = NULL, *cp1=NULL ;
  664.       NET_UnEscape(parm_value);
  665.       /* strip '"' */
  666.       cp = parm_value;
  667.       while (*cp == '"') cp++;
  668.       if ((cp1 = XP_STRCHR(cp, '"')))
  669.         *cp1 = 0;
  670.       StrAllocCopy(newAttachment->orig_url, cp);
  671.       FREEIF(parm_value);
  672.     }
  673.   }
  674.  
  675.   mdd->curAttachment = newAttachment;
  676.  
  677.   newAttachment->type =  MimeHeaders_get ( headers, HEADER_CONTENT_TYPE,
  678.                                            TRUE, FALSE );
  679.   
  680.   /* This is to handle the degenerated Apple Double attachment.
  681.    */
  682.   parm_value = MimeHeaders_get( headers, HEADER_CONTENT_TYPE,
  683.                                            FALSE, FALSE );
  684.   if (parm_value) {
  685.       char *boundary = NULL;
  686.       char *tmp_value = NULL;
  687.       boundary = MimeHeaders_get_parameter(parm_value, "boundary");
  688.       if (boundary)
  689.           tmp_value = PR_smprintf("; boundary=\"%s\"", boundary);
  690.       if (tmp_value)
  691.           StrAllocCat(newAttachment->type, tmp_value);
  692.       newAttachment->x_mac_type = 
  693.           MimeHeaders_get_parameter(parm_value, "x-mac-type");
  694.       newAttachment->x_mac_creator = 
  695.           MimeHeaders_get_parameter(parm_value, "x-mac-creator");
  696.       FREEIF(parm_value);
  697.       FREEIF(boundary);
  698.       FREEIF(tmp_value);
  699.   }
  700.   newAttachment->encoding = MimeHeaders_get ( headers, 
  701.                                               HEADER_CONTENT_TRANSFER_ENCODING,
  702.                                               FALSE, FALSE );
  703.   newAttachment->description = MimeHeaders_get( headers, 
  704.                                                 HEADER_CONTENT_DESCRIPTION,
  705.                                                 FALSE, FALSE );
  706.   mdd->tmp_file_name = WH_TempName (xpFileToPost, "nsmail");
  707.  
  708.   if (!mdd->tmp_file_name)
  709.     return MK_OUT_OF_MEMORY;
  710.  
  711.   StrAllocCopy (newAttachment->file_name, mdd->tmp_file_name);
  712.   mdd->tmp_file = XP_FileOpen ( mdd->tmp_file_name, 
  713.                                 xpFileToPost, XP_FILE_WRITE_BIN );
  714.   if (!mdd->tmp_file)
  715.     return MK_UNABLE_TO_OPEN_TMP_FILE;
  716.  
  717.   /* if need an URL and we don't have one, let's fake one */
  718.   if (needURL && !newAttachment->orig_url) {
  719.     newAttachment->orig_url = PR_smprintf ("file://%s", mdd->tmp_file_name);
  720.   }
  721.  
  722.   if (creatingMsgBody) {
  723.     MimeDecoderData *(*fn) (int (*) (const char*, int32, void*), void*) = 0;
  724.  
  725.     /* Initialize a decoder if necessary.
  726.      */
  727.     if (!newAttachment->encoding || mdd->options->decrypt_p)
  728.     ;
  729.     else if (!strcasecomp(newAttachment->encoding, ENCODING_BASE64))
  730.       fn = &MimeB64DecoderInit;
  731.     else if (!strcasecomp(newAttachment->encoding, ENCODING_QUOTED_PRINTABLE))
  732.       fn = &MimeQPDecoderInit;
  733.     else if (!strcasecomp(newAttachment->encoding, ENCODING_UUENCODE) ||
  734.              !strcasecomp(newAttachment->encoding, ENCODING_UUENCODE2) ||
  735.              !strcasecomp(newAttachment->encoding, ENCODING_UUENCODE3) ||
  736.              !strcasecomp(newAttachment->encoding, ENCODING_UUENCODE4))
  737.       fn = &MimeUUDecoderInit;
  738.  
  739.     if (fn) {
  740.       mdd->decoder_data =
  741.         fn (/* The (int (*) ...) cast is to turn the `void' argument
  742.                into `MimeObject'. */
  743.             ((int (*) (const char *, int32, void *))
  744.              dummy_file_write),
  745.             mdd->tmp_file);
  746.       
  747.       if (!mdd->decoder_data)
  748.         return MK_OUT_OF_MEMORY;
  749.     }
  750.   }
  751.   return 0;
  752. }
  753.  
  754. int 
  755. mime_decompose_file_output_fn ( char *buf,
  756.                                 int32 size,
  757.                                 void *stream_closure )
  758. {
  759.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
  760.   int ret = 0;
  761.   
  762.   XP_ASSERT (mdd && buf);
  763.   if (!mdd || !buf) return -1;
  764.   if (!size) return 0;
  765.  
  766.   /****** doesn't seem to be needed *****
  767.   XP_ASSERT (mdd->tmp_file && mdd->tmp_file_name); 
  768.   */
  769.   if ( !mdd->tmp_file ) 
  770.     return 0;
  771.  
  772.   if (mdd->decoder_data) {
  773.     ret = MimeDecoderWrite(mdd->decoder_data, buf, size);
  774.     if (ret == -1) return -1;
  775.   }
  776.   else {
  777.     ret = XP_FileWrite(buf, size, mdd->tmp_file);
  778.     if (ret < size)
  779.       return MK_MIME_ERROR_WRITING_FILE;
  780.   }
  781.   
  782.   return 0;
  783. }
  784.  
  785. int
  786. mime_decompose_file_close_fn ( void *stream_closure )
  787. {
  788.   struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
  789.   
  790.   /* relax the rule in case we encountered invalid encrypted situation
  791.     XP_ASSERT (mdd && mdd->tmp_file); 
  792.    */
  793.   if ( !mdd || !mdd->tmp_file )
  794.     return -1;
  795.  
  796.   if ( !mdd->options->is_multipart_msg ) {
  797.     if ( --mdd->options->decompose_init_count > 0 )
  798.       return 0;
  799.   }
  800.  
  801.   if (mdd->decoder_data) {
  802.     MimeDecoderDestroy(mdd->decoder_data, FALSE);
  803.     mdd->decoder_data = 0;
  804.   }
  805.  
  806.   XP_FileClose ( mdd->tmp_file );
  807.   mdd->tmp_file = 0;
  808.   FREEIF ( mdd->tmp_file_name );
  809.   mdd->tmp_file_name = 0;
  810.  
  811.   return 0;
  812. }
  813.  
  814. extern NET_StreamClass *
  815. MIME_ToDraftConverter ( int format_out,
  816.             void *closure,
  817.             URL_Struct *url,
  818.             MWContext *context )
  819. {
  820.   int status = 0;
  821.   NET_StreamClass * stream = NULL;
  822.   struct mime_draft_data *mdd = NULL;
  823.   MimeObject *obj;
  824.  
  825.   XP_ASSERT (url && context);
  826.  
  827.   if ( !url || !context ) return NULL;
  828.  
  829.   mdd = XP_NEW_ZAP (struct mime_draft_data);
  830.   if (!mdd) return 0;
  831.  
  832.   mdd->url = url;
  833.   mdd->context = context;
  834.   mdd->format_out = format_out;
  835.  
  836.   mdd->options = XP_NEW_ZAP ( MimeDisplayOptions );
  837.   if ( !mdd->options ) {
  838.     XP_FREE (mdd);
  839.     return 0;
  840.   }
  841.   mdd->options->passwd_prompt_fn_arg = context;
  842.   mdd->options->decompose_file_p = TRUE;    /* new field in MimeDisplayOptions */
  843.   mdd->options->url = url->address;
  844.   mdd->options->stream_closure = mdd;
  845.   mdd->options->html_closure = mdd;
  846.   mdd->options->decompose_headers_info_fn = make_mime_headers_copy;
  847.   mdd->options->decompose_file_init_fn = mime_decompose_file_init_fn;
  848.   mdd->options->decompose_file_output_fn = mime_decompose_file_output_fn;
  849.   mdd->options->decompose_file_close_fn = mime_decompose_file_close_fn;
  850. #ifdef FO_MAIL_MESSAGE_TO
  851.   /* If we're attaching a message (for forwarding) then we must eradicate all
  852.      traces of encryption from it, since forwarding someone else a message
  853.      that wasn't encrypted for them doesn't work.  We have to decrypt it
  854.      before sending it.
  855.    */
  856.   mdd->options->decrypt_p = TRUE;
  857. #endif /* FO_MAIL_MESSAGE_TO */
  858.  
  859.   obj = mime_new ( (MimeObjectClass *) &mimeMessageClass,
  860.            (MimeHeaders *) NULL,
  861.            MESSAGE_RFC822 );
  862.   if ( !obj ) {
  863.     FREEIF( mdd->options->part_to_load );
  864.     XP_FREE ( mdd->options );
  865.     XP_FREE ( mdd );
  866.     return 0;
  867.   }
  868.   
  869.   obj->options = mdd->options;
  870.   mdd->obj = obj;
  871.  
  872.   stream = XP_NEW_ZAP ( NET_StreamClass );
  873.   if ( !stream ) {
  874.     FREEIF( mdd->options->part_to_load );
  875.     XP_FREE ( mdd->options );
  876.     XP_FREE ( mdd );
  877.     XP_FREE ( obj );
  878.     return 0;
  879.   }
  880.  
  881.   stream->name = "MIME To Draft Converter Stream";
  882.   stream->complete = mime_parse_stream_complete;
  883.   stream->abort = mime_parse_stream_abort;
  884.   stream->put_block = mime_parse_stream_write;
  885.   stream->is_write_ready = mime_parse_stream_write_ready;
  886.   stream->data_object = mdd;
  887.   stream->window_id = context;
  888.  
  889.   status = obj->class->initialize ( obj );
  890.   if ( status >= 0 )
  891.     status = obj->class->parse_begin ( obj );
  892.   if ( status < 0 ) {
  893.     XP_FREE ( stream );
  894.     FREEIF( mdd->options->part_to_load );
  895.     XP_FREE ( mdd->options );
  896.     XP_FREE ( mdd );
  897.     XP_FREE ( obj );
  898.     return 0;
  899.   }
  900.  
  901.   return stream;
  902. }
  903.