/* Helper function for mime_finish_crypto_encapsulation() to close off an opaque crypto object (for encrypted or signed-and-encrypted messages.) */ nsresult nsMsgComposeSecure::MimeFinishEncryption (bool aSign, nsIMsgSendReport *sendReport) { nsresult rv; /* If this object is both encrypted and signed, close off the signature first (since it's inside.) */ if (aSign) { rv = MimeFinishMultipartSigned (false, sendReport); if (NS_FAILED(rv)) { goto FAIL; } } /* Close off the opaque encrypted blob. */ PR_ASSERT(mEncryptionContext); if (mBufferedBytes) { rv = mEncryptionContext->Update(mBuffer, mBufferedBytes); mBufferedBytes = 0; if (NS_FAILED(rv)) { PR_ASSERT(PR_GetError() < 0); goto FAIL; } } rv = mEncryptionContext->Finish(); if (NS_FAILED(rv)) { SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotEncrypt").get()); goto FAIL; } mEncryptionContext = 0; PR_ASSERT(mEncryptionCinfo); if (!mEncryptionCinfo) { rv = NS_ERROR_FAILURE; } if (mEncryptionCinfo) { mEncryptionCinfo = 0; } /* Shut down the base64 encoder. */ rv = MIME_EncoderDestroy(mCryptoEncoderData, false); mCryptoEncoderData = 0; PRUint32 n; rv = mStream->Write(CRLF, 2, &n); if (NS_FAILED(rv) || n < 2) rv = NS_ERROR_FAILURE; FAIL: return rv; }
nsMsgComposeSecure::~nsMsgComposeSecure() { /* destructor code */ if (mEncryptionContext) { if (mBufferedBytes) { mEncryptionContext->Update(mBuffer, mBufferedBytes); mBufferedBytes = 0; } mEncryptionContext->Finish(); } if (mSigEncoderData) { MIME_EncoderDestroy (mSigEncoderData, true); } if (mCryptoEncoderData) { MIME_EncoderDestroy (mCryptoEncoderData, true); } delete [] mBuffer; PR_FREEIF(mMultipartSignedBoundary); }
nsMsgSendPart::~nsMsgSendPart() { if (m_encoder_data) { MIME_EncoderDestroy(m_encoder_data, false); m_encoder_data = nsnull; } for (int i=0 ; i < m_numchildren; i++) delete m_children[i]; delete [] m_children; PR_FREEIF(m_buffer); PR_FREEIF(m_other); PR_FREEIF(m_type); }
int nsMsgSendPart::Write() { int status = 0; char *separator = nsnull; bool needToWriteCRLFAfterEncodedBody = false; #define PUSHLEN(str, length) \ do { \ status = mime_write_message_body(m_state, str, length); \ if (status < 0) goto FAIL; \ } while (0) \ #define PUSH(str) PUSHLEN(str, PL_strlen(str)) // rhp: Suppress the output of parts that are empty! if ( (m_parent) && (m_numchildren == 0) && ( (!m_buffer) || (!*m_buffer) ) && (!m_file) && (!m_mainpart) ) return SKIP_EMPTY_PART; if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) { if (m_file) { // The "insert HTML links" code requires a memory buffer, // so read the file into memory. NS_ASSERTION(m_buffer == nsnull, "not-null buffer"); PRInt32 length = 0; PRInt64 fileSize; if (NS_SUCCEEDED(m_file->GetFileSize(&fileSize))) length = fileSize; m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1)); if (m_buffer) { nsCOMPtr<nsIInputStream> inputFile; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputFile), m_file); if (NS_SUCCEEDED(rv)) { PRUint32 bytesRead; rv = inputFile->Read(m_buffer, length, &bytesRead); inputFile->Close(); m_buffer[length] = '\0'; } else PR_Free(m_buffer); } } } if (m_parent && m_parent->m_type && !PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) && m_type && (!PL_strcasecmp(m_type, MESSAGE_RFC822) || !PL_strcasecmp(m_type, MESSAGE_NEWS))) { // If we're in a multipart/digest, and this document is of type // message/rfc822, then it's appropriate to emit no headers. // } else { char *message_headers = 0; char *content_headers = 0; char *content_type_header = 0; status = divide_content_headers(m_other, &message_headers, &content_headers, &content_type_header); if (status < 0) goto FAIL; /* First, write out all of the headers that refer to the message itself (From, Subject, MIME-Version, etc.) */ if (message_headers) { PUSH(message_headers); PR_Free(message_headers); message_headers = 0; } /* Now allow the crypto library to (potentially) insert some text (it may want to wrap the body in an envelope.) */ if (!m_parent) { status = m_state->BeginCryptoEncapsulation(); if (status < 0) goto FAIL; } /* Now make sure there's a Content-Type header. */ if (!content_type_header) { NS_ASSERTION(m_type && *m_type, "null ptr"); bool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN); if (needsCharset) { content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF, (m_type ? m_type : TEXT_PLAIN), m_charset_name); } else content_type_header = PR_smprintf("Content-Type: %s" CRLF, (m_type ? m_type : TEXT_PLAIN)); if (!content_type_header) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } /* If this is a compound object, tack a boundary string onto the Content-Type header. this */ if (m_numchildren > 0) { int L; char *ct2; NS_ASSERTION(m_type, "null ptr"); if (!separator) { separator = mime_make_separator(""); if (!separator) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } L = PL_strlen(content_type_header); if (content_type_header[L-1] == '\n') content_type_header[--L] = 0; if (content_type_header[L-1] == '\r') content_type_header[--L] = 0; ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator); PR_Free(content_type_header); if (!ct2) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } content_type_header = ct2; } // Now write out the Content-Type header... NS_ASSERTION(content_type_header && *content_type_header, "null ptr"); PUSH(content_type_header); PR_Free(content_type_header); content_type_header = 0; /* ...followed by all of the other headers that refer to the body of the message (Content-Transfer-Encoding, Content-Dispositon, etc.) */ if (content_headers) { PUSH(content_headers); PR_Free(content_headers); content_headers = 0; } } PUSH(CRLF); // A blank line, to mark the end of headers. m_firstBlock = true; /* only convert if we need to tag charset */ m_needIntlConversion = mime_type_needs_charset(m_type); if (m_buffer) { status = PushBody(m_buffer, PL_strlen(m_buffer)); if (status < 0) goto FAIL; } else if (m_file) { nsCOMPtr<nsIInputStream> inputStream; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), m_file); if (NS_FAILED(rv)) { // mysteriously disappearing? nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsMsgBuildMessageWithTmpFile(m_file, error_msg); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false); } status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE; goto FAIL; } nsCString curLine; bool more = true; /* Kludge to avoid having to allocate memory on the toy computers... */ if (!mime_mailto_stream_read_buffer) { mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE); if (!mime_mailto_stream_read_buffer) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } char *buffer = mime_mailto_stream_read_buffer; if (m_strip_sensitive_headers) { // We are attaching a message, so we should be careful to // strip out certain sensitive internal header fields. bool skipping = false; nsLineBuffer<char> *lineBuffer; rv = NS_InitLineBuffer(&lineBuffer); NS_ENSURE_SUCCESS(rv, rv); while (more) { // NS_ReadLine doesn't return line termination chars. rv = NS_ReadLine(inputStream.get(), lineBuffer, curLine, &more); curLine.Append(CRLF); char *line = (char *) curLine.get(); if (skipping) { if (*line == ' ' || *line == '\t') continue; else skipping = false; } if (!PL_strncasecmp(line, "From -", 6) || !PL_strncasecmp(line, "BCC:", 4) || !PL_strncasecmp(line, "FCC:", 4) || !PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) || !PL_strncasecmp(line, "Lines:", 6) || !PL_strncasecmp(line, "Status:", 7) || !PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) || !PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) || !PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */ { skipping = true; continue; } PUSH(line); if (curLine.Length() == 2) { nsCOMPtr <nsISeekableStream> seekableStream = do_QueryInterface(inputStream); // seek back the amount of data left in the line buffer... seekableStream->Seek(nsISeekableStream::NS_SEEK_CUR, lineBuffer->start - lineBuffer->end); break; // Now can do normal reads for the body. } } PR_Free(lineBuffer); } while (status >= 0) { PRUint32 bytesRead; nsresult rv = inputStream->Read(buffer, MIME_BUFFER_SIZE, &bytesRead); if (NS_FAILED(rv)) { nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsMsgBuildMessageWithFile(m_file, error_msg); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false); status = NS_MSG_UNABLE_TO_OPEN_FILE; goto FAIL; } } status = PushBody(buffer, bytesRead); if (status < 0) goto FAIL; if (bytesRead < MIME_BUFFER_SIZE) break; } } if (m_encoder_data) { status = MIME_EncoderDestroy(m_encoder_data, false); m_encoder_data = nsnull; needToWriteCRLFAfterEncodedBody = !m_parent; if (status < 0) goto FAIL; } // // Ok, from here we loop and drive the the output of all children // for this message. // if (m_numchildren > 0) { bool writeSeparator = true; for (int i = 0 ; i < m_numchildren ; i ++) { if (writeSeparator) { PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH(CRLF); } status = m_children[i]->Write(); if (status < 0) goto FAIL; if (status == SKIP_EMPTY_PART) writeSeparator = false; else writeSeparator = true; } PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH("--"); PUSH(CRLF); } else if (needToWriteCRLFAfterEncodedBody) PUSH(CRLF); FAIL: PR_FREEIF(separator); return status; }
nsresult nsMsgComposeSecure::MimeFinishMultipartSigned (bool aOuter, nsIMsgSendReport *sendReport) { int status; nsresult rv; nsCOMPtr<nsICMSMessage> cinfo = do_CreateInstance(NS_CMSMESSAGE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsICMSEncoder> encoder = do_CreateInstance(NS_CMSENCODER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); char * header = nsnull; nsCOMPtr<nsIStringBundleService> bundleSvc = mozilla::services::GetStringBundleService(); NS_ENSURE_TRUE(bundleSvc, NS_ERROR_UNEXPECTED); nsCOMPtr<nsIStringBundle> sMIMEBundle; nsString mime_smime_sig_content_desc; bundleSvc->CreateBundle(SMIME_STRBUNDLE_URL, getter_AddRefs(sMIMEBundle)); if (!sMIMEBundle) return NS_ERROR_FAILURE; sMIMEBundle->GetStringFromName(NS_LITERAL_STRING("mime_smimeSignatureContentDesc").get(), getter_Copies(mime_smime_sig_content_desc)); NS_ConvertUTF16toUTF8 sig_content_desc_utf8(mime_smime_sig_content_desc); /* Compute the hash... */ nsCAutoString hashString; mDataHash->Finish(false, hashString); mDataHash = 0; status = PR_GetError(); if (status < 0) goto FAIL; /* Write out the headers for the signature. */ PRUint32 L; header = PR_smprintf(CRLF "--%s" CRLF "Content-Type: " APPLICATION_PKCS7_SIGNATURE "; name=\"smime.p7s\"" CRLF "Content-Transfer-Encoding: " ENCODING_BASE64 CRLF "Content-Disposition: attachment; " "filename=\"smime.p7s\"" CRLF "Content-Description: %s" CRLF CRLF, mMultipartSignedBoundary, sig_content_desc_utf8.get()); if (!header) { rv = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } L = strlen(header); if (aOuter) { /* If this is the outer block, write it to the file. */ PRUint32 n; rv = mStream->Write(header, L, &n); if (NS_FAILED(rv) || n < L) { rv = MK_MIME_ERROR_WRITING_FILE; } } else { /* If this is an inner block, feed it through the crypto stream. */ rv = MimeCryptoWriteBlock (header, L); } PR_Free(header); /* Create the signature... */ PR_ASSERT(mHashType == nsICryptoHash::SHA1); PR_ASSERT (mSelfSigningCert); PR_SetError(0,0); rv = cinfo->CreateSigned(mSelfSigningCert, mSelfEncryptionCert, (unsigned char*)hashString.get(), hashString.Length()); if (NS_FAILED(rv)) { SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get()); goto FAIL; } /* Initialize the base64 encoder for the signature data. */ PR_ASSERT(!mSigEncoderData); mSigEncoderData = MIME_B64EncoderInit((aOuter ? mime_encoder_output_fn : mime_nested_encoder_output_fn), this); if (!mSigEncoderData) { rv = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } /* Write out the signature. */ PR_SetError(0,0); rv = encoder->Start(cinfo, mime_crypto_write_base64, mSigEncoderData); if (NS_FAILED(rv)) { SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get()); goto FAIL; } // We're not passing in any data, so no update needed. rv = encoder->Finish(); if (NS_FAILED(rv)) { SetError(sendReport, NS_LITERAL_STRING("ErrorCanNotSign").get()); goto FAIL; } /* Shut down the sig's base64 encoder. */ rv = MIME_EncoderDestroy(mSigEncoderData, false); mSigEncoderData = 0; if (NS_FAILED(rv)) { goto FAIL; } /* Now write out the terminating boundary. */ { PRUint32 L; char *header = PR_smprintf(CRLF "--%s--" CRLF, mMultipartSignedBoundary); PR_Free(mMultipartSignedBoundary); mMultipartSignedBoundary = 0; if (!header) { rv = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } L = strlen(header); if (aOuter) { /* If this is the outer block, write it to the file. */ PRUint32 n; rv = mStream->Write(header, L, &n); if (NS_FAILED(rv) || n < L) rv = MK_MIME_ERROR_WRITING_FILE; } else { /* If this is an inner block, feed it through the crypto stream. */ rv = MimeCryptoWriteBlock (header, L); } } FAIL: return rv; }
int nsMsgSendPart::Write() { int status = 0; char *separator = nsnull; PRBool needToWriteCRLFAfterEncodedBody = PR_FALSE; #define PUSHLEN(str, length) \ do { \ status = mime_write_message_body(m_state, str, length); \ if (status < 0) goto FAIL; \ } while (0) \ #define PUSH(str) PUSHLEN(str, PL_strlen(str)) // rhp: Suppress the output of parts that are empty! if ( (m_parent) && (m_numchildren == 0) && ( (!m_buffer) || (!*m_buffer) ) && (!m_filespec) && (!m_mainpart) ) return SKIP_EMPTY_PART; if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) { if (m_filespec) { // The "insert HTML links" code requires a memory buffer, // so read the file into memory. NS_ASSERTION(m_buffer == nsnull, "not-null buffer"); PRInt32 length = 0; if (m_filespec->Valid()) length = m_filespec->GetFileSize(); m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1)); if (m_buffer) { nsInputFileStream file(*m_filespec); if (file.is_open()) { length = file.read(m_buffer, length); file.close(); m_buffer[length] = '\0'; } else PR_Free(m_buffer); } } } if (m_parent && m_parent->m_type && !PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) && m_type && (!PL_strcasecmp(m_type, MESSAGE_RFC822) || !PL_strcasecmp(m_type, MESSAGE_NEWS))) { // If we're in a multipart/digest, and this document is of type // message/rfc822, then it's appropriate to emit no headers. // } else { char *message_headers = 0; char *content_headers = 0; char *content_type_header = 0; status = divide_content_headers(m_other, &message_headers, &content_headers, &content_type_header); if (status < 0) goto FAIL; /* First, write out all of the headers that refer to the message itself (From, Subject, MIME-Version, etc.) */ if (message_headers) { PUSH(message_headers); PR_Free(message_headers); message_headers = 0; } /* Now allow the crypto library to (potentially) insert some text (it may want to wrap the body in an envelope.) */ if (!m_parent) { status = m_state->BeginCryptoEncapsulation(); if (status < 0) goto FAIL; } /* Now make sure there's a Content-Type header. */ if (!content_type_header) { NS_ASSERTION(m_type && *m_type, "null ptr"); PRBool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN); if (needsCharset) { content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF, (m_type ? m_type : TEXT_PLAIN), m_charset_name); } else content_type_header = PR_smprintf("Content-Type: %s" CRLF, (m_type ? m_type : TEXT_PLAIN)); if (!content_type_header) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } /* If this is a compound object, tack a boundary string onto the Content-Type header. this */ if (m_numchildren > 0) { int L; char *ct2; NS_ASSERTION(m_type, "null ptr"); if (!separator) { separator = mime_make_separator(""); if (!separator) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } L = PL_strlen(content_type_header); if (content_type_header[L-1] == nsCRT::LF) content_type_header[--L] = 0; if (content_type_header[L-1] == nsCRT::CR) content_type_header[--L] = 0; ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator); PR_Free(content_type_header); if (!ct2) { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } content_type_header = ct2; } // Now write out the Content-Type header... NS_ASSERTION(content_type_header && *content_type_header, "null ptr"); PUSH(content_type_header); PR_Free(content_type_header); content_type_header = 0; /* ...followed by all of the other headers that refer to the body of the message (Content-Transfer-Encoding, Content-Dispositon, etc.) */ if (content_headers) { PUSH(content_headers); PR_Free(content_headers); content_headers = 0; } } PUSH(CRLF); // A blank line, to mark the end of headers. m_firstBlock = PR_TRUE; /* only convert if we need to tag charset */ m_needIntlConversion = mime_type_needs_charset(m_type); if (m_buffer) { status = PushBody(m_buffer, PL_strlen(m_buffer)); if (status < 0) goto FAIL; } else if (m_filespec) { nsInputFileStream myStream(*m_filespec); if (!myStream.is_open()) { // mysteriously disappearing? nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsAutoString path; NS_CopyNativeToUnicode( nsDependentCString(m_filespec->GetNativePathCString()), path); nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE); } status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE; goto FAIL; } /* Kludge to avoid having to allocate memory on the toy computers... */ if (!mime_mailto_stream_read_buffer) { mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE); if (!mime_mailto_stream_read_buffer) { status = NS_ERROR_OUT_OF_MEMORY; goto FAIL; } } char *buffer = mime_mailto_stream_read_buffer; if (m_strip_sensitive_headers) { // We are attaching a message, so we should be careful to // strip out certain sensitive internal header fields. PRBool skipping = PR_FALSE; while (1) { char *line; if (myStream.eof()) line = nsnull; else { buffer[0] = '\0'; myStream.readline(buffer, MIME_BUFFER_SIZE-3); line = buffer; } if (!line) break; /* EOF */ if (skipping) { if (*line == ' ' || *line == '\t') continue; else skipping = PR_FALSE; } int hdrLen = PL_strlen(buffer); if ((hdrLen < 2) || (buffer[hdrLen-2] != nsCRT::CR)) { // if the line doesn't end with CRLF, // ... make it end with CRLF. if ( (hdrLen == 0) || ((buffer[hdrLen-1] != nsCRT::CR) && (buffer[hdrLen-1] != nsCRT::LF)) ) hdrLen++; buffer[hdrLen-1] = '\015'; buffer[hdrLen] = '\012'; buffer[hdrLen+1] = '\0'; } if (!PL_strncasecmp(line, "From -", 6) || !PL_strncasecmp(line, "BCC:", 4) || !PL_strncasecmp(line, "FCC:", 4) || !PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) || !PL_strncasecmp(line, "Lines:", 6) || !PL_strncasecmp(line, "Status:", 7) || !PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) || !PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) || !PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) || !PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */ { skipping = PR_TRUE; continue; } PUSH(line); if (*line == nsCRT::CR || *line == nsCRT::LF) { break; // Now can do normal reads for the body. } } } while (!myStream.eof()) { if ((status = myStream.read(buffer, MIME_BUFFER_SIZE)) < 0) { nsCOMPtr<nsIMsgSendReport> sendReport; m_state->GetSendReport(getter_AddRefs(sendReport)); if (sendReport) { nsAutoString error_msg; nsAutoString path; NS_CopyNativeToUnicode(nsDependentCString(m_filespec->GetNativePathCString()), path); nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_FILE, error_msg, &path, nsnull); sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE); status = NS_MSG_UNABLE_TO_OPEN_FILE; goto FAIL; } } status = PushBody(buffer, status); if (status < 0) goto FAIL; } } if (m_encoder_data) { status = MIME_EncoderDestroy(m_encoder_data, PR_FALSE); m_encoder_data = nsnull; needToWriteCRLFAfterEncodedBody = !m_parent; if (status < 0) goto FAIL; } // // Ok, from here we loop and drive the the output of all children // for this message. // if (m_numchildren > 0) { PRBool writeSeparator = PR_TRUE; for (int i = 0 ; i < m_numchildren ; i ++) { if (writeSeparator) { PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH(CRLF); } status = m_children[i]->Write(); if (status < 0) goto FAIL; if (status == SKIP_EMPTY_PART) writeSeparator = PR_FALSE; else writeSeparator = PR_TRUE; } PUSH(CRLF); PUSH("--"); PUSH(separator); PUSH("--"); PUSH(CRLF); } else if (needToWriteCRLFAfterEncodedBody) PUSH(CRLF); FAIL: PR_FREEIF(separator); return status; }