if (obj->options->format_out == nsMimeOutput::nsMimeMessageAttach && mult->state != MimeMultipartPartLine) { if (!obj->options->state->strippingPart  )
if (obj->options->format_out == nsMimeOutput::nsMimeMessageAttach && (!obj->options->state->strippingPart && mult->state != MimeMultipartPartLine))
MimeMultipart_parse_line (char *line, PRInt32 length, MimeObject *obj){  MimeMultipart *mult = (MimeMultipart *) obj;  int status = 0;  MimeMultipartBoundaryType boundary;  PR_ASSERT(line && *line);  if (!line || !*line) return -1;  PR_ASSERT(!obj->closed_p);  if (obj->closed_p) return -1;  /* If we're supposed to write this object, but aren't supposed to convert     it to HTML, simply pass it through unaltered. */  if (obj->output_p &&	  obj->options &&	  !obj->options->write_html_p &&	  obj->options->output_fn          && obj->options->format_out != nsMimeOutput::nsMimeMessageAttach)	return MimeObject_write(obj, line, length, PR_TRUE);  if (mult->state == MimeMultipartEpilogue)  /* already done */    boundary = MimeMultipartBoundaryTypeNone;  else    boundary = ((MimeMultipartClass *)obj->clazz)->check_boundary(obj, line,                                                                  length);  if (boundary == MimeMultipartBoundaryTypeTerminator ||    boundary == MimeMultipartBoundaryTypeSeparator)  {  /* Match!  Close the currently-open part, move on to the next     state, and discard this line.   */    PRBool endOfPart = (mult->state != MimeMultipartPreamble);    if (endOfPart)      status = ((MimeMultipartClass *)obj->clazz)->close_child(obj);    if (status < 0) return status;        if (boundary == MimeMultipartBoundaryTypeTerminator)      mult->state = MimeMultipartEpilogue;    else    {      mult->state = MimeMultipartHeaders;            /* Reset the header parser for this upcoming part. */      PR_ASSERT(!mult->hdrs);      if (mult->hdrs)        MimeHeaders_free(mult->hdrs);      mult->hdrs = MimeHeaders_new();      if (!mult->hdrs)        return MIME_OUT_OF_MEMORY;      if (obj->options->state->partsToStrip.Count() > 0)      {        nsCAutoString newPart(mime_part_address(obj));        MimeContainer *container = (MimeContainer*) obj;         newPart.Append('.');        newPart.AppendInt(container->nchildren + 1);        obj->options->state->strippingPart = PR_FALSE;        // check if this is a sub-part of a part we're stripping.        for (PRInt32 partIndex = 0; partIndex < obj->options->state->partsToStrip.Count(); partIndex++)        {          if (newPart.Find(*obj->options->state->partsToStrip.CStringAt(partIndex)) == 0)          {            obj->options->state->strippingPart = PR_TRUE;            if (partIndex < obj->options->state->detachToFiles.Count())              obj->options->state->detachedFilePath = *obj->options->state->detachToFiles.CStringAt(partIndex);            break;          }        }      }    }        // if stripping out attachments, write the boundary line. Otherwise, return    // to ignore it.    if (obj->options->format_out == nsMimeOutput::nsMimeMessageAttach)    {      // Because MimeMultipart_parse_child_line strips out the       // the CRLF of the last line before the end of a part, we need to add that      // back in here.      if (endOfPart)        MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));      status = MimeObject_write(obj, line, length, PR_TRUE);    }    return 0;  }  /* Otherwise, this isn't a boundary string.  So do whatever it is we	 should do with this line (parse it as a header, feed it to the	 child part, ignore it, etc.) */  switch (mult->state)  {    case MimeMultipartPreamble:    case MimeMultipartEpilogue:      /* Ignore this line. */      break;    case MimeMultipartHeaders:    /* Parse this line as a header for the sub-part. */    {      status = MimeHeaders_parse_line(line, length, mult->hdrs);      if (status < 0) return status;            // If this line is blank, we're now done parsing headers, and should      // now examine the content-type to create this "body" part.      //      if (*line == nsCRT::CR || *line == nsCRT::LF)      {        if (obj->options->state->strippingPart)        {          PRBool detachingPart = obj->options->state->detachedFilePath.Length() > 0;          nsCAutoString fileName;          fileName.Adopt(MimeHeaders_get_name(mult->hdrs, obj->options));          if (detachingPart)          {            char *contentType = MimeHeaders_get(mult->hdrs, "Content-Type", PR_FALSE, PR_FALSE);            MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Type: "));            MimeWriteAString(obj, nsDependentCString(contentType));            PR_Free(contentType);            char *contentEncoding = MimeHeaders_get(mult->hdrs, "Content-Transfer-Encoding", PR_FALSE, PR_FALSE);            if (contentEncoding)            {              MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));              MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Transfer-Encoding: "));              MimeWriteAString(obj, nsDependentCString(contentEncoding));              PR_Free(contentEncoding);            }            MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));            MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Disposition: attachment; filename=\""));            MimeWriteAString(obj, fileName);            MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK));            MimeWriteAString(obj, NS_LITERAL_CSTRING("X-Mozilla-External-Attachment-URL: "));            MimeWriteAString(obj, obj->options->state->detachedFilePath);            MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK));            MimeWriteAString(obj, NS_LITERAL_CSTRING("X-Mozilla-Altered: AttachmentDetached; date=\""));          }          else          {            nsCAutoString header("Content-Type: text/x-moz-deleted; name=\"Deleted: ");            header.Append(fileName);            status = MimeWriteAString(obj, header);            if (status < 0)               return status;            status = MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"Content-Transfer-Encoding: 8bit"MSG_LINEBREAK));            MimeWriteAString(obj, NS_LITERAL_CSTRING("Content-Disposition: inline; filename=\"Deleted:"));            MimeWriteAString(obj, fileName);            MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK"X-Mozilla-Altered: AttachmentDeleted; date=\""));          }          nsCString result;          char timeBuffer[128];          PRExplodedTime now;          PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &now);          PR_FormatTimeUSEnglish(timeBuffer, sizeof(timeBuffer),                                 "%a %b %d %H:%M:%S %Y",                                 &now);          MimeWriteAString(obj, nsDependentCString(timeBuffer));          MimeWriteAString(obj, NS_LITERAL_CSTRING("\""MSG_LINEBREAK));          MimeWriteAString(obj, NS_LITERAL_CSTRING(MSG_LINEBREAK"The original MIME headers for this attachment are:"MSG_LINEBREAK));          MimeHeaders_write_raw_headers(mult->hdrs, obj->options, PR_FALSE);        }        status = ((MimeMultipartClass *) obj->clazz)->create_child(obj);        if (status < 0) return status;        PR_ASSERT(mult->state != MimeMultipartHeaders);        // Ok, at this point, we need to examine the headers and see if there        // is a special charset (i.e. non US-ASCII) for this message. If so,         // we need to tell the emitter that this is the case for use in in any        // possible reply or forward operation.        //        PRBool isBody = PR_FALSE;        PRBool isAlternative = PR_FALSE;        MimeContainer *container = (MimeContainer*) obj;         // check if we're stripping the part of this newly created child.        if (container->children && container->nchildren > 0)        {          MimeObject *kid = container->children[container->nchildren-1];          if (kid->output_p)            kid->output_p = !obj->options->state->strippingPart;        }        if (container->children && container->nchildren == 1)        {          PRBool isAlternativeOrRelated = PR_FALSE;          isBody = MimeObjectChildIsMessageBody(obj, &isAlternativeOrRelated);          // MimeObjectChildIsMessageBody returns false for "multipart/related"          // but we want to use the first part charset if that's a body.          // I don't want to change the behavior of MimeObjectChildIsMessageBody          // which is used by other places, so do the body check here.          if (!isBody &&               isAlternativeOrRelated &&              mime_subclass_p(obj->clazz, (MimeObjectClass*) &mimeMultipartRelatedClass))          {            MimeObject *firstChild = container->children[0];            char *disposition = MimeHeaders_get (firstChild->headers,                                                 HEADER_CONTENT_DISPOSITION,                                                  PR_TRUE,                                                 PR_FALSE);            if (!disposition)            {              if (!nsCRT::strcasecmp (firstChild->content_type, TEXT_PLAIN) ||                  !nsCRT::strcasecmp (firstChild->content_type, TEXT_HTML) ||                  !nsCRT::strcasecmp (firstChild->content_type, TEXT_MDL) ||                  !nsCRT::strcasecmp (firstChild->content_type, MULTIPART_ALTERNATIVE) ||                  !nsCRT::strcasecmp (firstChild->content_type, MULTIPART_RELATED) ||                  !nsCRT::strcasecmp (firstChild->content_type, MESSAGE_NEWS) ||                  !nsCRT::strcasecmp (firstChild->content_type, MESSAGE_RFC822))                isBody = PR_TRUE;            }          }        }        else           isAlternative = mime_subclass_p(obj->clazz, (MimeObjectClass*) &mimeMultipartAlternativeClass);        // If "multipart/alternative" or the first part is a message body        // then we should check for a charset and notify the emitter          // if one exists.                                                             if (obj->options && ((isAlternative && mult->state != MimeMultipartSkipPartLine) || isBody))        {          {           char *ct = MimeHeaders_get(mult->hdrs, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);           if (ct)           {             char *cset = MimeHeaders_get_parameter (ct, "charset", NULL, NULL);             if (cset)             {                mimeEmitterUpdateCharacterSet(obj->options, cset);                if (!(obj->options->override_charset))                  // Also set this charset to msgWindow                  SetMailCharacterSetToMsgWindow(obj, cset);              }              PR_FREEIF(ct);              PR_FREEIF(cset);            }          }        }      }      break;    }    case MimeMultipartPartFirstLine:      /* Hand this line off to the sub-part. */      status = (((MimeMultipartClass *) obj->clazz)->parse_child_line(obj,                                                  line, length, PR_TRUE));      if (status < 0) return status;      mult->state = MimeMultipartPartLine;      break;    case MimeMultipartPartLine:      /* Hand this line off to the sub-part. */      status = (((MimeMultipartClass *) obj->clazz)->parse_child_line(obj,                  line, length, PR_FALSE));      if (status < 0) return status;      break;    case MimeMultipartSkipPartLine:      /* we are skipping that part, therefore just ignore the line */      break;    default:      PR_ASSERT(0);      return -1;  }  if (obj->options->format_out == nsMimeOutput::nsMimeMessageAttach && mult->state != MimeMultipartPartLine)  {    if (!obj->options->state->strippingPart  /* || mult->state != MimeMultipartHeaders */)      return MimeObject_write(obj, line, length, PR_FALSE);  }  return 0;}