mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-14 18:51:28 +00:00
fix for #43221, #64781, and #53644. take folder charset and apply appropriate charset conversion before comparison. r=nhotta, a=bienvenu
This commit is contained in:
parent
3131997624
commit
11558b490b
@ -72,9 +72,6 @@ public:
|
||||
|
||||
static nsresult EncodeImapValue(char *encoding, const char *value, PRBool useQuotes, PRBool reallyDredd);
|
||||
|
||||
static char *TryToConvertCharset(const PRUnichar *sourceStr,
|
||||
const PRUnichar *destCharset,
|
||||
PRBool useMIME2Style);
|
||||
static char *GetImapCharsetParam(const PRUnichar *destCharset);
|
||||
void GetSearchCharsets(nsString &srcCharset, nsString &destCharset);
|
||||
static PRUnichar *EscapeSearchUrl (const PRUnichar *nntpCommand);
|
||||
|
@ -330,7 +330,11 @@ NS_IMETHODIMP nsMsgFilter::MatchHdr(nsIMsgDBHdr *msgHdr, nsIMsgFolder *folder, n
|
||||
nsMsgSearchScopeTerm* scope = new nsMsgSearchScopeTerm(nsnull, nsMsgSearchScope::MailFolder, folder);
|
||||
nsCOMPtr<nsIMsgSearchScopeTerm> scopeInterface = scope;
|
||||
|
||||
nsXPIDLString folderCharset;
|
||||
folder->GetCharset(getter_Copies(folderCharset));
|
||||
const char *charset = NS_ConvertUCS2toUTF8(folderCharset);
|
||||
return nsMsgSearchOfflineMail::MatchTermsForFilter(msgHdr, m_termList,
|
||||
charset,
|
||||
scope,
|
||||
db,
|
||||
headers,
|
||||
|
@ -478,28 +478,31 @@ nsresult nsMsgSearchOfflineMail::SummaryFileError ()
|
||||
nsresult
|
||||
nsMsgSearchOfflineMail::MatchTermsForFilter(nsIMsgDBHdr *msgToMatch,
|
||||
nsISupportsArray *termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm * scope,
|
||||
nsIMsgDatabase * db,
|
||||
const char * headers,
|
||||
PRUint32 headerSize,
|
||||
PRBool *pResult)
|
||||
{
|
||||
return MatchTerms(msgToMatch, termList, scope, db, headers, headerSize, PR_TRUE, pResult);
|
||||
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, headers, headerSize, PR_TRUE, pResult);
|
||||
}
|
||||
|
||||
// static method which matches a header against a list of search terms.
|
||||
nsresult
|
||||
nsMsgSearchOfflineMail::MatchTermsForSearch(nsIMsgDBHdr *msgToMatch,
|
||||
nsISupportsArray* termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm *scope,
|
||||
nsIMsgDatabase *db,
|
||||
PRBool *pResult)
|
||||
{
|
||||
return MatchTerms(msgToMatch, termList, scope, db, nsnull, 0, PR_FALSE, pResult);
|
||||
return MatchTerms(msgToMatch, termList, defaultCharset, scope, db, nsnull, 0, PR_FALSE, pResult);
|
||||
}
|
||||
|
||||
nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch,
|
||||
nsISupportsArray * termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm * scope,
|
||||
nsIMsgDatabase * db,
|
||||
const char * headers,
|
||||
@ -511,9 +514,10 @@ nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch,
|
||||
nsXPIDLCString recipients;
|
||||
nsXPIDLCString ccList;
|
||||
nsXPIDLCString matchString;
|
||||
PRUint32 msgFlags;
|
||||
|
||||
PRBool result;
|
||||
nsXPIDLCString msgCharset;
|
||||
const char *charset;
|
||||
PRUint32 msgFlags;
|
||||
PRBool result;
|
||||
|
||||
if (!pResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -527,8 +531,6 @@ nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch,
|
||||
|
||||
// Loop over all terms, and match them all to this message.
|
||||
|
||||
const char *charset = nsnull; // scope->m_folder->GetFolderCSID() & ~CS_AUTO;
|
||||
|
||||
nsMsgSearchBoolExpression * expression = new nsMsgSearchBoolExpression(); // create our expression
|
||||
if (!expression)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -544,6 +546,8 @@ nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch,
|
||||
|
||||
nsMsgSearchAttribValue attrib;
|
||||
pTerm->GetAttrib(&attrib);
|
||||
msgToMatch->GetCharset(getter_Copies(msgCharset));
|
||||
charset = *(const char *)msgCharset ? msgCharset : defaultCharset;
|
||||
switch (attrib)
|
||||
{
|
||||
case nsMsgSearchAttrib::Sender:
|
||||
@ -658,6 +662,7 @@ nsresult nsMsgSearchOfflineMail::Search (PRBool *aDone)
|
||||
err = OpenSummaryFile ();
|
||||
if (!m_db) // must be reparsing.
|
||||
return err;
|
||||
|
||||
// Reparsing is unnecessary or completed
|
||||
if (NS_SUCCEEDED(err))
|
||||
{
|
||||
@ -678,8 +683,11 @@ nsresult nsMsgSearchOfflineMail::Search (PRBool *aDone)
|
||||
else
|
||||
{
|
||||
PRBool match = PR_FALSE;
|
||||
nsAutoString nullCharset, folderCharset;
|
||||
GetSearchCharsets(nullCharset, folderCharset);
|
||||
const char *charset = NS_ConvertUCS2toUTF8(folderCharset);
|
||||
// Is this message a hit?
|
||||
err = MatchTermsForSearch (msgDBHdr, m_searchTerms, m_scope, m_db, &match);
|
||||
err = MatchTermsForSearch (msgDBHdr, m_searchTerms, charset, m_scope, m_db, &match);
|
||||
|
||||
// Add search hits to the results list
|
||||
if (NS_SUCCEEDED(err) && match)
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
|
||||
static nsresult MatchTermsForFilter(nsIMsgDBHdr * msgToMatch,
|
||||
nsISupportsArray *termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm *scope,
|
||||
nsIMsgDatabase * db,
|
||||
const char * headers,
|
||||
@ -60,6 +61,7 @@ public:
|
||||
|
||||
static nsresult MatchTermsForSearch(nsIMsgDBHdr * msgTomatch,
|
||||
nsISupportsArray * termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm *scope,
|
||||
nsIMsgDatabase *db, PRBool *pResult);
|
||||
|
||||
@ -67,11 +69,10 @@ public:
|
||||
virtual nsresult OpenSummaryFile ();
|
||||
nsresult SummaryFileError();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
static nsresult MatchTerms(nsIMsgDBHdr *msgToMatch,
|
||||
nsISupportsArray *termList,
|
||||
const char *defaultCharset,
|
||||
nsIMsgSearchScopeTerm *scope,
|
||||
nsIMsgDatabase * db,
|
||||
const char * headers,
|
||||
|
@ -136,73 +136,6 @@ NS_IMETHODIMP nsMsgSearchAdapter::AddHit(nsMsgKey key)
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
nsMsgSearchAdapter::TryToConvertCharset(const PRUnichar *sourceStr,
|
||||
const PRUnichar * destCharset,
|
||||
PRBool useMime2)
|
||||
{
|
||||
char *result = nsnull;
|
||||
|
||||
if (sourceStr == nsnull)
|
||||
return nsnull;
|
||||
|
||||
// Convert from unicode to a destination charset.
|
||||
if (NS_FAILED(ConvertFromUnicode(nsAutoString(destCharset), nsAutoString(sourceStr), &result))) {
|
||||
PR_FREEIF(result);
|
||||
result = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DO_I18N // I have no idea what we should do here.
|
||||
if ((src_csid != dest_csid) || (useMime2))
|
||||
{
|
||||
// Need to convert. See if we can.
|
||||
|
||||
// ### mwelch Much of this code is lifted from
|
||||
// lib/libi18n/mime2fun.c (in particular,
|
||||
// intl_EncodeMimePartIIStr).
|
||||
CCCDataObject obj = nsnull;
|
||||
CCCFunc cvtfunc = nsnull;
|
||||
int srcLen = XP_STRLEN(sourceStr);
|
||||
|
||||
obj = INTL_CreateCharCodeConverter();
|
||||
if (obj == nsnull)
|
||||
return 0;
|
||||
|
||||
/* setup converter from src_csid --> dest_csid */
|
||||
INTL_GetCharCodeConverter(src_csid, dest_csid, obj) ;
|
||||
cvtfunc = INTL_GetCCCCvtfunc(obj);
|
||||
|
||||
if (cvtfunc)
|
||||
{
|
||||
// We can convert, so do it.
|
||||
if (useMime2)
|
||||
// Force MIME-2 encoding so that the charset (if necessary) gets
|
||||
// passed to the Dredd server inline
|
||||
result = INTL_EncodeMimePartIIStr(sourceStr, src_csid, TRUE);
|
||||
else
|
||||
{
|
||||
// Copy the source string before using it for conversion.
|
||||
// You just don't know where those bits have been.
|
||||
char *temp = XP_STRDUP(sourceStr);
|
||||
if (temp)
|
||||
{
|
||||
// (result) will differ from (temp) iff a larger string
|
||||
// were needed to contain the converted chars.
|
||||
// (or so I understand)
|
||||
result = (char *) cvtfunc(obj,
|
||||
(unsigned char*)temp,
|
||||
srcLen);
|
||||
if (result != temp)
|
||||
XP_FREE(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
XP_FREEIF(obj);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
char *
|
||||
nsMsgSearchAdapter::GetImapCharsetParam(const PRUnichar *destCharset)
|
||||
{
|
||||
@ -370,8 +303,10 @@ void
|
||||
nsMsgSearchAdapter::GetSearchCharsets(nsString &srcCharset, nsString& dstCharset)
|
||||
{
|
||||
nsresult rv;
|
||||
// char *defaultCharset = nsMsgI18NGetDefaultMailCharset();
|
||||
nsAutoString defaultCharset; defaultCharset.AssignWithConversion(nsMsgI18NGetDefaultMailCharset());
|
||||
nsAutoString defaultCharset;
|
||||
char *search_charset = nsMsgI18NGetDefaultMailCharset();
|
||||
defaultCharset.AssignWithConversion(search_charset);
|
||||
PR_Free((void *)search_charset);
|
||||
srcCharset = defaultCharset;
|
||||
dstCharset = defaultCharset;
|
||||
|
||||
@ -646,7 +581,7 @@ nsresult nsMsgSearchAdapter::EncodeImapTerm (nsIMsgSearchTerm *term, PRBool real
|
||||
useQuotes = !reallyDredd ||
|
||||
(nsAutoString(convertedValue).FindChar((PRUnichar)' ') != -1);
|
||||
// now convert to char* and escape quoted_specials
|
||||
value = TryToConvertCharset(convertedValue, destCharset, reallyDredd);
|
||||
ConvertFromUnicode(nsAutoString(convertedValue), nsAutoString(destCharset), &value);
|
||||
if (value)
|
||||
{
|
||||
char *oldValue = value;
|
||||
|
@ -701,14 +701,6 @@ nsresult nsMsgSearchTerm::MatchBody (nsIMsgSearchScopeTerm *scope, PRUint32 offs
|
||||
PRBool endOfFile = PR_FALSE; // if retValue == 0, we've hit the end of the file
|
||||
uint32 lines = 0;
|
||||
|
||||
PRBool getConverter = PR_FALSE;
|
||||
#ifdef DO_I18N
|
||||
CCCDataObject conv = INTL_CreateCharCodeConverter();
|
||||
PRInt16 win_csid = INTL_DocToWinCharSetID(foldcsid);
|
||||
PRInt16 mail_csid = INTL_DefaultMailCharSetID(win_csid); // to default mail_csid (e.g. JIS for Japanese)
|
||||
if ((nsnull != conv) && INTL_GetCharCodeConverter(mail_csid, win_csid, conv))
|
||||
getConverter = PR_TRUE;
|
||||
#endif // DO_I18N
|
||||
// Change the sense of the loop so we don't bail out prematurely
|
||||
// on negative terms. i.e. opDoesntContain must look at all lines
|
||||
PRBool boolContinueLoop;
|
||||
@ -733,27 +725,13 @@ nsresult nsMsgSearchTerm::MatchBody (nsIMsgSearchScopeTerm *scope, PRUint32 offs
|
||||
// Do in-place decoding of quoted printable
|
||||
if (isQuotedPrintable)
|
||||
StripQuotedPrintable ((unsigned char*)buf);
|
||||
|
||||
nsCString compare(buf);
|
||||
if (getConverter)
|
||||
{
|
||||
#ifdef DO_I18N
|
||||
// In here we do I18N conversion if we get the converter
|
||||
char *newBody = nsnull;
|
||||
newBody = (char *)INTL_CallCharCodeConverter(conv, (unsigned char *) buf, (int32) PL_strlen(buf));
|
||||
if (newBody && (newBody != buf))
|
||||
{
|
||||
// CharCodeConverter return the char* to the orginal string
|
||||
// we don't want to free body in that case
|
||||
compare = newBody;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
nsCString compare(buf);
|
||||
// ConvertToUnicode(charset, buf, compare);
|
||||
if (compare.Length() > 0) {
|
||||
char startChar = (char) compare.CharAt(0);
|
||||
if (startChar != CR && startChar != LF)
|
||||
{
|
||||
err = MatchString (compare, nsnull, &result);
|
||||
err = MatchString (compare, folderCharset, &result);
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
@ -793,6 +771,7 @@ nsresult nsMsgSearchTerm::MatchRfc2047String (const char *rfc2047string,
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
stringToMatch = decodedString.ToNewUTF8String();
|
||||
mimedecode = PR_TRUE;
|
||||
charset = nsnull;
|
||||
}
|
||||
else
|
||||
stringToMatch = rfc2047string; // Try to match anyway
|
||||
@ -816,75 +795,83 @@ nsresult nsMsgSearchTerm::MatchString (const char *stringToMatch,
|
||||
|
||||
nsresult err = NS_OK;
|
||||
nsCAutoString n_str;
|
||||
const char* n_header = nsnull;
|
||||
const char *utf8 = stringToMatch;
|
||||
if(nsMsgSearchOp::IsEmpty != m_operator) // Save some performance for opIsEmpty
|
||||
{
|
||||
n_header = stringToMatch;
|
||||
n_str = m_value.string;
|
||||
if (charset != nsnull)
|
||||
{
|
||||
nsAutoString srcCharset;
|
||||
srcCharset.AssignWithConversion(charset);
|
||||
nsString out;
|
||||
ConvertToUnicode(srcCharset, stringToMatch ? stringToMatch : "", out);
|
||||
utf8 = out.ToNewUTF8String();
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_operator)
|
||||
{
|
||||
case nsMsgSearchOp::Contains:
|
||||
if ((nsnull != n_header) && ((n_str.GetBuffer())[0]) && /* INTL_StrContains(csid, n_header, n_str) */
|
||||
PL_strcasestr(stringToMatch, n_str))
|
||||
if ((nsnull != utf8) && ((n_str.GetBuffer())[0]) && /* INTL_StrContains(csid, n_header, n_str) */
|
||||
PL_strcasestr(utf8, n_str))
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
case nsMsgSearchOp::DoesntContain:
|
||||
if ((nsnull != n_header) && ((n_str.GetBuffer())[0]) && /* !INTL_StrContains(csid, n_header, n_str) */
|
||||
!PL_strcasestr(stringToMatch, n_str))
|
||||
if ((nsnull != utf8) && ((n_str.GetBuffer())[0]) && /* !INTL_StrContains(csid, n_header, n_str) */
|
||||
!PL_strcasestr(utf8, n_str))
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
case nsMsgSearchOp::Is:
|
||||
if(n_header)
|
||||
if(utf8)
|
||||
{
|
||||
if ((n_str.GetBuffer())[0])
|
||||
{
|
||||
if (n_str.EqualsWithConversion(stringToMatch, PR_TRUE /*ignore case*/) /* INTL_StrIs(csid, n_header, n_str)*/ )
|
||||
if (n_str.EqualsWithConversion(utf8, PR_TRUE /*ignore case*/) /* INTL_StrIs(csid, n_header, n_str)*/ )
|
||||
result = PR_TRUE;
|
||||
}
|
||||
else if (n_header[0] == '\0') // Special case for "is <the empty string>"
|
||||
else if (utf8[0] == '\0') // Special case for "is <the empty string>"
|
||||
result = PR_TRUE;
|
||||
}
|
||||
break;
|
||||
case nsMsgSearchOp::Isnt:
|
||||
if(n_header)
|
||||
if(utf8)
|
||||
{
|
||||
if ((n_str.GetBuffer())[0])
|
||||
{
|
||||
if (!n_str.EqualsWithConversion(stringToMatch, PR_TRUE)/* INTL_StrIs(csid, n_header, n_str)*/ )
|
||||
if (!n_str.EqualsWithConversion(utf8, PR_TRUE)/* INTL_StrIs(csid, n_header, n_str)*/ )
|
||||
result = PR_TRUE;
|
||||
}
|
||||
else if (n_header[0] != '\0') // Special case for "isn't <the empty string>"
|
||||
else if (utf8[0] != '\0') // Special case for "isn't <the empty string>"
|
||||
result = PR_TRUE;
|
||||
}
|
||||
break;
|
||||
case nsMsgSearchOp::IsEmpty:
|
||||
if (!PL_strlen(stringToMatch))
|
||||
if (!PL_strlen(utf8))
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
case nsMsgSearchOp::BeginsWith:
|
||||
#ifdef DO_I18N_YET
|
||||
if((nsnull != n_str) && (nsnull != n_header) && INTL_StrBeginWith(csid, n_header, n_str))
|
||||
if((nsnull != n_str) && (nsnull != utf8) && INTL_StrBeginWith(csid, utf8, n_str))
|
||||
result = PR_TRUE;
|
||||
#else
|
||||
// ### DMB - not the most efficient way to do this.
|
||||
if (PL_strncmp(stringToMatch, n_str, PL_strlen(n_str)) == 0)
|
||||
if (PL_strncmp(utf8, n_str, PL_strlen(n_str)) == 0)
|
||||
result = PR_TRUE;
|
||||
#endif
|
||||
break;
|
||||
case nsMsgSearchOp::EndsWith:
|
||||
{
|
||||
PRUint32 searchStrLen = (PRUint32) PL_strlen(stringToMatch);
|
||||
PRUint32 searchStrLen = (PRUint32) PL_strlen(utf8);
|
||||
if (n_str.Length() <= searchStrLen)
|
||||
{
|
||||
PRInt32 sourceStrOffset = searchStrLen - n_str.Length();
|
||||
if (PL_strcmp(stringToMatch + sourceStrOffset, n_str) == 0)
|
||||
if (PL_strcmp(utf8 + sourceStrOffset, n_str) == 0)
|
||||
result = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#ifdef DO_I18N_YET
|
||||
{
|
||||
if((nsnull != n_str) && (nsnull != n_header) && INTL_StrEndWith(csid, n_header, n_str))
|
||||
if((nsnull != n_str) && (nsnull != utf8) && INTL_StrEndWith(csid, utf8, n_str))
|
||||
result = PR_TRUE;
|
||||
}
|
||||
#else
|
||||
@ -895,6 +882,9 @@ nsresult nsMsgSearchTerm::MatchString (const char *stringToMatch,
|
||||
NS_ASSERTION(PR_FALSE, "invalid operator matching search results");
|
||||
}
|
||||
|
||||
if (utf8 != nsnull && utf8 != stringToMatch)
|
||||
free((void *)utf8);
|
||||
|
||||
*pResult = result;
|
||||
return err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user