diff --git a/mailnews/compose/build/nsMsgCompFactory.cpp b/mailnews/compose/build/nsMsgCompFactory.cpp index bc793be8f6c..c87ff7ffa67 100644 --- a/mailnews/compose/build/nsMsgCompFactory.cpp +++ b/mailnews/compose/build/nsMsgCompFactory.cpp @@ -295,7 +295,7 @@ extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char* rv = compMgr->RegisterComponent(kCMsgSendLaterCID, "Message Compose Send Later", - "Xcomponent://netscape/messengercompose/sendlater", + "component://netscape/messengercompose/sendlater", path, PR_TRUE, PR_TRUE); if (NS_FAILED(rv)) finalResult = rv; @@ -322,7 +322,7 @@ extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char* // For Drafts... rv = compMgr->RegisterComponent(kMsgDraftCID, "Message Drafts", - "Xcomponent://netscape/messengercompose/drafts", + "component://netscape/messengercompose/drafts", path, PR_TRUE, PR_TRUE); if (NS_FAILED(rv)) finalResult = rv; diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.cpp b/mailnews/compose/src/nsMsgAttachmentHandler.cpp index 64860d3d066..8210b852081 100644 --- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp +++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp @@ -64,6 +64,9 @@ MacGetFileType(nsFileSpec *fs, PRBool *useDefault, char **type, char **encoding) // nsMsgAttachmentHandler::nsMsgAttachmentHandler() { + mMHTMLPart = PR_FALSE; + mPartOrderProcessed = PR_FALSE; + m_charset = NULL; m_override_type = NULL; m_override_encoding = NULL; @@ -683,7 +686,7 @@ nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg) NS_ASSERTION (m_mime_delivery_state->m_attachment_pending_count > 0, "no more pending attachment"); m_mime_delivery_state->m_attachment_pending_count--; - if (status >= 0 && m_mime_delivery_state->m_be_synchronous_p) + if (NS_SUCCEEDED(status) && m_mime_delivery_state->m_be_synchronous_p) { /* Find the next attachment which has not yet been loaded, if any, and start it going. diff --git a/mailnews/compose/src/nsMsgAttachmentHandler.h b/mailnews/compose/src/nsMsgAttachmentHandler.h index e04c7004ebf..bf6c9ebc90c 100644 --- a/mailnews/compose/src/nsMsgAttachmentHandler.h +++ b/mailnews/compose/src/nsMsgAttachmentHandler.h @@ -99,6 +99,9 @@ public: PRBool mDeleteFile; // If this is true, Delete the file...its // NOT the original file! + PRBool mMHTMLPart; // This is true if its an MHTML part, otherwise, FALSE + PRBool mPartOrderProcessed; // This is a flag to see if we processed this in the final sweep + // // Vars for analyzing file data... // diff --git a/mailnews/compose/src/nsMsgCompUtils.cpp b/mailnews/compose/src/nsMsgCompUtils.cpp index 573192772a5..fcbfb9690cf 100644 --- a/mailnews/compose/src/nsMsgCompUtils.cpp +++ b/mailnews/compose/src/nsMsgCompUtils.cpp @@ -758,18 +758,18 @@ mime_generate_headers (nsMsgCompFields *fields, static void GenerateGlobalRandomBytes(unsigned char *buf, PRInt32 len) { - PRBool firstTime = PR_TRUE; - + static PRBool firstTime = PR_TRUE; + if (firstTime) { - /* Seed the random-number generator with current time so that - * the numbers will be different every time we run. */ - PRInt32 aTime; - LL_L2I(aTime, PR_Now()); - srand( (unsigned)aTime ); - firstTime = PR_FALSE; + // Seed the random-number generator with current time so that + // the numbers will be different every time we run. + PRInt32 aTime; + LL_L2I(aTime, PR_Now()); + srand( (unsigned)aTime ); + firstTime = PR_FALSE; } - + for( PRInt32 i = 0; i < len; i++ ) buf[i] = rand() % 10; } diff --git a/mailnews/compose/src/nsMsgCompose.cpp b/mailnews/compose/src/nsMsgCompose.cpp index 689f6f91da3..188058d71de 100644 --- a/mailnews/compose/src/nsMsgCompose.cpp +++ b/mailnews/compose/src/nsMsgCompose.cpp @@ -35,6 +35,7 @@ #include "CNavDTD.h" #include "nsMsgCompUtils.h" #include "nsMsgComposeStringBundle.h" +#include "nsMsgSend.h" // XXX temporary so we can use the current identity hack -alecf #include "nsIMsgMailSession.h" @@ -141,7 +142,6 @@ nsMsgCompose::~nsMsgCompose() /* the following macro actually implement addref, release and query interface for our component. */ NS_IMPL_ISUPPORTS(nsMsgCompose, nsCOMTypeInfo::GetIID()); - nsresult nsMsgCompose::SetQuotingToFollow(PRBool aVal) { @@ -262,7 +262,7 @@ nsresult nsMsgCompose::_SendMsg(MSG_DeliverMode deliverMode, printf("----------------------------\n"); #endif //DEBUG - nsIMsgSend *tMsgComp = new nsMsgComposeAndSend(); + nsMsgComposeAndSend *tMsgComp = new nsMsgComposeAndSend(); if (!tMsgComp) return NS_ERROR_OUT_OF_MEMORY; @@ -806,7 +806,7 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIChannel * /* aChanne tempFile.close(); // Now load the URL... - nsString urlStr = mComposeObj->mTempComposeFileSpec->GetNativePathCString(); + nsString urlStr = nsMsgPlatformFileToURL(mComposeObj->mTempComposeFileSpec->GetNativePathCString()); nsIEditorShell *editor; mComposeObj->GetEditor(&editor); @@ -928,7 +928,7 @@ void nsMsgCompose::HackToGetBody(PRInt32 what) if (what == 1 && ! m_composeHTML) msgBody += "> "; msgBody += buffer; - msgBody += MSG_LINEBREAK; + msgBody += CRLF; } if (m_composeHTML) @@ -962,22 +962,22 @@ void nsMsgCompose::HackToGetBody(PRInt32 what) if (endBodyOffset == -1) endBodyOffset = lowerMsgBody.Length(); - msgBody.Insert(MSG_LINEBREAK, endBodyOffset); + msgBody.Insert(CRLF, endBodyOffset); if (startBodyOffset == 0) { msgBody.Insert("", endBodyOffset); - msgBody.Insert(MSG_LINEBREAK, endBodyOffset); + msgBody.Insert(CRLF, endBodyOffset); } msgBody.Insert("", endBodyOffset); - msgBody.Insert(MSG_LINEBREAK, endBodyOffset); + msgBody.Insert(CRLF, endBodyOffset); - msgBody.Insert(MSG_LINEBREAK, startBodyOffset); + msgBody.Insert(CRLF, startBodyOffset); msgBody.Insert("
", startBodyOffset); - msgBody.Insert(MSG_LINEBREAK, startBodyOffset); + msgBody.Insert(CRLF, startBodyOffset); if (startBodyOffset == 0) { msgBody.Insert("", startBodyOffset); - msgBody.Insert(MSG_LINEBREAK, startBodyOffset); + msgBody.Insert(CRLF, startBodyOffset); msgBody.Insert("", startBodyOffset); } } @@ -1511,13 +1511,13 @@ nsMsgCompose::ProcessSignature(nsOutputFileStream *aAppendFileStream) tempFile.write(htmlBreak, PL_strlen(htmlBreak)); else { - tempFile.write(MSG_LINEBREAK, MSG_LINEBREAK_LEN); + tempFile.write(CRLF, 2); tempFile.write(dashes, PL_strlen(dashes)); } if (m_composeHTML) tempFile.write(htmlBreak, PL_strlen(htmlBreak)); else - tempFile.write(MSG_LINEBREAK, MSG_LINEBREAK_LEN); + tempFile.write(CRLF, 2); tempFile.write(nsAutoCString(sigData), sigData.Length()); tempFile.close(); @@ -1535,13 +1535,13 @@ nsMsgCompose::ProcessSignature(nsOutputFileStream *aAppendFileStream) if (m_composeHTML) aAppendFileStream->write(htmlBreak, PL_strlen(htmlBreak)); else - aAppendFileStream->write(MSG_LINEBREAK, MSG_LINEBREAK_LEN); + aAppendFileStream->write(CRLF, 2); aAppendFileStream->write(dashes, PL_strlen(dashes)); if (m_composeHTML) aAppendFileStream->write(htmlBreak, PL_strlen(htmlBreak)); else - aAppendFileStream->write(MSG_LINEBREAK, MSG_LINEBREAK_LEN); + aAppendFileStream->write(CRLF, 2); aAppendFileStream->write(nsAutoCString(sigData), sigData.Length()); } diff --git a/mailnews/compose/src/nsMsgCopy.cpp b/mailnews/compose/src/nsMsgCopy.cpp index aec6bdbdab4..af7a88808ca 100644 --- a/mailnews/compose/src/nsMsgCopy.cpp +++ b/mailnews/compose/src/nsMsgCopy.cpp @@ -30,7 +30,10 @@ static NS_DEFINE_CID(kCMsgMailSessionCID, NS_MSGMAILSESSION_CID); // This is the listener class for the copy operation. We have to create this class // to listen for message copy completion and eventually notify the caller //////////////////////////////////////////////////////////////////////////////////// -NS_IMPL_ISUPPORTS(CopyListener, nsCOMTypeInfo::GetIID()); +// RICHIE SHERRY NS_IMPL_ISUPPORTS(CopyListener, nsCOMTypeInfo::GetIID()); +NS_IMPL_ADDREF(CopyListener); +NS_IMPL_RELEASE(CopyListener); +NS_IMPL_QUERY_INTERFACE(CopyListener,nsCOMTypeInfo::GetIID()); CopyListener::CopyListener(void) { @@ -40,7 +43,7 @@ CopyListener::CopyListener(void) CopyListener::~CopyListener(void) { - //this; + this; } nsresult diff --git a/mailnews/compose/src/nsMsgSend.cpp b/mailnews/compose/src/nsMsgSend.cpp index ec58b13c8b5..07373704310 100644 --- a/mailnews/compose/src/nsMsgSend.cpp +++ b/mailnews/compose/src/nsMsgSend.cpp @@ -337,23 +337,16 @@ nsMsgComposeAndSend::GatherMimeAttachments() PRInt32 status; PRUint32 i; char *headers = 0; - char *separator = 0; PRFileDesc *in_file = 0; PRBool multipart_p = PR_FALSE; PRBool plaintext_is_mainbody_p = PR_FALSE; // only using text converted from HTML? char *buffer = 0; char *buffer_tail = 0; char* error_msg = nsnull; - - // to news is true if we have a m_field and we have a Newsgroup and it is not empty - PRBool tonews = PR_FALSE; - if (mCompFields) - { - const char* pstrzNewsgroup = mCompFields->GetNewsgroups(); - if (pstrzNewsgroup && *pstrzNewsgroup) - tonews = PR_TRUE; - } - + PRBool multiPartRelatedWithAttachments = PR_FALSE; + char *attachmentSeparator = nsnull; + char *multipartRelatedSeparator = nsnull; + PRBool tonews; nsMsgSendPart* toppart = nsnull; // The very top most container of the message // that we are going to send. @@ -377,6 +370,49 @@ nsMsgComposeAndSend::GatherMimeAttachments() char *hdrs = 0; PRBool maincontainerISrelatedpart = PR_FALSE; + + // + // First things first! What kind of message is this going to be when it grows up. + // We will need to know this as we start building the message... + // + multiPartRelatedWithAttachments = ( (mMultipartRelatedAttachmentCount > 0) && + (m_attachment_count > mMultipartRelatedAttachmentCount) ); + // If we have any attachments, we generate multipart. + multipart_p = (m_attachment_count > 0); + + // + // Ok, we need to create the separators for the + // multipart message... + // + if (multipart_p) + { + attachmentSeparator = mime_make_separator(""); + if (!attachmentSeparator) + { + status = NS_ERROR_OUT_OF_MEMORY; + goto FAILMEM; + } + + if (multiPartRelatedWithAttachments) + { + multipartRelatedSeparator = mime_make_separator("MPR"); + if (!multipartRelatedSeparator) + { + status = NS_ERROR_OUT_OF_MEMORY; + goto FAILMEM; + } + } + } + + // to news is true if we have a m_field and we have a Newsgroup and it is not empty + tonews = PR_FALSE; + if (mCompFields) + { + const char* pstrzNewsgroup = mCompFields->GetNewsgroups(); + if (pstrzNewsgroup && *pstrzNewsgroup) + tonews = PR_TRUE; + } + status = m_status; if (status < 0) goto FAIL; @@ -566,6 +602,16 @@ nsMsgComposeAndSend::GatherMimeAttachments() mainbody->SetMainPart(PR_TRUE); mainbody->SetType(m_attachment1_type ? m_attachment1_type : TEXT_PLAIN); + if (multipart_p) + { + // Need to do this only for complex messages... + // Since the toppart is the body of the MHTML message, this needs the multipart + // related separator + // + mainbody->SetPartSeparator(attachmentSeparator); + mainbody->SetMultipartRelatedFlag(PR_TRUE); + } + NS_ASSERTION(mainbody->GetBuffer() == nsnull, "not-null buffer"); status = mainbody->SetBuffer(m_attachment1_body ? m_attachment1_body : " "); if (status < 0) @@ -630,6 +676,13 @@ nsMsgComposeAndSend::GatherMimeAttachments() mainbody = maincontainer; mainbody->SetMainPart(PR_TRUE); + // + // Need to do this only for complex messages... + // Since the toppart is the body of the MHTML message, this needs the multipart + // related separator + // + mainbody->SetPartSeparator(attachmentSeparator); + mainbody->SetMultipartRelatedFlag(PR_TRUE); } if (m_plaintext) @@ -647,7 +700,21 @@ nsMsgComposeAndSend::GatherMimeAttachments() status = plainpart->SetFile(m_plaintext->mFileSpec); if (status < 0) goto FAIL; - m_plaintext->AnalyzeSnarfedFile(); // look for 8 bit text, long lines, etc. + + if (multipart_p) + { + // Need to do this only for complex messages... + // Since the toppart is the body of the MHTML message, this needs the multipart + // related separator + // + if (multiPartRelatedWithAttachments) + plainpart->SetPartSeparator(multipartRelatedSeparator); + else + plainpart->SetPartSeparator(attachmentSeparator); + plainpart->SetMultipartRelatedFlag(PR_TRUE); + } + + m_plaintext->AnalyzeSnarfedFile(); // look for 8 bit text, long lines, etc. m_plaintext->PickEncoding(mCompFields->GetCharacterSet()); hdrs = mime_generate_attachment_headers(m_plaintext->m_type, m_plaintext->m_encoding, @@ -667,7 +734,8 @@ nsMsgComposeAndSend::GatherMimeAttachments() if (status < 0) goto FAIL; - if (mCompFields->GetUseMultipartAlternative()) { + if (mCompFields->GetUseMultipartAlternative()) + { nsMsgSendPart* htmlpart = maincontainer; maincontainer = new nsMsgSendPart(this); if (!maincontainer) @@ -675,7 +743,18 @@ nsMsgComposeAndSend::GatherMimeAttachments() status = maincontainer->SetType(MULTIPART_ALTERNATIVE); if (status < 0) goto FAIL; - status = maincontainer->AddChild(plainpart); + + if (multipart_p) + { + // Need to do this only for complex messages... + // Since the toppart is the body of the MHTML message, this needs the multipart + // related separator + // + maincontainer->SetPartSeparator(attachmentSeparator); + maincontainer->SetMultipartRelatedFlag(PR_TRUE); + } + + status = maincontainer->AddChild(plainpart); if (status < 0) goto FAIL; status = maincontainer->AddChild(htmlpart); @@ -718,20 +797,15 @@ nsMsgComposeAndSend::GatherMimeAttachments() } } - // ###tw This used to be this more complicated thing, but for now, if it we - // have any attachments, we generate multipart. - // multipart_p = (m_attachment_count > 1 || - // (m_attachment_count == 1 && - // m_attachment1_body_length > 0)); - multipart_p = (m_attachment_count > 0); - if (multipart_p) { toppart = new nsMsgSendPart(this); if (!toppart) goto FAILMEM; - if (mMultipartRelatedAttachmentCount > 0) + // This is JUST multpart related! + if ( (mMultipartRelatedAttachmentCount > 0) && + (m_attachment_count == mMultipartRelatedAttachmentCount) ) status = toppart->SetType(MULTIPART_RELATED); else status = toppart->SetType(m_digest_p ? MULTIPART_DIGEST : MULTIPART_MIXED); @@ -741,21 +815,57 @@ nsMsgComposeAndSend::GatherMimeAttachments() status = toppart->AddChild(maincontainer); if (status < 0) goto FAIL; + if (!m_crypto_closure) { - status = toppart->SetBuffer(MIME_MULTIPART_BLURB); - if (status < 0) - goto FAIL; + // This is a multi-part message in MIME format. + // --------------C428B2F3369F2FBEBDD59897 + // Content-Type: multipart/related; + // boundary="------------ACE298C3793AC965A3B99725" + if (multiPartRelatedWithAttachments) + { + char *newLine = PR_smprintf("%s%s--%s%sContent-Type: %s;%s boundary=\"%s\"%s%s", + MIME_MULTIPART_BLURB, CRLF, + attachmentSeparator, CRLF, + MULTIPART_RELATED, CRLF, + multipartRelatedSeparator, CRLF, CRLF); + status = toppart->SetBuffer(newLine); + PR_FREEIF(newLine); + } + else + { + status = toppart->SetBuffer(MIME_MULTIPART_BLURB); + } + + if (status < 0) + goto FAIL; } + + if (multiPartRelatedWithAttachments) + { + toppart->SetPartSeparator(multipartRelatedSeparator); + maincontainer->SetPartSeparator(multipartRelatedSeparator); + } + else + { + toppart->SetPartSeparator(attachmentSeparator); + maincontainer->SetPartSeparator(attachmentSeparator); + } + + toppart->SetMultipartRelatedFlag(PR_TRUE); + maincontainer->SetMultipartRelatedFlag(PR_TRUE); } else + { + maincontainer->SetPartSeparator(attachmentSeparator); + maincontainer->SetMultipartRelatedFlag(PR_FALSE); toppart = maincontainer; + } /* Write out the message headers. */ - headers = mime_generate_headers (mCompFields, - mCompFields->GetCharacterSet(), - m_deliver_mode); + headers = mime_generate_headers (mCompFields, mCompFields->GetCharacterSet(), + m_deliver_mode); if (!headers) goto FAILMEM; @@ -838,12 +948,34 @@ nsMsgComposeAndSend::GatherMimeAttachments() if (status < 0) goto FAIL; - - /* Set up the subsequent parts. - */ - if (m_attachment_count > 0) + // + // Ok, I think I can do the magic here and make MHTML messages with + // attachments work. This is where we set up the subsequent parts, but + // what we need to do in our case is process all of the attachments in + // two blocks (i.e. multipart/related then the rest of the attachments with + // unique separators) + // + // So an MHTML message with attachments should look like the following: + // + // (In the main header) + // Content-Type: multipart/mixed; + // boundary="------------C428B2F3369F2FBEBDD59897" + // + // (then the first thing after the headers should be: + // + // This is a multi-part message in MIME format. + // --------------C428B2F3369F2FBEBDD59897 + // Content-Type: multipart/related; + // boundary="------------ACE298C3793AC965A3B99725" + // + // all multipart related parts... + // + // --------------C428B2F3369F2FBEBDD59897 {main message separator} + // rest of the attached parts + // + if (m_attachment_count > 0) { - /* Kludge to avoid having to allocate memory on the toy computers... */ + // 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); buffer = mime_mailto_stream_read_buffer; @@ -851,85 +983,51 @@ nsMsgComposeAndSend::GatherMimeAttachments() goto FAILMEM; buffer_tail = buffer; + // do 2 loops here and count up the mpart related + // and total count + PRInt32 multipartPartFound = 0; + PRInt32 attachmentFound = 0; + + // First, gather all of the multipart related parts for this message! for (i = 0; i < m_attachment_count; i++) - { - nsMsgAttachmentHandler *ma = &m_attachments[i]; - hdrs = 0; + { + nsMsgAttachmentHandler *ma = &m_attachments[i]; + if (!ma->mMHTMLPart) + continue; - nsMsgSendPart* part = nsnull; + if (multiPartRelatedWithAttachments) + multipartPartFound += PreProcessPart(ma, multipartRelatedSeparator, toppart); + else + multipartPartFound += PreProcessPart(ma, attachmentSeparator, toppart); + } - // If at this point we *still* don't have an content-type, then - // we're never going to get one. - if (ma->m_type == nsnull) { - ma->m_type = PL_strdup(UNKNOWN_CONTENT_TYPE); - if (ma->m_type == nsnull) - goto FAILMEM; - } + // Now, gather all of the attachments! + for (i = 0; i < m_attachment_count; i++) + { + nsMsgAttachmentHandler *ma = &m_attachments[i]; + if (ma->mMHTMLPart) + continue; - ma->PickEncoding (mCompFields->GetCharacterSet()); - - part = new nsMsgSendPart(this); - if (!part) - goto FAILMEM; - status = toppart->AddChild(part); - if (status < 0) - goto FAIL; - status = part->SetType(ma->m_type); - if (status < 0) - goto FAIL; - - nsXPIDLCString turl; - ma->mURL->GetSpec(getter_Copies(turl)); - hdrs = mime_generate_attachment_headers (ma->m_type, ma->m_encoding, - ma->m_description, - ma->m_x_mac_type, - ma->m_x_mac_creator, - ma->m_real_name, - turl, - m_digest_p, - ma, - ma->m_charset, // rhp - this needs to be the charset we determine from - // the file or none at all! - ma->m_content_id); - if (!hdrs) - goto FAILMEM; - - status = part->SetOtherHeaders(hdrs); - PR_FREEIF(hdrs); - if (status < 0) - goto FAIL; - status = part->SetFile(ma->mFileSpec); - if (status < 0) - goto FAIL; - if (ma->m_encoder_data) { - status = part->SetEncoderData(ma->m_encoder_data); - if (status < 0) - goto FAIL; - ma->m_encoder_data = nsnull; - } - - ma->m_current_column = 0; - - if (ma->m_type && - (!PL_strcasecmp (ma->m_type, MESSAGE_RFC822) || - !PL_strcasecmp (ma->m_type, MESSAGE_NEWS))) { - status = part->SetStripSensitiveHeaders(PR_TRUE); - if (status < 0) - goto FAIL; - } - } + attachmentFound += PreProcessPart(ma, attachmentSeparator, toppart); + } } // OK, now actually write the structure we've carefully built up. - status = toppart->Write(); + // Pass in TRUE if this is a multipart message WITH Attachments, + // false if not + status = toppart->Write(multiPartRelatedWithAttachments, + attachmentSeparator, + multipartRelatedSeparator); if (status < 0) goto FAIL; HJ45609 - if (mOutputFile) { + if (mOutputFile) + { /* If we don't do this check...ZERO length files can be sent */ - if (mOutputFile->failed()) { + if (mOutputFile->failed()) + { status = NS_MSG_ERROR_WRITING_FILE; goto FAIL; } @@ -970,9 +1068,12 @@ FAIL: mainbody = nsnull; maincontainer = nsnull; + PR_FREEIF(multipartRelatedSeparator); + PR_FREEIF(attachmentSeparator); + PR_FREEIF(headers); - PR_FREEIF(separator); - if (in_file) { + if (in_file) + { PR_Close (in_file); in_file = nsnull; } @@ -994,6 +1095,90 @@ FAILMEM: goto FAIL; } +PRInt32 +nsMsgComposeAndSend::PreProcessPart(nsMsgAttachmentHandler *ma, + char *aSeparator, + nsMsgSendPart *toppart) // The very top most container of the message +{ + nsresult status; + char *hdrs = 0; + nsMsgSendPart *part = nsnull; + + if (ma->mPartOrderProcessed) + return 0; + + ma->mPartOrderProcessed = PR_TRUE; + + // If at this point we *still* don't have an content-type, then + // we're never going to get one. + if (ma->m_type == nsnull) + { + ma->m_type = PL_strdup(UNKNOWN_CONTENT_TYPE); + if (ma->m_type == nsnull) + return 0; + } + + ma->PickEncoding (mCompFields->GetCharacterSet()); + + part = new nsMsgSendPart(this); + if (!part) + return 0; + status = toppart->AddChild(part); + if (status < 0) + return 0; + status = part->SetType(ma->m_type); + if (status < 0) + return 0; + + // Set this so we know what to do with the separator when writing + // it to disk... + part->SetMultipartRelatedFlag(ma->mMHTMLPart); + part->SetPartSeparator(aSeparator); + + nsXPIDLCString turl; + ma->mURL->GetSpec(getter_Copies(turl)); + hdrs = mime_generate_attachment_headers (ma->m_type, ma->m_encoding, + ma->m_description, + ma->m_x_mac_type, + ma->m_x_mac_creator, + ma->m_real_name, + turl, + m_digest_p, + ma, + ma->m_charset, // rhp - this needs to be the charset we determine from + // the file or none at all! + ma->m_content_id); + if (!hdrs) + return 0; + + status = part->SetOtherHeaders(hdrs); + PR_FREEIF(hdrs); + if (status < 0) + return 0; + status = part->SetFile(ma->mFileSpec); + if (status < 0) + return 0; + if (ma->m_encoder_data) + { + status = part->SetEncoderData(ma->m_encoder_data); + if (status < 0) + return 0; + ma->m_encoder_data = nsnull; + } + + ma->m_current_column = 0; + + if (ma->m_type && + (!PL_strcasecmp (ma->m_type, MESSAGE_RFC822) || + !PL_strcasecmp (ma->m_type, MESSAGE_NEWS))) { + status = part->SetStripSensitiveHeaders(PR_TRUE); + if (status < 0) + return 0; + } + + return 1; +} + #if defined(XP_MAC) && defined(DEBUG) // Compiler runs out of registers for the debug build. @@ -1016,7 +1201,7 @@ HJ91531 int -mime_write_message_body (nsMsgComposeAndSend *state, char *buf, PRInt32 size) +mime_write_message_body(nsMsgComposeAndSend *state, char *buf, PRInt32 size) { HJ62011 @@ -1031,7 +1216,7 @@ mime_write_message_body (nsMsgComposeAndSend *state, char *buf, PRInt32 size) } int -mime_encoder_output_fn (const char *buf, PRInt32 size, void *closure) +mime_encoder_output_fn(const char *buf, PRInt32 size, void *closure) { nsMsgComposeAndSend *state = (nsMsgComposeAndSend *) closure; return mime_write_message_body (state, (char *) buf, size); @@ -1145,6 +1330,9 @@ PRUint32 i; // Reset this structure to null! nsCRT::memset(&attachment, 0, sizeof(nsMsgAttachmentData)); + // MUST set this to get placed in the correct part of the message + m_attachments[i].mMHTMLPart = PR_TRUE; + locCount++; m_attachments[i].mDeleteFile = PR_TRUE; m_attachments[i].m_done = PR_FALSE; @@ -1398,7 +1586,7 @@ nsMsgComposeAndSend::CountCompFieldAttachments() mCompFieldLocalAttachments++; #ifdef NS_DEBUG printf("Counting LOCAL attachment %d: %s\n", - mCompFieldLocalAttachments, str); + mCompFieldLocalAttachments, str.GetBuffer()); #endif } else // This is a remote URL... @@ -1406,7 +1594,7 @@ nsMsgComposeAndSend::CountCompFieldAttachments() mCompFieldRemoteAttachments++; #ifdef NS_DEBUG printf("Counting REMOTE attachment %d: %s\n", - mCompFieldRemoteAttachments, str); + mCompFieldRemoteAttachments, str.GetBuffer()); #endif } @@ -1455,7 +1643,7 @@ nsMsgComposeAndSend::AddCompFieldLocalAttachments() if (str.Compare("file://", PR_TRUE, 7) == 0) { #ifdef NS_DEBUG - printf("Adding LOCAL attachment %d: %s\n", newLoc, str); + printf("Adding LOCAL attachment %d: %s\n", newLoc, str.GetBuffer()); #endif // // Now we have to setup the m_attachments entry for the file:// @@ -1558,7 +1746,7 @@ nsMsgComposeAndSend::AddCompFieldRemoteAttachments(PRUint32 aStartLocation, if (str.Compare("file://", PR_TRUE, 7) != 0) { #ifdef NS_DEBUG - printf("Adding REMOTE attachment %d: %s\n", newLoc, str); + printf("Adding REMOTE attachment %d: %s\n", newLoc, str.GetBuffer()); #endif m_attachments[newLoc].mDeleteFile = PR_TRUE; @@ -3021,7 +3209,7 @@ nsMsgGetEnvelopeLine(void) // PL_strcpy(result, "From - "); PL_strcpy(result + 7, buffer); - PL_strcpy(result + 7 + 24, MSG_LINEBREAK); + PL_strcpy(result + 7 + 24, CRLF); return result; } @@ -3146,7 +3334,7 @@ nsMsgComposeAndSend::MimeDoFCC(nsFileSpec *input_file, flags |= MSG_FLAG_READ; if (mode == nsMsgQueueForLater) flags |= MSG_FLAG_QUEUED; - buf = PR_smprintf(X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, flags); + buf = PR_smprintf(X_MOZILLA_STATUS_FORMAT CRLF, flags); if (buf) { PRInt32 len = PL_strlen(buf); @@ -3162,7 +3350,7 @@ nsMsgComposeAndSend::MimeDoFCC(nsFileSpec *input_file, PRUint32 flags2 = 0; if (mode == nsMsgSaveAsTemplate) flags2 |= MSG_FLAG_TEMPLATE; - buf = PR_smprintf(X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, flags2); + buf = PR_smprintf(X_MOZILLA_STATUS2_FORMAT CRLF, flags2); if (buf) { PRInt32 len = PL_strlen(buf); @@ -3213,7 +3401,7 @@ nsMsgComposeAndSend::MimeDoFCC(nsFileSpec *input_file, goto FAIL; } - PR_snprintf(buf, L-1, "FCC: %s" MSG_LINEBREAK, fcc_header); + PR_snprintf(buf, L-1, "FCC: %s" CRLF, fcc_header); PRInt32 len = PL_strlen(buf); n = tempOutfile.write(buf, len); @@ -3239,7 +3427,7 @@ nsMsgComposeAndSend::MimeDoFCC(nsFileSpec *input_file, goto FAIL; } - PR_snprintf(buf, L-1, "BCC: %s" MSG_LINEBREAK, bcc_header); + PR_snprintf(buf, L-1, "BCC: %s" CRLF, bcc_header); PRInt32 len = PL_strlen(buf); n = tempOutfile.write(buf, len); if (n != len) @@ -3279,7 +3467,7 @@ nsMsgComposeAndSend::MimeDoFCC(nsFileSpec *input_file, if ((host_and_port && *host_and_port) || !secure_p) { - char *line = PR_smprintf(X_MOZILLA_NEWSHOST ": %s%s" MSG_LINEBREAK, + char *line = PR_smprintf(X_MOZILLA_NEWSHOST ": %s%s" CRLF, host_and_port ? host_and_port : "", secure_p ? "/secure" : ""); PR_FREEIF(orig_hap); diff --git a/mailnews/compose/src/nsMsgSend.h b/mailnews/compose/src/nsMsgSend.h index 132c3e57796..cbd36a3f7c5 100644 --- a/mailnews/compose/src/nsMsgSend.h +++ b/mailnews/compose/src/nsMsgSend.h @@ -280,6 +280,11 @@ public: PRUint32 attachment1_body_length, const char *attachment1_type); + PRInt32 PreProcessPart(nsMsgAttachmentHandler *ma, + char *aSeparator, + nsMsgSendPart *toppart); // The very top most container of the message + // For part processing + //////////////////////////////////////////////////////////////////////////////// // The current nsIMsgSend Interfaces exposed to the world! //////////////////////////////////////////////////////////////////////////////// diff --git a/mailnews/compose/src/nsMsgSendPart.cpp b/mailnews/compose/src/nsMsgSendPart.cpp index 1909d158513..b0284e2aa83 100644 --- a/mailnews/compose/src/nsMsgSendPart.cpp +++ b/mailnews/compose/src/nsMsgSendPart.cpp @@ -58,7 +58,10 @@ nsMsgSendPart::nsMsgSendPart(nsMsgComposeAndSend* state, const char *part_charse m_numchildren = 0; SetMimeDeliveryState(state); - + + mMHTMLPart = PR_FALSE; + mPartSeparator = nsnull; + m_parent = NULL; m_filespec = NULL; m_filetype = (XP_FileType)0; @@ -94,6 +97,30 @@ nsMsgSendPart::~nsMsgSendPart() PR_FREEIF(m_type); } +void +nsMsgSendPart::SetMultipartRelatedFlag(PRBool aFlag) +{ + mMHTMLPart = aFlag; +} + +void +nsMsgSendPart::SetPartSeparator(char *aPartSeparator) +{ + mPartSeparator = aPartSeparator; +} + +char * +nsMsgSendPart::GetPartSeparator() +{ + return mPartSeparator; +} + +PRBool +nsMsgSendPart::IsMultipartRelatedPart() +{ + return mMHTMLPart; +} + int nsMsgSendPart::CopyString(char** dest, const char* src) { NS_ASSERTION(src, "src null"); @@ -120,7 +147,7 @@ int nsMsgSendPart::SetFile(nsFileSpec *filename) int nsMsgSendPart::SetBuffer(const char* buffer) { - NS_ASSERTION(m_buffer == NULL, "not-null m_buffer"); + PR_FREEIF(m_buffer); return CopyString(&m_buffer, buffer); } @@ -343,11 +370,12 @@ itself. (This relies on the fact that all body-related headers begin with (How many header parsers are in this program now?) */ - static int divide_content_headers(const char *headers, - char **message_headers, - char **content_headers, - char **content_type_header) - { +static int +divide_content_headers(const char *headers, + char **message_headers, + char **content_headers, + char **content_type_header) +{ const char *tail; char *message_tail, *content_tail, *type_tail; int L = 0; @@ -460,24 +488,24 @@ itself. (This relies on the fact that all body-related headers begin with return 0; } -extern "C" { - extern char *mime_make_separator(const char *prefix); -} - -int nsMsgSendPart::Write() +int +nsMsgSendPart::Write(PRBool aMultiPartRelatedWithAttachmentsMessage, + char *attachmentSeparator, + char *multipartRelatedSeparator) { - int status = 0; - char *separator = 0; - + int status = 0; + PRBool partOfMPARTMessage; + #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)) - if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) { + if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) + { if (m_filespec) { // The "insert HTML links" code requires a memory buffer, @@ -502,19 +530,21 @@ int nsMsgSendPart::Write() PR_Free(m_buffer); } } + if (m_buffer) { nsCOMPtr myURLUtil; char *tmp = NULL; nsresult res = nsComponentManager::CreateInstance(kCMimeURLUtilsCID, - NULL, nsCOMTypeInfo::GetIID(), - (void **) getter_AddRefs(myURLUtil)); + NULL, nsCOMTypeInfo::GetIID(), + (void **) getter_AddRefs(myURLUtil)); if (!NS_SUCCEEDED(res)) goto FAIL; myURLUtil->ScanHTMLForURLs(m_buffer, &tmp); - if (tmp) { + if (tmp) + { SetBuffer(tmp); PR_Free(tmp); } @@ -525,27 +555,29 @@ int nsMsgSendPart::Write() !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. - */ + !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 { + 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); + &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) { + if (message_headers) + { PUSH(message_headers); PR_Free(message_headers); message_headers = 0; @@ -560,20 +592,20 @@ int nsMsgSendPart::Write() /* Now make sure there's a Content-Type header. */ - if (!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); + 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) { + 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; @@ -582,20 +614,14 @@ int nsMsgSendPart::Write() } /* If this is a compound object, tack a boundary string onto the - Content-Type header. + 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] == LF) @@ -603,10 +629,10 @@ int nsMsgSendPart::Write() if (content_type_header[L-1] == CR) content_type_header[--L] = 0; - ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, - content_type_header, separator); + ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, attachmentSeparator); PR_Free(content_type_header); - if (!ct2) { + if (!ct2) + { if (content_headers) PR_Free(content_headers); status = NS_ERROR_OUT_OF_MEMORY; @@ -616,8 +642,7 @@ int nsMsgSendPart::Write() content_type_header = ct2; } - /* Now write out the Content-Type header... - */ + // 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); @@ -626,28 +651,29 @@ int nsMsgSendPart::Write() /* ...followed by all of the other headers that refer to the body of the message (Content-Transfer-Encoding, Content-Dispositon, etc.) */ - if (content_headers) { + 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); m_intlDocToMailConverter = NULL; - if (m_buffer) { status = PushBody(m_buffer, PL_strlen(m_buffer)); if (status < 0) goto FAIL; } - else if (m_filespec) { + else if (m_filespec) + { nsIOFileStream myStream(*m_filespec); if (!myStream.is_open()) @@ -657,20 +683,21 @@ int nsMsgSendPart::Write() 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) { + 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. - */ + + 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; NS_ASSERTION(MIME_BUFFER_SIZE > 1000, "buffer size out of range"); /* SMTP (RFC821) limit */ @@ -743,35 +770,65 @@ int nsMsgSendPart::Write() } } - if (m_encoder_data) { + if (m_encoder_data) + { status = MIME_EncoderDestroy(m_encoder_data, PR_FALSE); m_encoder_data = NULL; if (status < 0) goto FAIL; } - if (m_numchildren > 0) { - NS_ASSERTION(separator, "Null separator"); - for (int i = 0 ; i < m_numchildren ; i ++) { + // + // Ok, from here we loop and drive the the output of all children + // for this message. Need to do write the correct separator depending + // on what kind of part it is + // + partOfMPARTMessage = PR_TRUE; + if (m_numchildren > 0) + { + for (int i = 0 ; i < m_numchildren ; i ++) + { PUSH(CRLF); PUSH("--"); - PUSH(separator); + + PUSH(m_children[i]->GetPartSeparator()); PUSH(CRLF); - status = m_children[i]->Write(); + status = m_children[i]->Write(aMultiPartRelatedWithAttachmentsMessage, + attachmentSeparator, + multipartRelatedSeparator); if (status < 0) goto FAIL; + + // + // If we are at a part that has a new separator, then + // this is not part of the past the first entry, then we are at the + // end of the multipart related message and we need to + // mark the end of the multipart/related field. + // + if ( (aMultiPartRelatedWithAttachmentsMessage) && + (partOfMPARTMessage) && + (i+1 < m_numchildren) && + (!m_children[i+1]->mMHTMLPart) ) + //(i > 0) && + // PL_strcasecmp(m_children[i]->GetPartSeparator(), m_children[i-1]->GetPartSeparator(), ) != 0 ) + { + PUSH(CRLF); + PUSH("--"); + PUSH(m_children[i]->GetPartSeparator()); + PUSH("--"); + PUSH(CRLF); + partOfMPARTMessage = PR_FALSE; + } } + PUSH(CRLF); PUSH("--"); - PUSH(separator); + PUSH(m_children[m_numchildren-1]->GetPartSeparator()); PUSH("--"); PUSH(CRLF); } - - FAIL: - PR_FREEIF(separator); return status; } diff --git a/mailnews/compose/src/nsMsgSendPart.h b/mailnews/compose/src/nsMsgSendPart.h index b10f83eb8db..afa98ef5c4e 100644 --- a/mailnews/compose/src/nsMsgSendPart.h +++ b/mailnews/compose/src/nsMsgSendPart.h @@ -28,89 +28,97 @@ #include "nsMsgZapIt.h" #include "nsMsgSend.h" - typedef int (*MSG_SendPartWriteFunc)(const char* line, PRInt32 size, - PRBool isheader, void* closure); + PRBool isheader, void* closure); class nsMsgSendPart : public nsMsgZapIt { public: nsMsgSendPart(nsMsgComposeAndSend* state, const char *part_charset = NULL); - virtual ~nsMsgSendPart(); // Note that the destructor also destroys - // any children that were added. + virtual ~nsMsgSendPart(); // Note that the destructor also destroys + // any children that were added. - virtual int Write(); + virtual int Write(PRBool aMultiPartRelatedWithAttachmentsMessage, + char *attachmentSeparator, + char *multipartRelatedSeparator); - virtual int SetFile(nsFileSpec *filename); - const nsFileSpec * GetFileSpec() {return m_filespec;} - XP_FileType GetFiletype() {return m_filetype;} + virtual int SetFile(nsFileSpec *filename); + const nsFileSpec *GetFileSpec() {return m_filespec;} + XP_FileType GetFiletype() {return m_filetype;} - virtual int SetBuffer(const char* buffer); - const char* GetBuffer() {return m_buffer;} + virtual int SetBuffer(const char* buffer); + const char *GetBuffer() {return m_buffer;} - virtual int SetType(const char* type); - const char* GetType() {return m_type;} + virtual int SetType(const char* type); + const char *GetType() {return m_type;} - const char* GetCharsetName() {return m_charset_name;} + const char *GetCharsetName() {return m_charset_name;} - virtual int SetOtherHeaders(const char* other); - const char* SetOtherHeaders() {return m_other;} - virtual int AppendOtherHeaders(const char* moreother); + virtual int SetOtherHeaders(const char* other); + const char *SetOtherHeaders() {return m_other;} + virtual int AppendOtherHeaders(const char* moreother); - virtual int SetMimeDeliveryState(nsMsgComposeAndSend* state); + virtual int SetMimeDeliveryState(nsMsgComposeAndSend* state); // Note that the nsMsgSendPart class will take over ownership of the // MimeEncoderData* object, deleting it when it chooses. (This is // necessary because deleting these objects is the only current way to // flush out the data in them.) - int SetEncoderData(MimeEncoderData* data); - MimeEncoderData *GetEncoderData() {return m_encoder_data;} + int SetEncoderData(MimeEncoderData* data); + MimeEncoderData *GetEncoderData() {return m_encoder_data;} - int SetStripSensitiveHeaders(PRBool value) { - m_strip_sensitive_headers = value; - return 0; - } - PRBool GetStripSensitiveHeaders() {return m_strip_sensitive_headers;} + int SetStripSensitiveHeaders(PRBool value) + { + m_strip_sensitive_headers = value; + return 0; + } + PRBool GetStripSensitiveHeaders() {return m_strip_sensitive_headers;} - virtual int AddChild(nsMsgSendPart* child); + virtual int AddChild(nsMsgSendPart* child); - PRInt32 GetNumChildren() {return m_numchildren;} - nsMsgSendPart* GetChild(PRInt32 which); - nsMsgSendPart* DetachChild(PRInt32 which); - - virtual int SetMainPart(PRBool value); - PRBool IsMainPart() {return m_mainpart;} + PRInt32 GetNumChildren() {return m_numchildren;} + nsMsgSendPart *GetChild(PRInt32 which); + nsMsgSendPart *DetachChild(PRInt32 which); + virtual int SetMainPart(PRBool value); + PRBool IsMainPart() + { + return m_mainpart; + } + void SetMultipartRelatedFlag(PRBool aFlag); + PRBool IsMultipartRelatedPart(); + void SetPartSeparator(char *aPartSeparator); + char *GetPartSeparator(); protected: - int CopyString(char** dest, const char* src); - int PushBody(char* buffer, PRInt32 length); + int CopyString(char** dest, const char* src); + int PushBody(char* buffer, PRInt32 length); - nsMsgComposeAndSend* m_state; - nsMsgSendPart* m_parent; - nsFileSpec *m_filespec; - XP_FileType m_filetype; - char* m_buffer; - char* m_type; - char* m_other; - char m_charset_name[64+1]; // charset name associated with this part - PRBool m_strip_sensitive_headers; - MimeEncoderData *m_encoder_data; /* Opaque state for base64/qp encoder. */ + char *mPartSeparator; // Don't Free this memory! + PRBool mMHTMLPart; // Is this an MHTML part? + nsMsgComposeAndSend *m_state; + nsMsgSendPart *m_parent; + nsFileSpec *m_filespec; + XP_FileType m_filetype; + char *m_buffer; + char *m_type; + char *m_other; + char m_charset_name[64+1]; // charset name associated with this part + PRBool m_strip_sensitive_headers; + MimeEncoderData *m_encoder_data; /* Opaque state for base64/qp encoder. */ - nsMsgSendPart** m_children; - PRInt32 m_numchildren; + nsMsgSendPart **m_children; + PRInt32 m_numchildren; // Data used while actually writing. - PRBool m_firstBlock; - PRBool m_needIntlConversion; - CCCDataObject m_intlDocToMailConverter; + PRBool m_firstBlock; + PRBool m_needIntlConversion; + CCCDataObject m_intlDocToMailConverter; - PRBool m_mainpart; + PRBool m_mainpart; - PRBool m_just_hit_CR; + PRBool m_just_hit_CR; - static PRInt32 M_counter; + static PRInt32 M_counter; }; - - #endif /* _MsgSendPart_H_ */ diff --git a/mailnews/makefiles b/mailnews/makefiles index c1f7e103a3e..a44afa7faaf 100644 --- a/mailnews/makefiles +++ b/mailnews/makefiles @@ -99,6 +99,7 @@ mailnews/mime/public/Makefile mailnews/mime/src/Makefile mailnews/mime/resources/Makefile mailnews/mime/resources/skin/Makefile +mailnews/mime/resources/content/Makefile mailnews/compose/Makefile mailnews/compose/public/Makefile mailnews/compose/src/Makefile diff --git a/mailnews/mime/emitters/resources/skin/mailheader-all.css b/mailnews/mime/emitters/resources/skin/mailheader-all.css index 2596f0ad063..8314f8f156e 100644 --- a/mailnews/mime/emitters/resources/skin/mailheader-all.css +++ b/mailnews/mime/emitters/resources/skin/mailheader-all.css @@ -6,10 +6,10 @@ window { overflow: auto; } mailheader { display: block; } mailattachcount { display: none; } -box[name=header-attachment] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part1] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part2] { background-color: #DEDEDE; border: 2px solid #DEDEDE } -box[name=header-part3] { background-color: #DEDEDE; border: 2px solid #DEDEDE } +box[name=header-attachment] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part1] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part2] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } +box[name=header-part3] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } /************************************************** * These are all the headers that are displayed @@ -21,7 +21,7 @@ box[name=header-part3] { background-color: #DEDEDE; border: 2px solid #DEDE **************************************************/ header { display: block; text-align: left; } -headerdisplayname { font-weight: bold; } +headerdisplayname { font-weight: bold; white-space: pre; } header[field=DATE] { display: block; text-align:left; } diff --git a/mailnews/mime/emitters/resources/skin/mailheader-micro.css b/mailnews/mime/emitters/resources/skin/mailheader-micro.css index 5eabcd0c8eb..399f313b836 100644 --- a/mailnews/mime/emitters/resources/skin/mailheader-micro.css +++ b/mailnews/mime/emitters/resources/skin/mailheader-micro.css @@ -6,10 +6,10 @@ window { overflow: auto; } mailheader { display: block; } mailattachcount { display: none; } -box[name=header-attachment] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part1] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part2] { background-color: #DEDEDE; border: 2px solid #DEDEDE } -box[name=header-part3] { background-color: #DEDEDE; border: 2px solid #DEDEDE } +box[name=header-attachment] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part1] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part2] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } +box[name=header-part3] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } /************************************************** * These are all the headers that are displayed @@ -21,7 +21,7 @@ box[name=header-part3] { background-color: #DEDEDE; border: 2px solid #DEDE **************************************************/ header { display: none; text-align: left; } -headerdisplayname { font-weight: bold; } +headerdisplayname { font-weight: bold; white-space: pre; } header[field=DATE] { display: block; text-align:left; } diff --git a/mailnews/mime/emitters/resources/skin/mailheader-normal.css b/mailnews/mime/emitters/resources/skin/mailheader-normal.css index e9d41c0ec9f..747dd6fac4a 100644 --- a/mailnews/mime/emitters/resources/skin/mailheader-normal.css +++ b/mailnews/mime/emitters/resources/skin/mailheader-normal.css @@ -6,10 +6,10 @@ window { overflow: auto; } mailheader { display: block; } mailattachcount { display: none; } -box[name=header-attachment] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part1] { background-color: #EFEFEF; border: 2px solid #EFEFEF } -box[name=header-part2] { background-color: #DEDEDE; border: 2px solid #DEDEDE } -box[name=header-part3] { background-color: #DEDEDE; border: 2px solid #DEDEDE } +box[name=header-attachment] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part1] { background-color: #EFEFEF; border: 0px solid #EFEFEF; border-left-width: 4px; } +box[name=header-part2] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } +box[name=header-part3] { background-color: #DEDEDE; border: 0px solid #DEDEDE; border-left-width: 4px; } /************************************************** * These are all the headers that are displayed diff --git a/mailnews/mime/emitters/src/nsEmitterUtils.cpp b/mailnews/mime/emitters/src/nsEmitterUtils.cpp index 134143e61ce..5eff6d8fa1c 100644 --- a/mailnews/mime/emitters/src/nsEmitterUtils.cpp +++ b/mailnews/mime/emitters/src/nsEmitterUtils.cpp @@ -189,7 +189,7 @@ MimeGetStringByName(const char *aHeaderName) #include "windows.h" #endif -static char * +char * GetTheTempDirectoryOnTheSystem(void) { char *retPath = (char *)PR_Malloc(TPATH_LEN); diff --git a/mailnews/mime/emitters/src/nsEmitterUtils.h b/mailnews/mime/emitters/src/nsEmitterUtils.h index 42c9e89857f..2cfecd13151 100644 --- a/mailnews/mime/emitters/src/nsEmitterUtils.h +++ b/mailnews/mime/emitters/src/nsEmitterUtils.h @@ -33,5 +33,7 @@ char *nsMsgCreateTempFileName(char *tFileName); char *nsMimePlatformFileToURL (const char *name); +char *GetTheTempDirectoryOnTheSystem(void); + #endif // _nsEmitterUtils_h_ diff --git a/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp b/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp index 262dd9e903e..907e436ea39 100644 --- a/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeXULEmitter.cpp @@ -31,9 +31,15 @@ #include "nsFileStream.h" #include "nsMimeStringResources.h" #include "msgCore.h" +#include "nsIMsgHeaderParser.h" +#include "nsIComponentManager.h" +#include "nsEmitterUtils.h" +#include "nsFileSpec.h" // For the new pref API's static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); +static NS_DEFINE_CID(kMsgHeaderParserCID, NS_MSGHEADERPARSER_CID); +static NS_DEFINE_CID(kMimeMiscStatusCID, NS_MIME_MISC_STATUS_CID); nsresult NS_NewMimeXULEmitter(const nsIID& iid, void **result) { @@ -59,6 +65,7 @@ nsMimeXULEmitter::nsMimeXULEmitter() { NS_INIT_REFCNT(); + mCutoffValue = 3; mBufferMgr = NULL; mTotalWritten = 0; mTotalRead = 0; @@ -89,7 +96,22 @@ nsMimeXULEmitter::nsMimeXULEmitter() return; if ((mPrefs && NS_SUCCEEDED(rv))) + { mPrefs->GetIntPref("mail.show_headers", &mHeaderDisplayType); + mPrefs->GetIntPref("mailnews.max_header_display_length", &mCutoffValue); + } + + rv = nsComponentManager::CreateInstance(kMimeMiscStatusCID, + NULL, nsIMimeMiscStatus::GetIID(), + (void **) getter_AddRefs(mMiscStatus)); + if (NS_FAILED(rv)) + mMiscStatus = null_nsCOMPtr(); + + rv = nsComponentManager::CreateInstance(kMsgHeaderParserCID, + NULL, nsIMsgHeaderParser::GetIID(), + (void **) getter_AddRefs(mHeaderParser)); + if (NS_FAILED(rv)) + mHeaderParser = null_nsCOMPtr(); } nsMimeXULEmitter::~nsMimeXULEmitter(void) @@ -233,9 +255,47 @@ nsMimeXULEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWrit return NS_OK; } +#define TEMP_FILE_PREFIX "nsMimeBody" + +// +// RICHIE - We need to find a way to tell the webshell to delete the file once it is +// loaded. Until then, we will continually cleaup behind ourselves....ugh.. +nsresult +nsMimeXULEmitter::OhTheHumanityCleanupTempFileHack() +{ + // Age old question, where to store temp files....ugh! + char *tDir = GetTheTempDirectoryOnTheSystem(); + if (!tDir) + return NS_OK; + + nsFileSpec tempDir(tDir); + if (tempDir.Exists()) + { + for (nsDirectoryIterator i(tempDir, PR_FALSE); i.Exists(); i++) + { + nsFileSpec possibleTempFile = i.Spec(); + char *filename = possibleTempFile.GetLeafName(); + + if ((PL_strncmp(TEMP_FILE_PREFIX, filename, PL_strlen(TEMP_FILE_PREFIX)) == 0) && + (PL_strlen(filename) > PL_strlen(TEMP_FILE_PREFIX))) + { + possibleTempFile.Delete(PR_FALSE); + } + + nsCRT::free(filename); + filename = nsnull; + } + } + + PR_FREEIF(tDir); + return NS_OK; +} + nsresult nsMimeXULEmitter::EndBody() { + OhTheHumanityCleanupTempFileHack(); + mBody.Append(""); mBodyStarted = PR_FALSE; @@ -339,7 +399,7 @@ nsMimeXULEmitter::UtilityWriteCRLF(const char *buf) PRUint32 written; Write(buf, tmpLen, &written); - Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &written); + Write(CRLF, 2, &written); return NS_OK; } @@ -480,6 +540,8 @@ nsMimeXULEmitter::WriteXULHeader(const char *msgID) // Now, the JavaScript... UtilityWriteCRLF(""); + UtilityWriteCRLF(""); + DoGlobalStatusProcessing(); return NS_OK; } @@ -560,59 +622,6 @@ nsMimeXULEmitter::EndHeader() return NS_OK; } -// -// This is a header tag (i.e. tagname: "From", value: rhp@netscape.com. Do the right -// thing here to display this header in the XUL output. -// -nsresult -nsMimeXULEmitter::WriteXULTag(const char *tagName, const char *value) -{ - if ( (!value) || (!*value) ) - return NS_OK; - - char *upCaseTag = NULL; - char *newValue = nsEscapeHTML(value); - if (!newValue) - return NS_OK; - - nsString newTagName(tagName); - newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); - - newTagName.ToUpperCase(); - upCaseTag = newTagName.ToNewCString(); - - UtilityWrite("
"); - - // Here is where we are going to try to L10N the tagName so we will always - // get a field name next to an emitted header value. Note: Default will always - // be the name of the header itself. - // - UtilityWrite(""); - char *l10nTagName = LocalizeHeaderName(upCaseTag, tagName); - if ( (!l10nTagName) || (!*l10nTagName) ) - UtilityWrite(tagName); - else - { - UtilityWrite(l10nTagName); - PR_FREEIF(l10nTagName); - } - - UtilityWrite(""); - - // Now write out the actual value itself and move on! - // - UtilityWrite(": "); - UtilityWrite(newValue); - UtilityWrite("
"); - - delete[] upCaseTag; - PR_FREEIF(newValue); - - return NS_OK; -} - // // This is called at teardown time, but since we have been cacheing lots of // good information about the mail message (headers, attachments and body), this @@ -712,11 +721,49 @@ nsMimeXULEmitter::DumpAttachmentMenu() } nsresult -nsMimeXULEmitter::DumpAddBookIcon() +nsMimeXULEmitter::DumpAddBookIcon(char *fromLine) { + char *email = nsnull; + char *name = nsnull; + PRUint32 numAddresses; + char *names; + char *addresses; + nsresult rv; + char *newName; + UtilityWriteCRLF(""); - UtilityWriteCRLF(""); + + if (mHeaderParser) + rv = mHeaderParser->ParseHeaderAddresses ("UTF-8", fromLine, + &names, &addresses, &numAddresses); + if (NS_SUCCEEDED(rv)) + { + name = names; + email = addresses; + } + else + { + name = fromLine; + email = fromLine; + } + + // Strip off extra quotes... + nsString workString(name); + workString.Trim("\""); + newName = workString.ToNewCString(); + + UtilityWrite(""); + UtilityWriteCRLF(""); + + PR_FREEIF(newName); + PR_FREEIF(names); + PR_FREEIF(addresses); return NS_OK; } @@ -745,7 +792,7 @@ nsMimeXULEmitter::OutputGenericHeader(const char *aHeaderVal) if (val) { - UtilityWriteCRLF(""); + UtilityWriteCRLF(""); rv = WriteXULTag(aHeaderVal, val); UtilityWriteCRLF(""); return rv; @@ -776,7 +823,7 @@ nsMimeXULEmitter::DumpSubjectFromDate() UtilityWriteCRLF(""); // Now the addbook and attachment icons need to be displayed - DumpAddBookIcon(); + DumpAddBookIcon(GetHeaderValue(HEADER_FROM)); DumpAttachmentMenu(); UtilityWriteCRLF(""); @@ -831,7 +878,7 @@ nsMimeXULEmitter::DumpRestOfHeaders() (!PL_strcasecmp(HEADER_CC, headerInfo->name)) ) continue; - UtilityWriteCRLF(""); + UtilityWriteCRLF(""); WriteXULTag(headerInfo->name, headerInfo->value); UtilityWriteCRLF(""); } @@ -841,3 +888,306 @@ nsMimeXULEmitter::DumpRestOfHeaders() UtilityWriteCRLF(""); return NS_OK; } + +// +// This is a general routine that will dispatch the writing of headers to +// the correct method +// +nsresult +nsMimeXULEmitter::WriteXULTag(const char *tagName, const char *value) +{ + if ( (!PL_strcasecmp(HEADER_FROM, tagName)) || + (!PL_strcasecmp(HEADER_CC, tagName)) || + (!PL_strcasecmp(HEADER_TO, tagName)) || + (!PL_strcasecmp(HEADER_BCC, tagName)) ) + return WriteEmailAddrXULTag(tagName, value); + else + return WriteMiscXULTag(tagName, value); +} + + +nsresult +nsMimeXULEmitter::WriteXULTagPrefix(const char *tagName, const char *value) +{ + char *upCaseTag = NULL; + + nsString newTagName(tagName); + newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); + + newTagName.ToUpperCase(); + upCaseTag = newTagName.ToNewCString(); + + UtilityWrite("
"); + + // Here is where we are going to try to L10N the tagName so we will always + // get a field name next to an emitted header value. Note: Default will always + // be the name of the header itself. + // + UtilityWriteCRLF(""); + UtilityWriteCRLF(""); + UtilityWriteCRLF(""); + + UtilityWrite(""); + char *l10nTagName = LocalizeHeaderName(upCaseTag, tagName); + if ( (!l10nTagName) || (!*l10nTagName) ) + UtilityWrite(tagName); + else + { + UtilityWrite(l10nTagName); + PR_FREEIF(l10nTagName); + } + + UtilityWrite(": "); + UtilityWriteCRLF(""); + + UtilityWriteCRLF(""); + + delete[] upCaseTag; + return NS_OK; +} + +nsresult +nsMimeXULEmitter::WriteXULTagPostfix(const char *tagName, const char *value) +{ + UtilityWriteCRLF(""); + UtilityWriteCRLF(""); + + // Finalize and write out end of headers... + UtilityWriteCRLF("
"); + return NS_OK; +} + +// +// This is the routine that is responsible for parsing and writing email +// header. (i.e. From:, CC:, etc...) This will parse apart the addresses +// and do things like make them links for easy adding to the address book +// +nsresult +nsMimeXULEmitter::WriteEmailAddrXULTag(const char *tagName, const char *value) +{ +char *upCaseTag = NULL; + + if ( (!value) || (!*value) ) + return NS_OK; + + nsString newTagName(tagName); + newTagName.CompressWhitespace(PR_TRUE, PR_TRUE); + newTagName.ToUpperCase(); + upCaseTag = newTagName.ToNewCString(); + + WriteXULTagPrefix(tagName, value); + + // Ok, now this is where we need to loop through all of the addresses and + // do interesting things with the contents. + // + UtilityWriteCRLF(""); + OutputEmailAddresses(upCaseTag, value); + UtilityWriteCRLF(""); + + PR_FREEIF(upCaseTag); + WriteXULTagPostfix(tagName, value); + return NS_OK; +} + +// +// This is a header tag (i.e. tagname: "From", value: rhp@netscape.com. Do the right +// thing here to display this header in the XUL output. +// +nsresult +nsMimeXULEmitter::WriteMiscXULTag(const char *tagName, const char *value) +{ + if ( (!value) || (!*value) ) + return NS_OK; + + WriteXULTagPrefix(tagName, value); + + UtilityWriteCRLF(""); + + // Now write out the actual value itself and move on! + char *newValue = nsEscapeHTML(value); + if (newValue) + UtilityWrite(newValue); + else + UtilityWrite(value); + PR_FREEIF(newValue); + //// + + UtilityWriteCRLF(""); + + WriteXULTagPostfix(tagName, value); + return NS_OK; +} + +nsresult +nsMimeXULEmitter::DoGlobalStatusProcessing() +{ + char *retval = nsnull; + + if (!mMiscStatus) + return NS_OK; + + if (NS_SUCCEEDED(mMiscStatus->GetGlobalXULandJS(&retval))) + if ( (retval) && (*retval) ) + UtilityWriteCRLF(retval); + + PR_FREEIF(retval); + return NS_OK; +} + +nsresult +nsMimeXULEmitter::OutputEmailAddresses(const char *aHeader, const char *aEmailAddrs) +{ + PRUint32 numAddresses; + char *names; + char *addresses; + char *newValue = nsEscapeHTML(aEmailAddrs); + + if ( (!mHeaderParser) || + NS_FAILED(mHeaderParser->ParseHeaderAddresses ("UTF-8", aEmailAddrs, + &names, &addresses, &numAddresses)) ) + { + if (newValue) + UtilityWrite(newValue); + + PR_FREEIF(newValue); + return NS_OK; + } + + char *curName = names; + char *curAddress = addresses; + + if (numAddresses > (PRUint32) mCutoffValue) + { + UtilityWrite(""); + + for (PRUint32 i = 0; i < (PRUint32) mCutoffValue; i++) + { + ProcessSingleEmailEntry(aHeader, curName, curAddress); + + if (i != (numAddresses-1)) + UtilityWrite(", "); + + if ( ( ((i+1) % 2) == 0) && ((i+1) != (PRUint32) mCutoffValue)) + { + UtilityWrite(""); + } + + curName += strlen(curName) + 1; + curAddress += strlen(curAddress) + 1; + } + + UtilityWrite(""); + + UtilityWrite(""); + UtilityWrite(""); + } + + curName = names; + curAddress = addresses; + for (PRUint32 i = 0; i < numAddresses; i++) + { + ProcessSingleEmailEntry(aHeader, curName, curAddress); + + if (i != (numAddresses-1)) + UtilityWrite(", "); + + if ( ( ((i+1) % 2) == 0) && (i != (numAddresses-1))) + { + UtilityWrite(""); + } + + curName += strlen(curName) + 1; + curAddress += strlen(curAddress) + 1; + } + + if (numAddresses > (PRUint32) mCutoffValue) + { + UtilityWrite(""); + + UtilityWriteCRLF(""); + } + + PR_FREEIF(addresses); + PR_FREEIF(names); + + return NS_OK; +} + +nsresult +nsMimeXULEmitter::ProcessSingleEmailEntry(const char *curHeader, char *curName, char *curAddress) +{ +nsresult rv; +char *link = nsnull; +char *tLink = nsnull; +char *workName = nsnull; +char *workAddr = nsnull; + + if ( (curName) && (*curName) ) + { + nsString workString(curName); + + workString.Trim("\""); + workName = workString.ToNewCString(); + } + + if ( (curAddress) && (*curAddress) ) + { + nsString workString2(curAddress); + + workString2.Trim("\""); + workAddr = workString2.ToNewCString(); + } + + // tLink = PR_smprintf("addbook:add?vcard=begin%%3Avcard%%0Afn%%3A%s%%0Aemail%%3Binternet%%3A%s%%0Aend%%3Avcard%%0A", + // (workName ? workName : workAddr), workAddr); + tLink = PR_smprintf("mailto:%s", workAddr); + if (tLink) + link = nsEscapeHTML(tLink); + if (link) + { + UtilityWrite(""); + } + + if (workName) + UtilityWrite(workName); + else + UtilityWrite(curName); + UtilityWrite(" "); + + UtilityWrite("<"); + UtilityWrite(curAddress); + UtilityWrite(">"); + + // End link stuff here... + if (link) + UtilityWriteCRLF(""); + + PR_FREEIF(link); + PR_FREEIF(tLink); + + // Misc here + char *xul; + rv = mMiscStatus->GetIndividualXUL(curHeader, workAddr, &xul); + if (NS_SUCCEEDED(rv) && xul) + UtilityWrite(xul); + + PR_FREEIF(workName); + PR_FREEIF(workAddr); + return NS_OK; +} diff --git a/mailnews/mime/emitters/src/nsMimeXULEmitter.h b/mailnews/mime/emitters/src/nsMimeXULEmitter.h index cdd8482cf9c..1d590a3912b 100644 --- a/mailnews/mime/emitters/src/nsMimeXULEmitter.h +++ b/mailnews/mime/emitters/src/nsMimeXULEmitter.h @@ -30,6 +30,8 @@ #include "nsVoidArray.h" #include "nsString.h" #include "nsFileSpec.h" +#include "nsIMimeMiscStatus.h" +#include "nsIMsgHeaderParser.h" // // Used for keeping track of the attachment information... @@ -87,10 +89,17 @@ public: NS_IMETHOD WriteXULHeader(const char *msgID); NS_IMETHOD WriteXULTag(const char *tagName, const char *value); + NS_IMETHOD WriteMiscXULTag(const char *tagName, const char *value); + NS_IMETHOD WriteEmailAddrXULTag(const char *tagName, const char *value); + nsresult OutputEmailAddresses(const char *aHeader, const char *aEmailAddrs); + nsresult ProcessSingleEmailEntry(const char *curHeader, char *curName, char *curAddress); + nsresult WriteXULTagPrefix(const char *tagName, const char *value); + nsresult WriteXULTagPostfix(const char *tagName, const char *value); + nsresult OhTheHumanityCleanupTempFileHack(); // For Interesting XUL output! nsresult DumpAttachmentMenu(); - nsresult DumpAddBookIcon(); + nsresult DumpAddBookIcon(char *fromLine); nsresult DumpSubjectFromDate(); nsresult DumpToCC(); nsresult DumpRestOfHeaders(); @@ -99,6 +108,7 @@ public: // For storing recipient info in the history database... nsresult DoSpecialSenderProcessing(const char *field, const char *value); + nsresult DoGlobalStatusProcessing(); char *GetHeaderValue(const char *aHeaderName); @@ -128,6 +138,7 @@ protected: // The setting for header output... nsIPref *mPrefs; /* Connnection to prefs service manager */ PRInt32 mHeaderDisplayType; + PRInt32 mCutoffValue; // For attachment processing... PRInt32 mAttachCount; @@ -141,6 +152,8 @@ protected: // For header caching... nsVoidArray *mHeaderArray; + nsCOMPtr mMiscStatus; + nsCOMPtr mHeaderParser; }; diff --git a/mailnews/mime/public/Makefile.in b/mailnews/mime/public/Makefile.in index 872d5fb5cb7..aba42e40937 100644 --- a/mailnews/mime/public/Makefile.in +++ b/mailnews/mime/public/Makefile.in @@ -28,6 +28,7 @@ XPIDLSRCS = \ nsIMimeEmitter.idl \ nsIMimeURLUtils.idl \ nsIMsgHeaderParser.idl \ + nsIMimeMiscStatus.idl \ $(NULL) EXPORTS = \ diff --git a/mailnews/mime/public/makefile.win b/mailnews/mime/public/makefile.win index ac015872dd5..90f63f0a853 100644 --- a/mailnews/mime/public/makefile.win +++ b/mailnews/mime/public/makefile.win @@ -24,6 +24,7 @@ XPIDLSRCS = \ .\nsIMimeURLUtils.idl \ .\nsIMsgHeaderParser.idl \ .\nsIMimeStreamConverter.idl \ + .\nsIMimeMiscStatus.idl \ $(NULL) EXPORTS = \ diff --git a/mailnews/mime/resources/Makefile.in b/mailnews/mime/resources/Makefile.in index 917e43a4acc..a3f00871288 100644 --- a/mailnews/mime/resources/Makefile.in +++ b/mailnews/mime/resources/Makefile.in @@ -24,7 +24,7 @@ include $(DEPTH)/config/autoconf.mk MESSENGER_DIR = $(DIST)/bin/res/mailnews/messenger -DIRS = skin +DIRS = skin content EXPORT_RESOURCES = \ $(srcdir)/mime_en.properties \ diff --git a/mailnews/mime/resources/makefile.win b/mailnews/mime/resources/makefile.win index d810ad6a3b5..43ce553b3b4 100644 --- a/mailnews/mime/resources/makefile.win +++ b/mailnews/mime/resources/makefile.win @@ -16,7 +16,7 @@ DEPTH=..\..\.. -DIRS= skin +DIRS= skin content include <$(DEPTH)\config\rules.mak> diff --git a/mailnews/mime/resources/skin/MANIFEST b/mailnews/mime/resources/skin/MANIFEST index 74b7f3b1590..36fdf91cafb 100644 --- a/mailnews/mime/resources/skin/MANIFEST +++ b/mailnews/mime/resources/skin/MANIFEST @@ -20,3 +20,6 @@ frown.gif smile.gif wink.gif sick.gif +more.gif +less.gif + diff --git a/mailnews/mime/resources/skin/Makefile.in b/mailnews/mime/resources/skin/Makefile.in index cb301e48826..23e1f0fcffb 100644 --- a/mailnews/mime/resources/skin/Makefile.in +++ b/mailnews/mime/resources/skin/Makefile.in @@ -33,6 +33,8 @@ EXPORT_RESOURCES = \ $(srcdir)/frown.gif \ $(srcdir)/wink.gif \ $(srcdir)/sick.gif \ + $(srcdir)/less.gif \ + $(srcdir)/more.gif \ $(NULL) EXPORT_RESOURCES_TO_REMOVE := $(addprefix $(MESSENGER_DIR)/, $(EXPORT_RESOURCES)) diff --git a/mailnews/mime/resources/skin/makefile.win b/mailnews/mime/resources/skin/makefile.win index 838790fd1cd..f6189ef1a8e 100644 --- a/mailnews/mime/resources/skin/makefile.win +++ b/mailnews/mime/resources/skin/makefile.win @@ -23,9 +23,13 @@ install:: $(MAKE_INSTALL) smile.gif $(DIST)\bin\chrome\messenger\skin\default $(MAKE_INSTALL) wink.gif $(DIST)\bin\chrome\messenger\skin\default $(MAKE_INSTALL) sick.gif $(DIST)\bin\chrome\messenger\skin\default + $(MAKE_INSTALL) more.gif $(DIST)\bin\chrome\messenger\skin\default + $(MAKE_INSTALL) less.gif $(DIST)\bin\chrome\messenger\skin\default clobber:: rm -f $(DIST)\bin\chrome\messenger\skin\default\frown.gif rm -f $(DIST)\bin\chrome\messenger\skin\default\smile.gif rm -f $(DIST)\bin\chrome\messenger\skin\default\wink.gif rm -f $(DIST)\bin\chrome\messenger\skin\default\sick.gif + rm -f $(DIST)\bin\chrome\messenger\skin\default\more.gif + rm -f $(DIST)\bin\chrome\messenger\skin\default\less.gif diff --git a/mailnews/mime/src/mimemsg.cpp b/mailnews/mime/src/mimemsg.cpp index 10c917e143e..f95ebf7ab60 100644 --- a/mailnews/mime/src/mimemsg.cpp +++ b/mailnews/mime/src/mimemsg.cpp @@ -564,12 +564,12 @@ MimeMessage_write_headers_html (MimeObject *obj) // 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? */ mimeEmitterStartHeader(obj->options, - (obj == obj->options->state->root), + outer_p, (obj->options->headers == MimeHeadersOnly), msgID, - "UTF-8" - ); + "UTF-8"); PR_FREEIF(msgID); #ifdef MOZ_SECURITY diff --git a/mailnews/mime/src/nsMimeURLUtils.cpp b/mailnews/mime/src/nsMimeURLUtils.cpp index 4a3b0bcf99d..883fa7e8fff 100644 --- a/mailnews/mime/src/nsMimeURLUtils.cpp +++ b/mailnews/mime/src/nsMimeURLUtils.cpp @@ -1197,18 +1197,19 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) several URLs, which ought to be as many as most docs use. */ output = (char *)PR_Malloc(output_max); - if (!output) goto FAIL; + if (!output) + goto FAIL; tmpbuf_max = 1024; tmpbuf = (char *)PR_Malloc(tmpbuf_max); - if (!tmpbuf) goto FAIL; + if (!tmpbuf) + goto FAIL; inputend = input + inputlength; linestart = input; curoutput = output; - /* Here's the strategy. We find a chunk of plainish looking text -- no embedded CR or LF, no "<" or "&". We feed that off to ScanForURLs, and append the result. Then we skip to the next bit of plain text. If @@ -1216,8 +1217,6 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) "<", well, if it was a "" tag, then skip to the closing "". Otherwise, skip to the end of the tag. */ - - lineend = linestart; while (linestart < inputend && lineend <= inputend) { switch (*lineend) { @@ -1233,7 +1232,8 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) tmpbuf_max = length * 3 + 512; PR_Free(tmpbuf); tmpbuf = (char *)PR_Malloc(tmpbuf_max); - if (!tmpbuf) goto FAIL; + if (!tmpbuf) + goto FAIL; } if (ScanForURLs(linestart, length, tmpbuf, tmpbuf_max, TRUE) != NS_OK) { @@ -1241,8 +1241,8 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) } length = PL_strlen(tmpbuf); Append(&output, &output_max, &curoutput, tmpbuf, length); - if (!output) goto FAIL; - + if (!output) + goto FAIL; } linestart = lineend; lineend = NULL; @@ -1276,7 +1276,8 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) if (!lineend) lineend = inputend; Append(&output, &output_max, &curoutput, linestart, lineend - linestart); - if (!output) goto FAIL; + if (!output) + goto FAIL; linestart = lineend; break; default: @@ -1287,12 +1288,13 @@ nsMimeURLUtils::ScanHTMLForURLs(const char* input, char **retBuf) tmpbuf = NULL; *curoutput = '\0'; *retBuf = output; + return NS_OK; FAIL: if (tmpbuf) PR_Free(tmpbuf); if (output) PR_Free(output); *retBuf = NULL; - return NS_OK; + return NS_ERROR_FAILURE; } // diff --git a/mailnews/mime/tests/mimetest/mimetest.cpp b/mailnews/mime/tests/mimetest/mimetest.cpp index 128a39516d1..2dc14d7a4c5 100644 --- a/mailnews/mime/tests/mimetest/mimetest.cpp +++ b/mailnews/mime/tests/mimetest/mimetest.cpp @@ -254,7 +254,8 @@ NS_IMETHODIMP ConsoleOutputStreamListener::OnDataAvailable(nsIChannel * aChannel inStr->Read(aBuf, count, &aCount); // If raw, don't postprocess... - if (mOutFormat == nsMimeOutput::nsMimeMessageRaw) + if ((mOutFormat == nsMimeOutput::nsMimeMessageRaw) || + (mOutFormat == nsMimeOutput::nsMimeMessageXULDisplay) ) { PR_Write(PR_GetSpecialFD(PR_StandardOutput), aBuf, aCount); return NS_OK;