more work on search, not really part of build

This commit is contained in:
bienvenu%netscape.com 2000-04-18 04:47:50 +00:00
Родитель 0f18167887
Коммит a971e7d302
5 изменённых файлов: 223 добавлений и 143 удалений

Просмотреть файл

@ -23,6 +23,8 @@
#include "nsISupports.idl"
#include "nsMsgSearchCore.idl"
interface nsMsgResultElement;
//////////////////////////////////////////////////////////////////////////////
// The Msg Search Session is an interface designed to make constructing
// searches easier. Clients typically build up search terms, and then run
@ -84,6 +86,8 @@ interface nsIMsgSearchSession : nsISupports {
[noscript] nsMsgSearchType SetSearchParam(in nsMsgSearchType type,
in voidStar param);
[noscript] void AddResultElement(in nsMsgResultElement element);
readonly attribute long numResults;
/* these longs are all actually of type nsMsgSearchBooleanOp */

Просмотреть файл

@ -36,6 +36,14 @@
// the special smarts for that protocol.
//-----------------------------------------------------------------------------
inline PRBool IsStringAttribute (nsMsgSearchAttribute a)
{
return ! (a == nsMsgSearchAttrib::Priority || a == nsMsgSearchAttrib::Date ||
a == nsMsgSearchAttrib::MsgStatus || a == nsMsgSearchAttrib::MessageKey ||
a == nsMsgSearchAttrib::Size || a == nsMsgSearchAttrib::AgeInDays ||
a == nsMsgSearchAttrib::FolderInfo);
}
class nsMsgSearchAdapter : public nsIMsgSearchAdapter
{
public:
@ -59,15 +67,15 @@ public:
static nsresult EncodeImap (char **ppEncoding,
nsMsgSearchTermArray &searchTerms,
PRInt16 src_csid,
PRInt16 dest_csid,
const PRUnichar *srcCharset,
const PRUnichar *destCharset,
PRBool reallyDredd = PR_FALSE);
static nsresult EncodeImapValue(char *encoding, const char *value, PRBool useQuotes, PRBool reallyDredd);
static char *TryToConvertCharset(char *sourceStr, PRInt16 src_csid, PRInt16 dest_csid, PRBool useMIME2Style);
static char *GetImapCharsetParam(PRInt16 dest_csid);
void GetSearchCSIDs(PRInt16& src_csid, PRInt16& dst_csid);
static char *TryToConvertCharset(char *sourceStr, const PRUnichar *srcCharset, const PRUnichar *destCharset, PRBool useMIME2Style);
static char *GetImapCharsetParam(const PRUnichar *destCharset);
void GetSearchCharsets(nsString &srcCharset, nsString &destCharset);
// This stuff lives in the base class because the IMAP search syntax
// is used by the Dredd SEARCH command as well as IMAP itself
@ -103,7 +111,7 @@ protected:
char *TransformSpacesToStars (const char *, msg_TransformType transformType);
nsresult OpenNewsResultInUnknownGroup (nsMsgResultElement*);
static nsresult EncodeImapTerm (nsMsgSearchTerm *, PRBool reallyDredd, PRInt16 src_csid, PRInt16 dest_csid, char **ppOutTerm);
static nsresult EncodeImapTerm (nsMsgSearchTerm *, PRBool reallyDredd, const char*srcCharset, PRInt16 dest_csid, char **ppOutTerm);
};
#endif

Просмотреть файл

@ -14,11 +14,18 @@
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "msgCore.h"
#include "nsMsgSearchAdapter.h"
#include "nsXPIDLString.h"
#include "nsMsgSearchScopeTerm.h"
#include "nsMsgResultElement.h"
#include "nsMsgSearchTerm.h"
#include "nsIMsgHdr.h"
// Implementation of search for IMAP mail folders
@ -26,170 +33,155 @@
//---------- Adapter class for searching online (IMAP) folders ----------------
//-----------------------------------------------------------------------------
const char *msg_SearchOnlineMail::m_kSearchTemplate = "SEARCH%s%s";
msg_SearchOnlineMail::msg_SearchOnlineMail (MSG_ScopeTerm *scope, MSG_SearchTermArray &termList) : msg_SearchAdapter (scope, termList)
class nsMsgSearchOnlineMail : public nsMsgSearchAdapter
{
public:
nsMsgSearchOnlineMail (nsMsgSearchScopeTerm *scope, nsMsgSearchTermArray &termList);
virtual ~nsMsgSearchOnlineMail ();
NS_IMETHOD ValidateTerms ();
NS_IMETHOD Search ();
virtual const char *GetEncoding ();
static nsresult Encode (nsCString *ppEncoding, nsMsgSearchTermArray &searchTerms, const PRUnichar *srcCharset, const PRUnichar *destCharset);
nsresult AddResultElement (nsIMsgDBHdr *);
protected:
nsCString m_encoding;
};
nsMsgSearchOnlineMail::nsMsgSearchOnlineMail (nsMsgSearchScopeTerm *scope, nsMsgSearchTermArray &termList) : nsMsgSearchAdapter (scope, termList)
{
m_encoding = NULL;
}
msg_SearchOnlineMail::~msg_SearchOnlineMail ()
nsMsgSearchOnlineMail::~nsMsgSearchOnlineMail ()
{
XP_FREEIF(m_encoding);
}
MSG_SearchError msg_SearchOnlineMail::ValidateTerms ()
nsresult nsMsgSearchOnlineMail::ValidateTerms ()
{
MSG_SearchError err = msg_SearchAdapter::ValidateTerms ();
if (SearchError_Success == err)
{
// ### mwelch Figure out the charsets to use
// for the search terms and targets.
PRInt16 src_csid, dst_csid;
GetSearchCSIDs(src_csid, dst_csid);
nsresult err = nsMsgSearchAdapter::ValidateTerms ();
if (NS_SUCCEEDED(err))
{
// ### mwelch Figure out the charsets to use
// for the search terms and targets.
nsString srcCharset, dstCharset;
GetSearchCharsets(srcCharset, dstCharset);
// do IMAP specific validation
char *tmpEncoding = NULL;
err = Encode (&tmpEncoding, m_searchTerms, src_csid, dst_csid);
if (SearchError_Success == err)
{
// we are searching an online folder, right?
PR_ASSERT(m_scope->m_folder->GetType() == FOLDER_IMAPMAIL);
MSG_IMAPFolderInfoMail *imapFolder = (MSG_IMAPFolderInfoMail *) m_scope->m_folder;
m_encoding = CreateImapSearchUrl(imapFolder->GetHostName(),
imapFolder->GetOnlineName(),
imapFolder->GetOnlineHierarchySeparator(),
tmpEncoding,
PR_TRUE); // return UIDs
delete [] tmpEncoding;
}
else
if (err == SearchError_ScopeAgreement)
PR_ASSERT(PR_FALSE);
}
return err;
// do IMAP specific validation
err = Encode (&m_encoding, m_searchTerms, srcCharset.GetUnicode(), dstCharset.GetUnicode());
NS_ASSERTION(NS_SUCCEEDED(err), "failed to encode imap search");
}
return err;
}
const char *msg_SearchOnlineMail::GetEncoding ()
const char *nsMsgSearchOnlineMail::GetEncoding ()
{
return m_encoding;
}
void msg_SearchOnlineMail::PreExitFunction (URL_Struct * /*url*/, int status, MWContext *context)
nsresult nsMsgSearchOnlineMail::AddResultElement (nsIMsgDBHdr *pHeaders)
{
MSG_SearchFrame *frame = MSG_SearchFrame::FromContext (context);
msg_SearchAdapter *adapter = frame->GetRunningAdapter();
nsresult err = NS_OK;
if (status == MK_INTERRUPTED)
{
adapter->Abort();
frame->EndCylonMode();
}
else
{
frame->m_idxRunningScope++;
if (frame->m_idxRunningScope >= frame->m_scopeList.GetSize())
frame->EndCylonMode();
}
}
// stolen from offline mail, talk to phil
MSG_SearchError msg_SearchOnlineMail::AddResultElement (NeoMessageHdr *pHeaders)
{
MSG_SearchError err = SearchError_Success;
MSG_ResultElement *newResult = new MSG_ResultElement (this);
nsMsgResultElement *newResult = new nsMsgResultElement (this);
NS_ASSERTION (newResult, "out of memory getting result element");
if (newResult)
{
PR_ASSERT (newResult);
// This isn't very general. Just add the headers we think we'll be interested in
// to the list of attributes per result element.
MSG_SearchValue *pValue = new MSG_SearchValue;
nsMsgSearchValue *pValue = new nsMsgSearchValue;
if (pValue)
{
ENeoString subject;
pValue->attribute = attribSubject;
char *reString = (pHeaders->GetFlags() & kHasRe) ? "Re:" : "";
pHeaders->GetSubject(subject);
nsXPIDLCString subject;
PRUint32 flags;
pValue->attribute = nsMsgSearchAttrib::Subject;
pHeaders->GetFlags(&flags);
char *reString = (flags & MSG_FLAG_HAS_RE) ? "Re:" : "";
pHeaders->GetSubject(getter_Copies(subject));
pValue->u.string = PR_smprintf ("%s%s", reString, (const char*) subject); // hack. invoke cast operator by force
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribSender;
nsXPIDLCString author;
pValue->attribute = nsMsgSearchAttrib::Sender;
pValue->u.string = (char*) PR_Malloc(64);
if (pValue->u.string)
{
pHeaders->GetAuthor(pValue->u.string, 64);
pHeaders->GetAuthor(getter_Copies(author));
PL_strncpy(pValue->u.string, (const char *) author, 64);
newResult->AddValue (pValue);
}
else
err = SearchError_OutOfMemory;
err = NS_ERROR_OUT_OF_MEMORY;
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribDate;
pValue->u.date = pHeaders->GetDate();
pValue->attribute = nsMsgSearchAttrib::Date;
pHeaders->GetDate(&pValue->u.date);
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribMsgStatus;
pValue->u.msgStatus = pHeaders->GetFlags();
pValue->attribute = nsMsgSearchAttrib::MsgStatus;
pHeaders->GetFlags(&pValue->u.msgStatus);
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribPriority;
pValue->u.priority = pHeaders->GetPriority();
pValue->attribute = nsMsgSearchAttrib::Priority;
pHeaders->GetPriority(&pValue->u.priority);
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribLocation;
pValue->u.string = nsCRT::strdup(m_scope->m_folder->GetName());
nsXPIDLString folderName;
pValue->attribute = nsMsgSearchAttrib::Location;
m_scope->m_folder->GetName(getter_Copies(folderName));
pValue->u.wString = nsCRT::strdup((const PRUnichar *) folderName);
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribMessageKey;
pValue->u.key = pHeaders->GetMessageKey();
pValue->attribute = nsMsgSearchAttrib::MessageKey;
pHeaders->GetMessageKey(&pValue->u.key);
newResult->AddValue (pValue);
}
pValue = new MSG_SearchValue;
pValue = new nsMsgSearchValue;
if (pValue)
{
pValue->attribute = attribSize;
pValue->u.size = pHeaders->GetByteLength();
pValue->attribute = nsMsgSearchAttrib::Size;
pHeaders->GetMessageSize(&pValue->u.size);
newResult->AddValue (pValue);
}
if (!pValue)
err = SearchError_OutOfMemory;
m_scope->m_frame->AddResultElement (newResult);
err = NS_ERROR_OUT_OF_MEMORY;
m_scope->m_searchSession->AddResultElement (newResult);
}
return err;
}
#define WHITESPACE " \015\012" // token delimiter
SEARCH_API void MSG_AddImapSearchHit (MWContext *context, const char *resultLine)
#if 0 // this code belongs in imap parser or protocol object
void MSG_AddImapSearchHit (MWContext *context, const char *resultLine)
{
MSG_SearchFrame *frame = MSG_SearchFrame::FromContext (context);
if (frame)
@ -198,7 +190,7 @@ SEARCH_API void MSG_AddImapSearchHit (MWContext *context, const char *resultLine
if (adapter)
{
// open the relevant IMAP db
MailDB *imapDB = NULL;
MailDB *imapDB = nsnull;
PRBool wasCreated = PR_FALSE;
ImapMailDB::Open(adapter->m_scope->m_folder->GetMailFolderInfo()->GetPathname(),
PR_FALSE, // do not create if not found
@ -234,7 +226,7 @@ SEARCH_API void MSG_AddImapSearchHit (MWContext *context, const char *resultLine
shownUpdateAlert = PR_TRUE;
}
hitUidToken = XP_STRTOK(NULL, WHITESPACE);
hitUidToken = XP_STRTOK(nsnull, WHITESPACE);
}
}
@ -247,35 +239,37 @@ SEARCH_API void MSG_AddImapSearchHit (MWContext *context, const char *resultLine
}
else
{
PR_ASSERT(PR_FALSE); // apparently, this was left over from trying to do filtering on the server
NS_ASSERTION(PR_FALSE, "missing search frame?"); // apparently, this was left over from trying to do filtering on the server
}
}
#endif // 0
MSG_SearchError msg_SearchOnlineMail::Search ()
nsresult nsMsgSearchOnlineMail::Search ()
{
// we should never end up here for a purely online
// folder. We might for an offline IMAP folder.
MSG_SearchError err = SearchError_NotImplemented;
nsresult err = NS_ERROR_NOT_IMPLEMENTED;
return err;
}
MSG_SearchError msg_SearchOnlineMail::Encode (char **ppEncoding, MSG_SearchTermArray &searchTerms, PRInt16 src_csid, PRInt16 dest_csid)
nsresult nsMsgSearchOnlineMail::Encode (nsCString *pEncoding, nsMsgSearchTermArray &searchTerms, const PRUnichar *srcCharset, const PRUnichar *destCharset)
{
*ppEncoding = NULL;
char *imapTerms = NULL;
char *imapTerms = nsnull;
//check if searchTerms are ascii only
PRBool asciiOnly = PR_TRUE;
if ( !(src_csid & CODESET_MASK == STATEFUL || src_csid & CODESET_MASK == WIDECHAR) ) //assume all single/multiple bytes charset has ascii as subset
// ### what's this mean in the NWO?????
if (PR_TRUE) // !(srcCharset & CODESET_MASK == STATEFUL || srcCharset & CODESET_MASK == WIDECHAR) ) //assume all single/multiple bytes charset has ascii as subset
{
int termCount = searchTerms.GetSize();
int termCount = searchTerms.Count();
int i = 0;
for (i = 0; i < termCount && asciiOnly; i++)
{
MSG_SearchTerm *term = searchTerms.GetAt(i);
nsMsgSearchTerm *term = searchTerms.ElementAt(i);
if (IsStringAttribute(term->m_attribute))
{
char *pchar = term->m_value.u.string;
@ -293,34 +287,29 @@ MSG_SearchError msg_SearchOnlineMail::Encode (char **ppEncoding, MSG_SearchTermA
else
asciiOnly = PR_FALSE;
nsAutoString usAsciiCharSet = "us-ascii";
// Get the optional CHARSET parameter, in case we need it.
char *csname = GetImapCharsetParam(asciiOnly ? CS_ASCII : dest_csid);
char *csname = GetImapCharsetParam(asciiOnly ? usAsciiCharSet.GetUnicode() : destCharset);
MSG_SearchError err = msg_SearchAdapter::EncodeImap (&imapTerms,searchTerms, src_csid, asciiOnly ? CS_ASCII : dest_csid, PR_FALSE);
if (SearchError_Success == err)
{
int len = nsCRT::strlen(m_kSearchTemplate) + nsCRT::strlen(imapTerms) + (csname ? nsCRT::strlen(csname) : 0) + 1;
*ppEncoding = new char [len];
if (*ppEncoding)
{
PR_snprintf (*ppEncoding, len, m_kSearchTemplate,
csname ? csname : "", imapTerms);
}
else
err = SearchError_OutOfMemory;
}
XP_FREEIF(csname);
return err;
nsresult err = nsMsgSearchAdapter::EncodeImap (&imapTerms, searchTerms, srcCharset, asciiOnly ? usAsciiCharSet.GetUnicode(): destCharset, PR_FALSE);
if (NS_SUCCEEDED(err))
{
pEncoding->Append("SEARCH");
if (csname)
pEncoding->Append(csname);
pEncoding->Append(imapTerms);
}
PR_FREEIF(csname);
return err;
}
MSG_SearchError msg_SearchValidityManager::InitOfflineMailTable ()
#if 0
nsresult nsMsgSearchValidityManager::InitOfflineMailTable ()
{
PR_ASSERT (NULL == m_offlineMailTable);
MSG_SearchError err = NewTable (&m_offlineMailTable);
PR_ASSERT (nsnull == m_offlineMailTable);
nsresult err = NewTable (&m_offlineMailTable);
if (SearchError_Success == err)
if (NS_SUCCEEDED(err))
{
m_offlineMailTable->SetAvailable (attribSender, opContains, 1);
m_offlineMailTable->SetEnabled (attribSender, opContains, 1);
@ -437,12 +426,12 @@ MSG_SearchError msg_SearchValidityManager::InitOfflineMailTable ()
}
MSG_SearchError msg_SearchValidityManager::InitOnlineMailTable ()
nsresult nsMsgSearchValidityManager::InitOnlineMailTable ()
{
PR_ASSERT (NULL == m_onlineMailTable);
MSG_SearchError err = NewTable (&m_onlineMailTable);
PR_ASSERT (nsnull == m_onlineMailTable);
nsresult err = NewTable (&m_onlineMailTable);
if (SearchError_Success == err)
if (NS_SUCCEEDED(err))
{
m_onlineMailTable->SetAvailable (attribSender, opContains, 1);
m_onlineMailTable->SetEnabled (attribSender, opContains, 1);
@ -506,7 +495,7 @@ MSG_SearchError msg_SearchValidityManager::InitOnlineMailTable ()
}
MSG_SearchError msg_SearchValidityManager::InitOnlineMailFilterTable ()
nsresult nsMsgSearchValidityManager::InitOnlineMailFilterTable ()
{
// Oh what a tangled web...
//
@ -516,10 +505,10 @@ MSG_SearchError msg_SearchValidityManager::InitOnlineMailFilterTable ()
// is supposed to be the same as offline mail, except that the body
// attribute is omitted
PR_ASSERT (NULL == m_onlineMailFilterTable);
MSG_SearchError err = NewTable (&m_onlineMailFilterTable);
PR_ASSERT (nsnull == m_onlineMailFilterTable);
nsresult err = NewTable (&m_onlineMailFilterTable);
if (SearchError_Success == err)
if (NS_SUCCEEDED(err))
{
m_onlineMailFilterTable->SetAvailable (attribSender, opContains, 1);
m_onlineMailFilterTable->SetEnabled (attribSender, opContains, 1);
@ -621,3 +610,4 @@ MSG_SearchError msg_SearchValidityManager::InitOnlineMailFilterTable ()
return err;
}
#endif

Просмотреть файл

@ -23,6 +23,12 @@
#include "msgCore.h"
#include "nsMsgSearchCore.h"
#include "nsMsgSearchAdapter.h"
#include "nsMsgSearchScopeTerm.h"
#include "nsMsgI18N.h"
#include "nsIPref.h"
#include "nsXPIDLString.h"
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
NS_IMETHODIMP nsMsgSearchAdapter::FindTargetFolder(const nsMsgResultElement *,nsIMsgFolder * *)
{
@ -58,3 +64,57 @@ NS_IMETHODIMP nsMsgSearchAdapter::Abort ()
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsMsgSearchAdapter::GetSearchCharsets(nsString &srcCharset, nsString& dstCharset)
{
// char *defaultCharset = nsMsgI18NGetDefaultMailCharset();
nsAutoString defaultCharset = nsMsgI18NGetDefaultMailCharset();
srcCharset = defaultCharset;
dstCharset = defaultCharset;
if (m_scope)
{
// ### DMB is there a way to get the charset for the "window"?
// Ask the newsgroup/folder for its csid.
if (m_scope->m_folder)
{
nsXPIDLString folderCharset;
m_scope->m_folder->GetCharset(getter_Copies(folderCharset));
dstCharset = folderCharset;
}
}
// If
// the destination is still CS_DEFAULT, make the destination match
// the source. (CS_DEFAULT is an indication that the charset
// was undefined or unavailable.)
// ### well, it's not really anymore. Is there an equivalent?
if (!nsCRT::strcmp(dstCharset.GetUnicode(), defaultCharset.GetUnicode()))
dstCharset = srcCharset;
PRBool forceAscii = PR_FALSE;
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = prefs->GetBoolPref("mailnews.force_ascii_search", &forceAscii);
}
if (forceAscii)
{
// Special cases to use in order to force US-ASCII searching with Latin1
// or MacRoman text. Eurgh. This only has to happen because IMAP
// and Dredd servers currently (4/23/97) only support US-ASCII.
//
// If the dest csid is ISO Latin 1 or MacRoman, attempt to convert the
// source text to US-ASCII. (Not for now.)
// if ((dst_csid == CS_LATIN1) || (dst_csid == CS_MAC_ROMAN))
dstCharset = "us-ascii";
}
}

Просмотреть файл

@ -26,6 +26,8 @@
#include "nsMsgSearchSession.h"
#include "nsMsgResultElement.h"
#include "nsMsgSearchTerm.h"
#include "nsIMsgMessageService.h"
#include "nsMsgUtils.h"
#include "nsXPIDLString.h"
NS_IMPL_ISUPPORTS2(nsMsgSearchSession, nsIMsgSearchSession, nsIUrlListener)
@ -344,8 +346,15 @@ nsresult nsMsgSearchSession::BuildUrlQueue ()
nsresult nsMsgSearchSession::GetNextUrl()
{
nsCString nextUrl;
nsCOMPtr <nsIMsgMessageService> msgService;
m_urlQueue.CStringAt(0, nextUrl);
return NS_OK;
nsresult rv = GetMessageServiceFromURI(nextUrl.GetBuffer(), getter_AddRefs(msgService));
if (NS_SUCCEEDED(rv) && msgService)
msgService->Search(this, m_window, nextUrl.GetBuffer());
return rv;
}
@ -400,6 +409,15 @@ nsresult nsMsgSearchSession::SearchWOUrls ()
}
NS_IMETHODIMP nsMsgSearchSession::AddResultElement (nsMsgResultElement *element)
{
NS_ASSERTION(element, "no null elements");
m_resultList.AppendElement (element);
return NS_OK;
}
void nsMsgSearchSession::DestroyResultList ()
{