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:
taka%netscape.com 2001-01-26 13:50:44 +00:00
parent 3131997624
commit 11558b490b
6 changed files with 61 additions and 126 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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;
}