nsresult TestPlainTextSerializer() { nsString test; test.AppendLiteral("<html><base>base</base><head><span>span</span></head>" "<body>body</body></html>"); ConvertBufToPlainText(test, 0); if (!test.EqualsLiteral("basespanbody")) { fail("Wrong html to text serialization"); return NS_ERROR_FAILURE; } passed("HTML to text serialization test"); nsresult rv = TestASCIIWithFlowedDelSp(); NS_ENSURE_SUCCESS(rv, rv); rv = TestCJKWithFlowedDelSp(); NS_ENSURE_SUCCESS(rv, rv); rv = TestPrettyPrintedHtml(); NS_ENSURE_SUCCESS(rv, rv); rv = TestPreElement(); NS_ENSURE_SUCCESS(rv, rv); rv = TestBlockElement(); NS_ENSURE_SUCCESS(rv, rv); rv = TestPreWrapElementForThunderbird(); NS_ENSURE_SUCCESS(rv, rv); // Add new tests here... return NS_OK; }
// Test for ASCII with format=flowed; delsp=yes nsresult TestASCIIWithFlowedDelSp() { nsString test; nsString result; test.AssignLiteral("<html><body>" "Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox" "</body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed | nsIDocumentEncoder::OutputFormatDelSp); // create result case result.AssignLiteral("Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox " "Firefox \r\nFirefox Firefox Firefox\r\n"); if (!test.Equals(result)) { fail("Wrong HTML to ASCII text serialization with format=flowed; delsp=yes"); return NS_ERROR_FAILURE; } passed("HTML to ASCII text serialization with format=flowed; delsp=yes"); return NS_OK; }
// Test for CJK with DisallowLineBreaking TEST(PlainTextSerializer, CJKWithDisallowLineBreaking) { nsString test; nsString result; test.AssignLiteral("<html><body>"); for (uint32_t i = 0; i < 400; i++) { // Insert Kanji (U+5341) test.Append(0x5341); } test.AppendLiteral("</body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed | nsIDocumentEncoder::OutputDisallowLineBreaking); // create result case for (uint32_t i = 0; i < 400; i++) { result.Append(0x5341); } result.AppendLiteral("\r\n"); ASSERT_TRUE(test.Equals(result)) << "Wrong HTML to CJK text serialization with OutputDisallowLineBreaking"; }
nsresult TestPreWrapElementForThunderbird() { // This test examines the magic pre-wrap setup that Thunderbird relies on. nsString test; test.AppendLiteral( "<html>" NS_LINEBREAK "<body style=\"white-space: pre-wrap; width: 10ch;\">" NS_LINEBREAK "<pre>" NS_LINEBREAK " first line is too long" NS_LINEBREAK " second line is even loooonger " NS_LINEBREAK "</pre>" NS_LINEBREAK "</body>" NS_LINEBREAK "</html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputWrap); // "\n\n first\nline is\ntoo long\n second\nline is\neven\nloooonger\n\n\n" if (!test.EqualsLiteral(NS_LINEBREAK NS_LINEBREAK " first" NS_LINEBREAK "line is" NS_LINEBREAK "too long" NS_LINEBREAK " second" NS_LINEBREAK "line is" NS_LINEBREAK "even" NS_LINEBREAK "loooonger" NS_LINEBREAK NS_LINEBREAK NS_LINEBREAK)) { fail("Wrong prettyprinted html to text serialization"); return NS_ERROR_FAILURE; } passed("prettyprinted HTML to text serialization test"); return NS_OK; }
// Test for ASCII with format=flowed; delsp=yes TEST(PlainTextSerializer, ASCIIWithFlowedDelSp) { nsString test; nsString result; test.AssignLiteral("<html><body>" "Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox" "</body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed | nsIDocumentEncoder::OutputFormatDelSp); // create result case result.AssignLiteral("Firefox Firefox Firefox Firefox " "Firefox Firefox Firefox Firefox " "Firefox \r\nFirefox Firefox Firefox\r\n"); ASSERT_TRUE(test.Equals(result)) << "Wrong HTML to ASCII text serialization with format=flowed; delsp=yes"; }
// Test for ASCII with format=flowed; and quoted lines in preformatted span. TEST(PlainTextSerializer, PreformatFlowedQuotes) { nsString test; nsString result; test.AssignLiteral("<html><body>" "<span style=\"white-space: pre-wrap;\">" "> Firefox Firefox Firefox Firefox <br>" "> Firefox Firefox Firefox Firefox<br>" "><br>" ">> Firefox Firefox Firefox Firefox <br>" ">> Firefox Firefox Firefox Firefox<br>" "</span></body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed); // create result case result.AssignLiteral("> Firefox Firefox Firefox Firefox \r\n" "> Firefox Firefox Firefox Firefox\r\n" ">\r\n" ">> Firefox Firefox Firefox Firefox \r\n" ">> Firefox Firefox Firefox Firefox\r\n"); ASSERT_TRUE(test.Equals(result)) << "Wrong HTML to ASCII text serialization with format=flowed; and quoted " "lines"; }
TEST(PlainTextSerializer, PreWrapElementForThunderbird) { // This test examines the magic pre-wrap setup that Thunderbird relies on. nsString test; test.AppendLiteral( "<html>" NS_LINEBREAK "<body style=\"white-space: pre-wrap; width: 10ch;\">" NS_LINEBREAK "<pre>" NS_LINEBREAK " first line is too long" NS_LINEBREAK " second line is even loooonger " NS_LINEBREAK "</pre>" NS_LINEBREAK "</body>" NS_LINEBREAK "</html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputWrap); // "\n\n first\nline is\ntoo long\n second\nline is\neven\nloooonger\n\n\n" ASSERT_TRUE(test.EqualsLiteral(NS_LINEBREAK NS_LINEBREAK " first" NS_LINEBREAK "line is" NS_LINEBREAK "too long" NS_LINEBREAK " second" NS_LINEBREAK "line is" NS_LINEBREAK "even" NS_LINEBREAK "loooonger" NS_LINEBREAK NS_LINEBREAK NS_LINEBREAK)) << "Wrong prettyprinted html to text serialization"; }
// Test for CJK with DisallowLineBreaking nsresult TestCJKWithDisallowLineBreaking() { nsString test; nsString result; test.AssignLiteral("<html><body>"); for (uint32_t i = 0; i < 400; i++) { // Insert Kanji (U+5341) test.Append(0x5341); } test.AppendLiteral("</body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed | nsIDocumentEncoder::OutputDisallowLineBreaking); // create result case for (uint32_t i = 0; i < 400; i++) { result.Append(0x5341); } result.AppendLiteral("\r\n"); if (!test.Equals(result)) { fail("Wrong HTML to CJK text serialization with OutputDisallowLineBreaking"); return NS_ERROR_FAILURE; } passed("HTML to CJK text serialization with OutputDisallowLineBreaking"); return NS_OK; }
TEST(PlainTextSerializer, Simple) { nsString test; test.AppendLiteral("<html><base>base</base><head><span>span</span></head>" "<body>body</body></html>"); ConvertBufToPlainText(test, 0); ASSERT_TRUE(test.EqualsLiteral("basespanbody")) << "Wrong html to text serialization"; }
TEST(PlainTextSerializer, PrettyPrintedHtml) { nsString test; test.AppendLiteral("<html>" NS_LINEBREAK "<body>" NS_LINEBREAK " first<br>" NS_LINEBREAK " second<br>" NS_LINEBREAK "</body>" NS_LINEBREAK "</html>"); ConvertBufToPlainText(test, 0); ASSERT_TRUE(test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) << "Wrong prettyprinted html to text serialization"; }
NS_IMETHODIMP nsMsgCompFields::ConvertBodyToPlainText() { nsresult rv = NS_OK; if (!m_body.IsEmpty()) { nsAutoString body; rv = GetBody(body); if (NS_SUCCEEDED(rv)) { rv = ConvertBufToPlainText(body, UseFormatFlowed(GetCharacterSet())); if (NS_SUCCEEDED(rv)) rv = SetBody(body); } } return rv; }
nsresult TestPrettyPrintedHtml() { nsString test; test.AppendLiteral( "<html>" NS_LINEBREAK "<body>" NS_LINEBREAK " first<br>" NS_LINEBREAK " second<br>" NS_LINEBREAK "</body>" NS_LINEBREAK "</html>"); ConvertBufToPlainText(test, 0); if (!test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) { fail("Wrong prettyprinted html to text serialization"); return NS_ERROR_FAILURE; } passed("prettyprinted HTML to text serialization test"); return NS_OK; }
// Test for CJK with format=flowed; delsp=yes nsresult TestCJKWithFlowedDelSp() { nsString test; nsString result; test.AssignLiteral("<html><body>"); for (PRUint32 i = 0; i < 40; i++) { // Insert Kanji (U+5341) test.Append(0x5341); } test.AppendLiteral("</body></html>"); ConvertBufToPlainText(test, nsIDocumentEncoder::OutputFormatted | nsIDocumentEncoder::OutputCRLineBreak | nsIDocumentEncoder::OutputLFLineBreak | nsIDocumentEncoder::OutputFormatFlowed | nsIDocumentEncoder::OutputFormatDelSp); // create result case for (PRUint32 i = 0; i < 36; i++) { result.Append(0x5341); } result.Append(NS_LITERAL_STRING(" \r\n")); for (PRUint32 i = 0; i < 4; i++) { result.Append(0x5341); } result.Append(NS_LITERAL_STRING("\r\n")); if (!test.Equals(result)) { fail("Wrong HTML to CJK text serialization with format=flowed; delsp=yes"); return NS_ERROR_FAILURE; } passed("HTML to CJK text serialization with format=flowed; delsp=yes"); return NS_OK; }
nsresult nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg) { NS_ASSERTION(m_mime_delivery_state != nsnull, "not-null m_mime_delivery_state"); // Close the file, but don't delete the disk file (or the file spec.) if (mOutFile) { mOutFile->Close(); mOutFile = nsnull; } // this silliness is because Windows nsILocalFile caches its file size // so if an output stream writes to it, it will still return the original // cached size. if (mTmpFile) { nsCOMPtr <nsIFile> tmpFile; mTmpFile->Clone(getter_AddRefs(tmpFile)); mTmpFile = do_QueryInterface(tmpFile); } mRequest = nsnull; // First things first, we are now going to see if this is an HTML // Doc and if it is, we need to see if we can determine the charset // for this part by sniffing the HTML file. // This is needed only when the charset is not set already. // (e.g. a charset may be specified in HTTP header) // if (!m_type.IsEmpty() && m_charset.IsEmpty() && m_type.LowerCaseEqualsLiteral(TEXT_HTML)) m_charset = nsMsgI18NParseMetaCharset(mTmpFile); nsresult mimeDeliveryStatus; m_mime_delivery_state->GetStatus(&mimeDeliveryStatus); if (mimeDeliveryStatus == NS_ERROR_ABORT) status = NS_ERROR_ABORT; if (NS_FAILED(status) && status != NS_ERROR_ABORT && NS_SUCCEEDED(mimeDeliveryStatus)) { // At this point, we should probably ask a question to the user // if we should continue without this attachment. // bool keepOnGoing = true; nsCString turl; nsString msg; PRUnichar *printfString = nsnull; nsresult rv; nsCOMPtr<nsIStringBundleService> bundleService(do_GetService("@mozilla.org/intl/stringbundle;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow; m_mime_delivery_state->GetDeliveryMode(&mode); if (mode == nsIMsgSend::nsMsgSaveAsDraft || mode == nsIMsgSend::nsMsgSaveAsTemplate) bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SAVING, getter_Copies(msg)); else bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SENDING, getter_Copies(msg)); if (!m_realName.IsEmpty()) printfString = nsTextFormatter::smprintf(msg.get(), m_realName.get()); else if (NS_SUCCEEDED(mURL->GetSpec(turl)) && !turl.IsEmpty()) { nsCAutoString unescapedUrl; MsgUnescapeString(turl, 0, unescapedUrl); if (unescapedUrl.IsEmpty()) printfString = nsTextFormatter::smprintf(msg.get(), turl.get()); else printfString = nsTextFormatter::smprintf(msg.get(), unescapedUrl.get()); } else printfString = nsTextFormatter::smprintf(msg.get(), "?"); nsCOMPtr<nsIPrompt> aPrompt; if (m_mime_delivery_state) m_mime_delivery_state->GetDefaultPrompt(getter_AddRefs(aPrompt)); nsMsgAskBooleanQuestionByString(aPrompt, printfString, &keepOnGoing); PR_FREEIF(printfString); if (keepOnGoing) { status = 0; m_bogus_attachment = true; //That will cause this attachment to be ignored. } else { status = NS_ERROR_ABORT; m_mime_delivery_state->SetStatus(status); nsresult ignoreMe; m_mime_delivery_state->Fail(status, nsnull, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull); SetMimeDeliveryState(nsnull); return status; } } m_done = true; // // Ok, now that we have the file here on disk, we need to see if there was // a need to do conversion to plain text...if so, the magic happens here, // otherwise, just move on to other attachments... // if (NS_SUCCEEDED(status) && !m_type.LowerCaseEqualsLiteral(TEXT_PLAIN) && m_desiredType.LowerCaseEqualsLiteral(TEXT_PLAIN)) { // // Conversion to plain text desired. // PRInt32 width = 72; nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (pPrefBranch) pPrefBranch->GetIntPref("mailnews.wraplength", &width); // Let sanity reign! if (width == 0) width = 72; else if (width < 10) width = 10; else if (width > 30000) width = 30000; // // Now use the converter service here to do the right // thing and convert this data to plain text for us! // nsAutoString conData; if (NS_SUCCEEDED(LoadDataFromFile(mTmpFile, conData, true))) { if (NS_SUCCEEDED(ConvertBufToPlainText(conData, UseFormatFlowed(m_charset.get())))) { if (mDeleteFile) mTmpFile->Remove(false); nsCOMPtr<nsIOutputStream> outputStream; nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, PR_WRONLY | PR_CREATE_FILE, 00600); if (NS_SUCCEEDED(rv)) { nsCAutoString tData; if (NS_FAILED(ConvertFromUnicode(m_charset.get(), conData, tData))) LossyCopyUTF16toASCII(conData, tData); if (!tData.IsEmpty()) { PRUint32 bytesWritten; (void) outputStream->Write(tData.get(), tData.Length(), &bytesWritten); } outputStream->Close(); // this silliness is because Windows nsILocalFile caches its file size // so if an output stream writes to it, it will still return the original // cached size. if (mTmpFile) { nsCOMPtr <nsIFile> tmpFile; mTmpFile->Clone(getter_AddRefs(tmpFile)); mTmpFile = do_QueryInterface(tmpFile); } } } } m_type = m_desiredType; m_desiredType.Truncate(); m_encoding.Truncate(); } PRUint32 pendingAttachmentCount = 0; m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); NS_ASSERTION (pendingAttachmentCount > 0, "no more pending attachment"); m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1); bool processAttachmentsSynchronously = false; m_mime_delivery_state->GetProcessAttachmentsSynchronously(&processAttachmentsSynchronously); if (NS_SUCCEEDED(status) && processAttachmentsSynchronously) { /* Find the next attachment which has not yet been loaded, if any, and start it going. */ PRUint32 i; nsMsgAttachmentHandler *next = 0; nsMsgAttachmentHandler *attachments = nsnull; PRUint32 attachmentCount = 0; m_mime_delivery_state->GetAttachmentCount(&attachmentCount); if (attachmentCount) m_mime_delivery_state->GetAttachmentHandlers(&attachments); for (i = 0; i < attachmentCount; i++) { if (!attachments[i].m_done) { next = &attachments[i]; // // rhp: We need to get a little more understanding to failed URL // requests. So, at this point if most of next is NULL, then we // should just mark it fetched and move on! We probably ignored // this earlier on in the send process. // if ( (!next->mURL) && (next->m_uri.IsEmpty()) ) { attachments[i].m_done = true; m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1); next->mPartUserOmissionOverride = true; next = nsnull; continue; } break; } } if (next) { int status = next->SnarfAttachment(mCompFields); if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, nsnull, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } } } m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount); if (pendingAttachmentCount == 0) { // If this is the last attachment, then either complete the // delivery (if successful) or report the error by calling // the exit routine and terminating the delivery. if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } else { status = m_mime_delivery_state->GatherMimeAttachments (); if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull); SetMimeDeliveryState(nsnull); return NS_ERROR_UNEXPECTED; } } } else { // If this is not the last attachment, but it got an error, // then report that error and continue if (NS_FAILED(status)) { nsresult ignoreMe; m_mime_delivery_state->Fail(status, aMsg, &ignoreMe); } } SetMimeDeliveryState(nsnull); return NS_OK; }