Exemplo n.º 1
0
static int
MimeInlineImage_parse_decoded_buffer (const char *buf, PRInt32 size, MimeObject *obj)
{
  /* This is called (by MimeLeafClass->parse_buffer) with blocks of data
   that have already been base64-decoded.  Pass this raw image data
   along to the backend-specific image display code.
   */
  MimeInlineImage *img  = (MimeInlineImage *) obj;
  int status;

  if (obj->output_p &&
    obj->options &&
    !obj->options->write_html_p)
  {
    /* in this case, we just want the raw data...
     Make the stream, if it's not made, and dump the data out.
     */

    if (!obj->options->state->first_data_written_p)
    {
      status = MimeObject_output_init(obj, 0);
      if (status < 0) return status;
      NS_ASSERTION(obj->options->state->first_data_written_p, "1.1 <*****@*****.**> 19 Mar 1999 12:00");
    }

    return MimeObject_write(obj, buf, size, PR_TRUE);
  }


  if (!obj->options ||
    !obj->options->image_write_buffer)
  return 0;

  /* If we don't have any image data, the image_end method must have already
   been called, so don't call image_write_buffer again. */
  if (!img->image_data) return 0;

  /* Hand this data off to the backend-specific image display stream.
   */
  status = obj->options->image_write_buffer (buf, size, img->image_data);

  /* If the image display stream fails, then close the stream - but do not
   return the failure status, and do not give up on parsing this object.
   Just because the image data was corrupt doesn't mean we need to give up
   on the whole document; we can continue by just skipping over the rest of
   this part, and letting our parent continue.
   */
  if (status < 0)
  {
    obj->options->image_end (img->image_data, status);
    img->image_data = 0;
    status = 0;
  }

  return status;
}
Exemplo n.º 2
0
static int
MimeMessage_write_headers_html (MimeObject *obj)
{
  MimeMessage     *msg = (MimeMessage *) obj;
  int             status;

#ifdef MOZ_SECURITY
  HG33391
#endif /* MOZ_SECURITY */

  if (!obj->options || !obj->options->output_fn)
    return 0;

  PR_ASSERT(obj->output_p && obj->options->write_html_p);

  // To support the no header option! Make sure we are not
  // suppressing headers on included email messages...
  if ( (obj->options->headers == MimeHeadersNone) &&
       (obj == obj->options->state->root) )
  {
    // Ok, we are going to kick the Emitter for a StartHeader
    // operation ONLY WHEN THE CHARSET OF THE ORIGINAL MESSAGE IS
    // NOT US-ASCII ("ISO-8859-1")
    //
    // This is only to notify the emitter of the charset of the
    // original message
    char    *mailCharset = DetermineMailCharset(msg);

    if ( (mailCharset) && (PL_strcasecmp(mailCharset, "US-ASCII")) &&
         (PL_strcasecmp(mailCharset, "ISO-8859-1")) )
      mimeEmitterUpdateCharacterSet(obj->options, mailCharset);
    PR_FREEIF(mailCharset);
    return 0;
  }

  if (!obj->options->state->first_data_written_p)
  {
    status = MimeObject_output_init (obj, TEXT_HTML);
    if (status < 0)
    {
      mimeEmitterEndHeader(obj->options);
      return status;
    }
    PR_ASSERT(obj->options->state->first_data_written_p);
  }

  // Start the header parsing by the emitter
  char *msgID = MimeHeaders_get (msg->hdrs, HEADER_MESSAGE_ID,
                                    PR_FALSE, PR_FALSE);
  PRBool outer_p = !obj->headers; /* is this the outermost message? */
  if (!outer_p && obj->options->format_out == nsMimeOutput::nsMimeMessageBodyDisplay &&
      obj->options->part_to_load)
  {
    //Maybe we are displaying a embedded message as outer part!
    char *id = mime_part_address(obj);
    if (id)
    {
      outer_p = !strcmp(id, obj->options->part_to_load);
      PR_Free(id);
    }
  }

  // Ok, we should really find out the charset of this part. We always
  // output UTF-8 for display, but the original charset is necessary for
  // reply and forward operations.
  //
  char    *mailCharset = DetermineMailCharset(msg);
  mimeEmitterStartHeader(obj->options,
                            outer_p,
                            (obj->options->headers == MimeHeadersOnly),
                            msgID,
                            mailCharset);

  // Change the default_charset by the charset of the original message
  // ONLY WHEN THE CHARSET OF THE ORIGINAL MESSAGE IS NOT US-ASCII
  // ("ISO-8859-1") and defailt_charset and mailCharset are different.
  if ( (mailCharset) && (PL_strcasecmp(mailCharset, "US-ASCII")) &&
       (PL_strcasecmp(mailCharset, "ISO-8859-1")) &&
       (PL_strcasecmp(obj->options->default_charset, mailCharset)) &&
       !obj->options->override_charset )
  {
    PR_FREEIF(obj->options->default_charset);
    obj->options->default_charset = strdup(mailCharset);
  }

  PR_FREEIF(msgID);
  PR_FREEIF(mailCharset);

#ifdef MOZ_SECURITY
    HG00919
#endif /* MOZ_SECURITY */

  status = MimeHeaders_write_all_headers (msg->hdrs, obj->options, PR_FALSE);
  if (status < 0)
  {
    mimeEmitterEndHeader(obj->options);
    return status;
  }

  if (msg->crypto_stamped_p)
  {
#ifdef MOZ_SECURITY
    HG11995
#endif /* MOZ_SECURITY */
  }
  else
  {
  /* If we're not writing a xlation stamp, and this is the outermost
  message, then now is the time to run the post_header_html_fn.
  (Otherwise, it will be run when the xlation-stamp is finally
  closed off, in MimeXlateed_emit_buffered_child() or
  MimeMultipartSigned_emit_child().)
     */
    if (obj->options &&
      obj->options->state &&
      obj->options->generate_post_header_html_fn &&
      !obj->options->state->post_header_html_run_p)
    {
      char *html = 0;
      PR_ASSERT(obj->options->state->first_data_written_p);
      html = obj->options->generate_post_header_html_fn(NULL,
                                          obj->options->html_closure,
                                          msg->hdrs);
      obj->options->state->post_header_html_run_p = PR_TRUE;
      if (html)
      {
        status = MimeObject_write(obj, html, strlen(html), PR_FALSE);
        PR_Free(html);
        if (status < 0)
        {
          mimeEmitterEndHeader(obj->options);
          return status;
        }
      }
    }
  }

  mimeEmitterEndHeader(obj->options);

  // rhp:
  // For now, we are going to parse the entire message, even if we are
  // only interested in headers...why? Well, because this is the only
  // way to build the attachment list. Now we will have the attachment
  // list in the output being created by the XML emitter. If we ever
  // want to go back to where we were before, just uncomment the conditional
  // and it will stop at header parsing.
  //
  // if (obj->options->headers == MimeHeadersOnly)
  //   return -1;
  // else

  return 0;
}
Exemplo n.º 3
0
static int
MimeMessage_close_headers (MimeObject *obj)
{
  MimeMessage *msg = (MimeMessage *) obj;
  int status = 0;
  char *ct = 0;      /* Content-Type header */
  MimeObject *body;

  if (msg->hdrs)
  {
    PRBool outer_p = !obj->headers; /* is this the outermost message? */


#ifdef MIME_DRAFTS
    if (outer_p &&
      obj->options &&
          (obj->options->decompose_file_p || obj->options->caller_need_root_headers) &&
      obj->options->decompose_headers_info_fn)
    {
#ifdef ENABLE_SMIME
      if (obj->options->decrypt_p && !mime_crypto_object_p (msg->hdrs, PR_FALSE))
        obj->options->decrypt_p = PR_FALSE;
#endif /* ENABLE_SMIME */
      if (!obj->options->caller_need_root_headers || (obj == obj->options->state->root))
        status = obj->options->decompose_headers_info_fn (
                         obj->options->stream_closure,
                               msg->hdrs );
    }
#endif /* MIME_DRAFTS */


    /* If this is the outermost message, we need to run the
     `generate_header' callback.  This happens here instead of
     in `parse_begin', because it's only now that we've parsed
     our headers.  However, since this is the outermost message,
     we have yet to write any HTML, so that's fine.
     */
    if (outer_p &&
      obj->output_p &&
      obj->options &&
      obj->options->write_html_p &&
      obj->options->generate_header_html_fn)
    {
      int lstatus = 0;
      char *html = 0;

      /* The generate_header_html_fn might return HTML, so it's important
       that the output stream be set up with the proper type before we
       make the MimeObject_write() call below. */
      if (!obj->options->state->first_data_written_p)
      {
        lstatus = MimeObject_output_init (obj, TEXT_HTML);
        if (lstatus < 0) return lstatus;
        PR_ASSERT(obj->options->state->first_data_written_p);
      }

      html = obj->options->generate_header_html_fn(NULL,
                           obj->options->html_closure,
                             msg->hdrs);
      if (html)
      {
        lstatus = MimeObject_write(obj, html, strlen(html), PR_FALSE);
        PR_Free(html);
        if (lstatus < 0) return lstatus;
      }
    }


    /* Find the content-type of the body of this message.
     */
    {
    PRBool ok = PR_TRUE;
    char *mv = MimeHeaders_get (msg->hdrs, HEADER_MIME_VERSION,
                  PR_TRUE, PR_FALSE);

#ifdef REQUIRE_MIME_VERSION_HEADER
    /* If this is the outermost message, it must have a MIME-Version
       header with the value 1.0 for us to believe what might be in
       the Content-Type header.  If the MIME-Version header is not
       present, we must treat this message as untyped.
     */
    ok = (mv && !strcmp(mv, "1.0"));
#else
    /* #### actually, we didn't check this in Mozilla 2.0, and checking
       it now could cause some compatibility nonsense, so for now, let's
       just believe any Content-Type header we see.
     */
    ok = PR_TRUE;
#endif

    if (ok)
      {
      ct = MimeHeaders_get (msg->hdrs, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);

      /* If there is no Content-Type header, but there is a MIME-Version
         header, then assume that this *is* in fact a MIME message.
         (I've seen messages with

          MIME-Version: 1.0
          Content-Transfer-Encoding: quoted-printable

         and no Content-Type, and we should treat those as being of type
         MimeInlineTextPlain rather than MimeUntypedText.)
       */
      if (mv && !ct)
        ct = strdup(TEXT_PLAIN);
      }

    PR_FREEIF(mv);  /* done with this now. */
    }

    /* If this message has a body which is encrypted and we're going to
       decrypt it (whithout converting it to HTML, since decrypt_p and
       write_html_p are never true at the same time)
    */
    if (obj->output_p &&
        obj->options &&
        obj->options->decrypt_p
#ifdef ENABLE_SMIME
        && !mime_crypto_object_p (msg->hdrs, PR_FALSE)
#endif /* ENABLE_SMIME */
        )
    {
      /* The body of this message is not an encrypted object, so we need
         to turn off the decrypt_p flag (to prevent us from s#$%ing the
         body of the internal object up into one.) In this case,
         our output will end up being identical to our input.
      */
      obj->options->decrypt_p = PR_FALSE;
    }

    /* Emit the HTML for this message's headers.  Do this before
     creating the object representing the body.
     */
    if (obj->output_p &&
      obj->options &&
      obj->options->write_html_p)
    {
      /* If citation headers are on, and this is not the outermost message,
       turn them off. */
      if (obj->options->headers == MimeHeadersCitation && !outer_p)
      obj->options->headers = MimeHeadersSome;

      /* Emit a normal header block. */
      status = MimeMessage_write_headers_html(obj);
      if (status < 0) return status;
    }
    else if (obj->output_p)
    {
      /* Dump the headers, raw. */
      status = MimeObject_write(obj, "", 0, PR_FALSE);  /* initialize */
      if (status < 0) return status;
      status = MimeHeaders_write_raw_headers(msg->hdrs, obj->options,
                         obj->options->decrypt_p);
      if (status < 0) return status;
    }

#ifdef XP_UNIX
    if (outer_p && obj->output_p)
    /* Kludge from mimehdrs.c */
    MimeHeaders_do_unix_display_hook_hack(msg->hdrs);
#endif /* XP_UNIX */
  }

  /* Never put out a separator after a message header block. */
  if (obj->options && obj->options->state)
  obj->options->state->separator_suppressed_p = PR_TRUE;

#ifdef MIME_DRAFTS
  if ( !obj->headers &&    /* outer most message header */
     obj->options &&
     obj->options->decompose_file_p &&
     ct )
  obj->options->is_multipart_msg = PL_strcasestr(ct, "multipart/") != NULL;
#endif /* MIME_DRAFTS */


  body = mime_create(ct, msg->hdrs, obj->options);

  PR_FREEIF(ct);
  if (!body) return MIME_OUT_OF_MEMORY;
  status = ((MimeContainerClass *) obj->clazz)->add_child (obj, body);
  if (status < 0)
  {
    mime_free(body);
    return status;
  }

  // Only do this if this is a Text Object!
  if ( mime_typep(body, (MimeObjectClass *) &mimeInlineTextClass) )
  {
    ((MimeInlineText *) body)->needUpdateMsgWinCharset = PR_TRUE;
  }

  /* Now that we've added this new object to our list of children,
   start its parser going. */
  status = body->clazz->parse_begin(body);
  if (status < 0) return status;

  // Now notify the emitter if this is the outer most message, unless
  // it is a part that is not the head of the message. If it's a part,
  // we need to figure out the content type/charset of the part
  //
  PRBool outer_p = !obj->headers;  /* is this the outermost message? */

  if ( outer_p &&
       (!obj->options->part_to_load || obj->options->format_out == nsMimeOutput::nsMimeMessageBodyDisplay))
  {
    // call SetMailCharacterSetToMsgWindow() to set a menu charset
    if (mime_typep(body, (MimeObjectClass *) &mimeInlineTextClass))
    {
      MimeInlineText  *text = (MimeInlineText *) body;
      if (text && text->charset && *text->charset)
        SetMailCharacterSetToMsgWindow(body, text->charset);
    }

    char  *msgID = MimeHeaders_get (msg->hdrs, HEADER_MESSAGE_ID,
                                    PR_FALSE, PR_FALSE);

    const char  *outCharset = NULL;
    if (!obj->options->force_user_charset)  /* Only convert if the user prefs is false */
      outCharset = "UTF-8";

    mimeEmitterStartBody(obj->options, (obj->options->headers == MimeHeadersNone), msgID, outCharset);
    PR_FREEIF(msgID);

  // setting up truncated message html fotter function
  char *xmoz = MimeHeaders_get(msg->hdrs, HEADER_X_MOZILLA_STATUS, PR_FALSE,
                 PR_FALSE);
  if (xmoz)
  {
    PRUint32 flags = 0;
    char dummy = 0;
    if (sscanf(xmoz, " %lx %c", &flags, &dummy) == 1 &&
      flags & MSG_FLAG_PARTIAL)
    {
      obj->options->html_closure = obj;
      obj->options->generate_footer_html_fn =
        MimeMessage_partial_message_html;
    }
    PR_FREEIF(xmoz);
  }
  }

  return 0;
}
Exemplo n.º 4
0
static int
MimeExternalObject_parse_begin (MimeObject *obj)
{
  int status;

  status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_begin(obj);
  if (status < 0) return status;

  // If we're writing this object, and we're doing it in raw form, then
  // now is the time to inform the backend what the type of this data is.
  //
  if (obj->output_p &&
    obj->options &&
    !obj->options->write_html_p &&
    !obj->options->state->first_data_written_p)
  {
    status = MimeObject_output_init(obj, 0);
    if (status < 0) return status;
    NS_ASSERTION(obj->options->state->first_data_written_p, "1.1 <*****@*****.**> 19 Mar 1999 12:00");
  }

  //
  // If we're writing this object as HTML, do all the work now -- just write
  // out a table with a link in it.  (Later calls to the `parse_buffer' method
  // will simply discard the data of the object itself.)
  //
  if (obj->options &&
      obj->output_p &&
      obj->options->write_html_p &&
      obj->options->output_fn)
  {
    MimeDisplayOptions newopt = *obj->options;  // copy it
    char *id = 0;
    char *id_url = 0;
    char *id_name = 0;
    nsCString id_imap;
    PRBool all_headers_p = obj->options->headers == MimeHeadersAll;

    id = mime_part_address (obj);
    if (obj->options->missing_parts)
      id_imap.Adopt(mime_imap_part_address (obj));
    if (! id) return MIME_OUT_OF_MEMORY;

    if (obj->options && obj->options->url)
    {
      const char *url = obj->options->url;
      if (!id_imap.IsEmpty() && id)
      {
        // if this is an IMAP part.
        id_url = mime_set_url_imap_part(url, id_imap.get(), id);
      }
      else
      {
        // This is just a normal MIME part as usual.
        id_url = mime_set_url_part(url, id, PR_TRUE);
      }
      if (!id_url)
      {
        PR_Free(id);
        return MIME_OUT_OF_MEMORY;
      }
    }
    if (!strcmp (id, "0"))
    {
      PR_Free(id);
      id = MimeGetStringByID(MIME_MSG_ATTACHMENT);
    }
    else
    {
      const char *p = "Part ";
      PRUint32 slen = strlen(p) + strlen(id) + 1;
      char *s = (char *)PR_MALLOC(slen);
      if (!s)
      {
        PR_Free(id);
        PR_Free(id_url);
        return MIME_OUT_OF_MEMORY;
      }
      // we have a valid id
      if (id)
        id_name = mime_find_suggested_name_of_part(id, obj);
      PL_strncpyz(s, p, slen);
      PL_strcatn(s, slen, id);
      PR_Free(id);
      id = s;
    }

    if (all_headers_p &&
    // Don't bother showing all headers on this part if it's the only
    // part in the message: in that case, we've already shown these
    // headers.
    obj->options->state &&
    obj->options->state->root == obj->parent)
    all_headers_p = PR_FALSE;

    newopt.fancy_headers_p = PR_TRUE;
    newopt.headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome);

/******
RICHIE SHERRY
GOTTA STILL DO THIS FOR QUOTING!
     status = MimeHeaders_write_attachment_box (obj->headers, &newopt,
                                                 obj->content_type,
                                                 obj->encoding,
                                                 id_name? id_name : id, id_url, 0)
*****/

    // obj->options really owns the storage for this.
    newopt.part_to_load = nsnull;
    newopt.default_charset = nsnull;
    PR_FREEIF(id);
    PR_FREEIF(id_url);
    PR_FREEIF(id_name);
    if (status < 0) return status;
  }

  return 0;
}