static int MimeInlineTextPlainFlowed_parse_line (const char *aLine, PRInt32 length, MimeObject *obj) { int status; PRBool quoting = ( obj->options && ( obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting || obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting ) ); // see above PRBool plainHTML = quoting || (obj->options && obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs); // see above struct MimeInlineTextPlainFlowedExData *exdata; exdata = MimeInlineTextPlainFlowedExDataList; while(exdata && (exdata->ownerobj != obj)) { exdata = exdata->next; } NS_ASSERTION(exdata, "The extra data has disappeared!"); NS_ASSERTION(length > 0, "zero length"); if (length <= 0) return 0; uint32 linequotelevel = 0; nsCAutoString real_line(aLine, length); char *line = real_line.BeginWriting(); const char *linep = real_line.BeginReading(); // Space stuffed? if(' ' == *linep) { linep++; } else { // count '>':s before the first non-'>' while('>' == *linep) { linep++; linequotelevel++; } // Space stuffed? if(' ' == *linep) { linep++; } } // Look if the last character (after stripping ending end // of lines and quoting stuff) is a SPACE. If it is, we are looking at a // flowed line. Normally we assume that the last two chars // are CR and LF as said in RFC822, but that doesn't seem to // be the case always. PRBool flowed = PR_FALSE; PRBool sigSeparator = PR_FALSE; PRInt32 index = length-1; while(index >= 0 && ('\r' == line[index] || '\n' == line[index])) { index--; } if (index > linep - line && ' ' == line[index]) /* Ignore space stuffing, i.e. lines with just (quote marks and) a space count as empty */ { flowed = PR_TRUE; sigSeparator = (index - (linep - line) + 1 == 3) && !strncmp(linep, "-- ", 3); if (((MimeInlineTextPlainFlowed *) obj)->delSp && ! sigSeparator) /* If line is flowed and DelSp=yes, logically delete trailing space. Line consisting of dash dash space ("-- "), commonly used as signature separator, gets special handling (RFC 3676) */ { length--; line[index] = '\0'; } } mozITXTToHTMLConv *conv = GetTextConverter(obj->options); PRBool skipConversion = !conv || (obj->options && obj->options->force_user_charset); nsAutoString lineSource; nsString lineResult; char *mailCharset = NULL; nsresult rv; if (!skipConversion) { // Convert only if the source string is not empty if (length - (linep - line) > 0) { PRBool whattodo = obj->options->whattodo; if (plainHTML) { if (quoting) whattodo = 0; else whattodo = whattodo & ~mozITXTToHTMLConv::kGlyphSubstitution; /* Do recognition for the case, the result is viewed in Mozilla, but not GlyphSubstitution, because other UAs might not be able to display the glyphs. */ } const nsDependentCSubstring& inputStr = Substring(linep, linep + (length - (linep - line))); // For 'SaveAs', |line| is in |mailCharset|. // convert |line| to UTF-16 before 'html'izing (calling ScanTXT()) if (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs) { // Get the mail charset of this message. MimeInlineText *inlinetext = (MimeInlineText *) obj; if (!inlinetext->initializeCharset) ((MimeInlineTextClass*)&mimeInlineTextClass)->initialize_charset(obj); mailCharset = inlinetext->charset; if (mailCharset && *mailCharset) { rv = nsMsgI18NConvertToUnicode(mailCharset, PromiseFlatCString(inputStr), lineSource); NS_ENSURE_SUCCESS(rv, -1); } else // this probably never happens... CopyUTF8toUTF16(inputStr, lineSource); } else // line is in UTF-8 CopyUTF8toUTF16(inputStr, lineSource); // This is the main TXT to HTML conversion: // escaping (very important), eventually recognizing etc. rv = conv->ScanTXT(lineSource.get(), whattodo, getter_Copies(lineResult)); NS_ENSURE_SUCCESS(rv, -1); } } else { CopyUTF8toUTF16(nsDependentCString(line, length), lineResult); status = NS_OK; } nsCAutoString preface; /* Correct number of blockquotes */ int32 quoteleveldiff=linequotelevel - exdata->quotelevel; if((quoteleveldiff != 0) && flowed && exdata->inflow) { // From RFC 2646 4.5 // The receiver SHOULD handle this error by using the 'quote-depth-wins' rule, // which is to ignore the flowed indicator and treat the line as fixed. That // is, the change in quote depth ends the paragraph. // We get that behaviour by just going on. } while(quoteleveldiff>0) { quoteleveldiff--; preface += "<blockquote type=cite"; // This is to have us observe the user pref settings for citations MimeInlineTextPlainFlowed *tObj = (MimeInlineTextPlainFlowed *) obj; nsCAutoString style; MimeTextBuildPrefixCSS(tObj->mQuotedSizeSetting, tObj->mQuotedStyleSetting, tObj->mCitationColor, style); if (!plainHTML && !style.IsEmpty()) { preface += " style=\""; preface += style; preface += '"'; } preface += '>'; } while(quoteleveldiff<0) { quoteleveldiff++; preface += "</blockquote>"; } exdata->quotelevel = linequotelevel; nsAutoString lineResult2; if(flowed) { // Check RFC 2646 "4.3. Usenet Signature Convention": "-- "+CRLF is // not a flowed line if (sigSeparator) { if (linequotelevel > 0 || exdata->isSig) { preface += "-- <br>"; } else { exdata->isSig = PR_TRUE; preface += "<div class=\"moz-txt-sig\"><span class=\"moz-txt-tag\">" "-- <br></span>"; } } else { Line_convert_whitespace(lineResult, PR_FALSE /* Allow wraps */, lineResult2); } exdata->inflow=PR_TRUE; } else { // Fixed paragraph. Line_convert_whitespace(lineResult, !plainHTML && !obj->options->wrap_long_lines_p /* If wrap, convert all spaces but the last in a row into nbsp, otherwise all. */, lineResult2); lineResult2.AppendLiteral("<br>"); exdata->inflow = PR_FALSE; } // End Fixed line if (!(exdata->isSig && quoting)) { status = MimeObject_write(obj, preface.get(), preface.Length(), PR_TRUE); if (status < 0) return status; nsCAutoString outString; if (obj->options->format_out != nsMimeOutput::nsMimeMessageSaveAs || !mailCharset || !*mailCharset) CopyUTF16toUTF8(lineResult2, outString); else { // convert back to mailCharset before writing. rv = nsMsgI18NConvertFromUnicode(mailCharset, lineResult2, outString); NS_ENSURE_SUCCESS(rv, -1); } status = MimeObject_write(obj, outString.get(), outString.Length(), PR_TRUE); return status; } else return NS_OK; }
static int MimeInlineTextPlain_parse_line (char *line, PRInt32 length, MimeObject *obj) { int status; PRBool quoting = ( obj->options && ( obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting || obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting ) ); // see above PRBool plainHTML = quoting || (obj->options && obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs); // see above PRBool rawPlainText = obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageFilterSniffer || obj->options->format_out == nsMimeOutput::nsMimeMessageAttach); // this routine gets called for every line of data that comes through the // mime converter. It's important to make sure we are efficient with // how we allocate memory in this routine. be careful if you go to add // more to this routine. NS_ASSERTION(length > 0, "zero length"); if (length <= 0) return 0; mozITXTToHTMLConv *conv = GetTextConverter(obj->options); MimeInlineTextPlain *text = (MimeInlineTextPlain *) obj; PRBool skipConversion = !conv || rawPlainText || (obj->options && obj->options->force_user_charset); char *mailCharset = NULL; nsresult rv; // if this part has a name and it's not a message/rfc822, don't quote if (quoting && obj->headers && MimeHeaders_get_name(obj->headers, obj->options) && PL_strcasecmp(obj->content_type, MESSAGE_RFC822)) return 0; if (!skipConversion) { nsDependentCString inputStr(line, length); nsAutoString lineSourceStr; // For 'SaveAs', |line| is in |mailCharset|. // convert |line| to UTF-16 before 'html'izing (calling ScanTXT()) if (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs) { // Get the mail charset of this message. MimeInlineText *inlinetext = (MimeInlineText *) obj; if (!inlinetext->initializeCharset) ((MimeInlineTextClass*)&mimeInlineTextClass)->initialize_charset(obj); mailCharset = inlinetext->charset; if (mailCharset && *mailCharset) { rv = nsMsgI18NConvertToUnicode(mailCharset, inputStr, lineSourceStr); NS_ENSURE_SUCCESS(rv, -1); } else // this probably never happens ... CopyUTF8toUTF16(inputStr, lineSourceStr); } else // line is in UTF-8 CopyUTF8toUTF16(inputStr, lineSourceStr); nsCAutoString prefaceResultStr; // Quoting stuff before the real text // Recognize quotes PRUint32 oldCiteLevel = text->mCiteLevel; PRUint32 logicalLineStart = 0; rv = conv->CiteLevelTXT(lineSourceStr.get(), &logicalLineStart, &(text->mCiteLevel)); NS_ENSURE_SUCCESS(rv, -1); // Find out, which recognitions to do PRBool whattodo = obj->options->whattodo; if (plainHTML) { if (quoting) whattodo = 0; // This is done on Send. Don't do it twice. else whattodo = whattodo & ~mozITXTToHTMLConv::kGlyphSubstitution; /* Do recognition for the case, the result is viewed in Mozilla, but not GlyphSubstitution, because other UAs might not be able to display the glyphs. */ if (!text->mBlockquoting) text->mCiteLevel = 0; } // Write blockquote if (text->mCiteLevel > oldCiteLevel) { prefaceResultStr += "</pre>"; for (PRUint32 i = 0; i < text->mCiteLevel - oldCiteLevel; i++) { nsCAutoString style; MimeTextBuildPrefixCSS(text->mQuotedSizeSetting, text->mQuotedStyleSetting, text->mCitationColor, style); if (!plainHTML && !style.IsEmpty()) { prefaceResultStr += "<blockquote type=cite style=\""; prefaceResultStr += style; prefaceResultStr += "\">"; } else prefaceResultStr += "<blockquote type=cite>"; } prefaceResultStr += "<pre wrap>"; } else if (text->mCiteLevel < oldCiteLevel) { prefaceResultStr += "</pre>"; for (PRUint32 i = 0; i < oldCiteLevel - text->mCiteLevel; i++) prefaceResultStr += "</blockquote>"; prefaceResultStr += "<pre wrap>"; if (text->mCiteLevel == 0) prefaceResultStr += "<!---->"; /* Make sure, NGLayout puts out a linebreak */ } // Write plain text quoting tags if (logicalLineStart != 0 && !(plainHTML && text->mBlockquoting)) { if (!plainHTML) prefaceResultStr += "<span class=\"moz-txt-citetags\">"; nsAutoString citeTagsSource; lineSourceStr.Mid(citeTagsSource, 0, logicalLineStart); // Convert to HTML nsXPIDLString citeTagsResultUnichar; rv = conv->ScanTXT(citeTagsSource.get(), 0 /* no recognition */, getter_Copies(citeTagsResultUnichar)); if (NS_FAILED(rv)) return -1; AppendUTF16toUTF8(citeTagsResultUnichar, prefaceResultStr); if (!plainHTML) prefaceResultStr += "</span>"; } // recognize signature if ((lineSourceStr.Length() >= 4) && lineSourceStr.First() == '-' && Substring(lineSourceStr, 0, 3).EqualsLiteral("-- ") && (lineSourceStr[3] == '\r' || lineSourceStr[3] == '\n') ) { text->mIsSig = PR_TRUE; if (!quoting) prefaceResultStr += "<div class=\"moz-txt-sig\">"; } /* This is the main TXT to HTML conversion: escaping (very important), eventually recognizing etc. */ nsXPIDLString lineResultUnichar; rv = conv->ScanTXT(lineSourceStr.get() + logicalLineStart, whattodo, getter_Copies(lineResultUnichar)); NS_ENSURE_SUCCESS(rv, -1); if (!(text->mIsSig && quoting)) { status = MimeObject_write(obj, prefaceResultStr.get(), prefaceResultStr.Length(), PR_TRUE); if (status < 0) return status; nsCAutoString outString; if (obj->options->format_out != nsMimeOutput::nsMimeMessageSaveAs || !mailCharset || !*mailCharset) CopyUTF16toUTF8(lineResultUnichar, outString); else { // convert back to mailCharset before writing. rv = nsMsgI18NConvertFromUnicode(mailCharset, lineResultUnichar, outString); NS_ENSURE_SUCCESS(rv, -1); } status = MimeObject_write(obj, outString.get(), outString.Length(), PR_TRUE); } else { status = NS_OK; } } else { status = MimeObject_write(obj, line, length, PR_TRUE); } return status; }