From 5a079be1310e45777b228c5528ef21963e32c163 Mon Sep 17 00:00:00 2001 From: "mscott%netscape.com" Date: Thu, 12 Sep 2002 20:45:09 +0000 Subject: [PATCH] Bug #162789 --> Add backend support for filtering and searching based on the sender in an address book. r=navin sr=bienvenu --- .../base/search/public/nsMsgSearchCore.idl | 10 ++- mailnews/base/search/public/nsMsgSearchTerm.h | 9 ++- .../locale/en-US/search-attributes.properties | 4 +- .../locale/en-US/search-operators.properties | 2 + mailnews/base/search/src/Makefile.in | 1 + mailnews/base/search/src/nsMsgImapSearch.cpp | 26 +++++-- mailnews/base/search/src/nsMsgLocalSearch.cpp | 1 + mailnews/base/search/src/nsMsgSearchTerm.cpp | 73 +++++++++++++++++-- 8 files changed, 105 insertions(+), 21 deletions(-) diff --git a/mailnews/base/search/public/nsMsgSearchCore.idl b/mailnews/base/search/public/nsMsgSearchCore.idl index 51ccc03fe9ca..c11b6cb46244 100644 --- a/mailnews/base/search/public/nsMsgSearchCore.idl +++ b/mailnews/base/search/public/nsMsgSearchCore.idl @@ -102,8 +102,8 @@ interface nsMsgSearchAttrib { const nsMsgSearchAttribValue AdditionalEmail = 31; - // 32 - 48, reserved for ab / LDAP; - + // 32 - 46, reserved for ab / LDAP; + const nsMsgSearchAttribValue SenderInAddressBook = 47; const nsMsgSearchAttribValue Label = 48; /* mail only...can search by label */ //49 is for showing customize... in ui headers start from 50 onwards up until 99. const nsMsgSearchAttribValue OtherHeader = 49; /* for mail and news. MUST ALWAYS BE LAST attribute since we can have an arbitrary # of these... */ @@ -140,7 +140,9 @@ interface nsMsgSearchOp { const nsMsgSearchOpValue IsLessThan = 14; const nsMsgSearchOpValue NameCompletion = 15; /* Name Completion operator...as the name implies =) */ - const nsMsgSearchOpValue kNumMsgSearchOperators = 16; /* must be last operator */ + const nsMsgSearchOpValue IsInAB = 16; + const nsMsgSearchOpValue IsntInAB = 17; + const nsMsgSearchOpValue kNumMsgSearchOperators = 18; /* must be last operator */ }; typedef long nsMsgSearchWidgetValue; @@ -206,7 +208,7 @@ typedef struct nsMsgSearchValue (!(_a == nsMsgSearchAttrib::Priority || _a == nsMsgSearchAttrib::Date || \ _a == nsMsgSearchAttrib::MsgStatus || _a == nsMsgSearchAttrib::MessageKey || \ _a == nsMsgSearchAttrib::Size || _a == nsMsgSearchAttrib::AgeInDays || \ - _a == nsMsgSearchAttrib::FolderInfo || _a == nsMsgSearchAttrib::Location)) + _a == nsMsgSearchAttrib::FolderInfo || _a == nsMsgSearchAttrib::Location) || _a == nsMsgSearchAttrib::Label) %} [ptr] native nsSearchMenuItem(nsSearchMenuItem); diff --git a/mailnews/base/search/public/nsMsgSearchTerm.h b/mailnews/base/search/public/nsMsgSearchTerm.h index 8eaebf9bac59..38471faf882b 100644 --- a/mailnews/base/search/public/nsMsgSearchTerm.h +++ b/mailnews/base/search/public/nsMsgSearchTerm.h @@ -45,6 +45,9 @@ #include "nsIMsgSearchScopeTerm.h" #include "nsIMsgSearchTerm.h" +// needed to search for addresses in address books +#include "nsIAbMDBDirectory.h" + #define EMPTY_MESSAGE_LINE(buf) (buf[0] == nsCRT::CR || buf[0] == nsCRT::LF || buf[0] == '\0') class nsMsgSearchTerm : public nsIMsgSearchTerm @@ -102,6 +105,7 @@ public: nsMsgSearchBooleanOperator m_booleanOp; // boolean operator to be applied to this search term and the search term which precedes it. nsCString m_arbitraryHeader; // user specified string for the name of the arbitrary header to be used in the search // only has a value when m_attribute = attribOtherHeader!!!! + protected: nsresult MatchString (const char *stringToMatch, const char *charset, PRBool *pResult); @@ -110,7 +114,10 @@ protected: nsMsgSearchOpValue ParseOperator(char *inStream); nsresult ParseValue(char *inStream); nsresult InitHeaderAddressParser(); - + nsresult InitializeAddressBook(); + nsresult MatchInAddressBook(const char * aAddress, PRBool *pResult); + // fields used by search in address book + nsCOMPtr mDirectory; }; #endif diff --git a/mailnews/base/search/resources/locale/en-US/search-attributes.properties b/mailnews/base/search/resources/locale/en-US/search-attributes.properties index 38b936d7f6cf..aae0a7f89a4c 100644 --- a/mailnews/base/search/resources/locale/en-US/search-attributes.properties +++ b/mailnews/base/search/resources/locale/en-US/search-attributes.properties @@ -48,7 +48,7 @@ 44=reserved for AB 45=reserved for AB 46=reserved for AB -47=reserved for AB -48=reserved for AB +47=Sender +48=Label # don't use above 49 49=Customize... diff --git a/mailnews/base/search/resources/locale/en-US/search-operators.properties b/mailnews/base/search/resources/locale/en-US/search-operators.properties index 136c9a56dd9c..ea6e7800ca4b 100644 --- a/mailnews/base/search/resources/locale/en-US/search-operators.properties +++ b/mailnews/base/search/resources/locale/en-US/search-operators.properties @@ -20,4 +20,6 @@ 14=is less than 15=NameCompletion +16=is in my address book +17=isn't in my address book diff --git a/mailnews/base/search/src/Makefile.in b/mailnews/base/search/src/Makefile.in index 99b7d470ed7f..311fdefca7f6 100644 --- a/mailnews/base/search/src/Makefile.in +++ b/mailnews/base/search/src/Makefile.in @@ -46,6 +46,7 @@ REQUIRES = xpcom \ msgnews \ txmgr \ import \ + addrbook \ docshell \ $(NULL) diff --git a/mailnews/base/search/src/nsMsgImapSearch.cpp b/mailnews/base/search/src/nsMsgImapSearch.cpp index bd92d0e57eb2..3180c130d9c9 100644 --- a/mailnews/base/search/src/nsMsgImapSearch.cpp +++ b/mailnews/base/search/src/nsMsgImapSearch.cpp @@ -192,6 +192,12 @@ nsresult nsMsgSearchValidityManager::InitOfflineMailTable () m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1); m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1); + // don't enable this until we are ready to fork rules.dat + //m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1); + //m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1); + //m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1); + //m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1); + m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1); m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1); m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::To, nsMsgSearchOp::DoesntContain, 1); @@ -280,13 +286,13 @@ nsresult nsMsgSearchValidityManager::InitOfflineMailTable () m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::AgeInDays, nsMsgSearchOp::Is, 1); m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1); - m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1); - m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1); - m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1); - m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1); - m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1); - m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1); - m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1); + m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Contains, 1); + m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1); + m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::Is, 1); + m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1); + m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::BeginsWith, 1); + m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1); + m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::OtherHeader, nsMsgSearchOp::EndsWith, 1); } @@ -394,6 +400,12 @@ nsresult nsMsgSearchValidityManager::InitOnlineMailFilterTable () m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1); m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1); + // don't enable this until we are ready to fork rules.dat + //m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1); + //m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1); + //m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1); + //m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1); + m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1); m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1); m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::To, nsMsgSearchOp::DoesntContain, 1); diff --git a/mailnews/base/search/src/nsMsgLocalSearch.cpp b/mailnews/base/search/src/nsMsgLocalSearch.cpp index e99cd0ca47a1..aa07ad68df9a 100644 --- a/mailnews/base/search/src/nsMsgLocalSearch.cpp +++ b/mailnews/base/search/src/nsMsgLocalSearch.cpp @@ -567,6 +567,7 @@ nsresult nsMsgSearchOfflineMail::MatchTerms(nsIMsgDBHdr *msgToMatch, charset = (const char*)defaultCharset; switch (attrib) { + case nsMsgSearchAttrib::SenderInAddressBook: case nsMsgSearchAttrib::Sender: msgToMatch->GetAuthor(getter_Copies(matchString)); err = pTerm->MatchRfc822String (matchString, charset, charsetOverride, &result); diff --git a/mailnews/base/search/src/nsMsgSearchTerm.cpp b/mailnews/base/search/src/nsMsgSearchTerm.cpp index 78d03ec5a303..a3c31c6d9d5a 100644 --- a/mailnews/base/search/src/nsMsgSearchTerm.cpp +++ b/mailnews/base/search/src/nsMsgSearchTerm.cpp @@ -58,6 +58,8 @@ #include "nsTime.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" + +#include "nsIRDFService.h" #include "nsISupportsObsolete.h" //--------------------------------------------------------------------------- @@ -86,7 +88,8 @@ nsMsgSearchAttribEntry SearchAttribEntryTable[] = {nsMsgSearchAttrib::MsgStatus, "status"}, {nsMsgSearchAttrib::To, "to"}, {nsMsgSearchAttrib::CC, "cc"}, - {nsMsgSearchAttrib::ToOrCC, "to or cc"} + {nsMsgSearchAttrib::ToOrCC, "to or cc"}, + {nsMsgSearchAttrib::SenderInAddressBook, "from in ab"} }; // Take a string which starts off with an attribute @@ -207,7 +210,9 @@ nsMsgSearchOperatorEntry SearchOperatorEntryTable[] = {nsMsgSearchOp::IsHigherThan, "is higher than"}, {nsMsgSearchOp::IsLowerThan, "is lower than"}, {nsMsgSearchOp::BeginsWith, "begins with"}, - {nsMsgSearchOp::EndsWith, "ends with"} + {nsMsgSearchOp::EndsWith, "ends with"}, + {nsMsgSearchOp::IsInAB, "is in ab"}, + {nsMsgSearchOp::IsntInAB, "isn't in ab"}, }; nsresult NS_MsgGetOperatorFromString(const char *string, PRInt16 *op) @@ -816,7 +821,50 @@ nsresult nsMsgSearchTerm::MatchBody (nsIMsgSearchScopeTerm *scope, PRUint32 offs return err; } +nsresult nsMsgSearchTerm::InitializeAddressBook() +{ + // the search attribute value has the URI for the address book we need to load. + // we need both the database and the directory. + nsresult rv = NS_OK; + if (mDirectory) + { + nsXPIDLCString dirURI; + mDirectory->GetDirUri(getter_Copies(dirURI)); + if (strcmp(dirURI.get(), m_value.string)) + mDirectory = NULL; // clear out the directory....we are no longer pointing to the right one + } + if (!mDirectory) + { + nsCOMPtr rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1",&rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resource; + rv = rdfService->GetResource(m_value.string, getter_AddRefs(resource)); + NS_ENSURE_SUCCESS(rv, rv); + + mDirectory = do_QueryInterface(resource, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +nsresult nsMsgSearchTerm::MatchInAddressBook(const char * aAddress, PRBool *pResult) +{ + nsresult rv = InitializeAddressBook(); + *pResult = PR_FALSE; + + if (mDirectory) + { + PRBool cardExists = PR_FALSE; + rv = mDirectory->HasCardForEmailAddress(aAddress, &cardExists); + if ( (m_operator == nsMsgSearchOp::IsInAB && cardExists) || (m_operator == nsMsgSearchOp::IsntInAB && !cardExists)) + *pResult = PR_TRUE; + } + + return rv; +} // *pResult is PR_FALSE when strings don't match, PR_TRUE if they do. nsresult nsMsgSearchTerm::MatchRfc2047String (const char *rfc2047string, @@ -836,7 +884,12 @@ nsresult nsMsgSearchTerm::MatchRfc2047String (const char *rfc2047string, charset, charsetOverride, PR_FALSE); - res = MatchString(stringToMatch ? stringToMatch : rfc2047string, + if (nsMsgSearchAttrib::SenderInAddressBook == m_attribute) + { + res = MatchInAddressBook(stringToMatch ? stringToMatch : rfc2047string, pResult); + } + else + res = MatchString(stringToMatch ? stringToMatch : rfc2047string, nsnull, pResult); PR_FREEIF(stringToMatch); @@ -957,7 +1010,6 @@ nsresult nsMsgSearchTerm::GetMatchAllBeforeDeciding (PRBool *aResult) return NS_OK; } - nsresult nsMsgSearchTerm::MatchRfc822String (const char *string, const char *charset, PRBool charsetOverride, PRBool *pResult) { if (!pResult) @@ -997,9 +1049,16 @@ nsresult nsMsgSearchTerm::MatchRfc822String (const char *string, const char *cha { walkNames = names + namePos; walkAddresses = addresses + addressPos; - err = MatchRfc2047String (walkNames.get(), charset, charsetOverride, &result); - if (boolContinueLoop == result) - err = MatchRfc2047String (walkAddresses.get(), charset, charsetOverride, &result); + if (nsMsgSearchAttrib::SenderInAddressBook == m_attribute) + { + err = MatchRfc2047String (walkAddresses.get(), charset, charsetOverride, &result); + } + else + { + err = MatchRfc2047String (walkNames.get(), charset, charsetOverride, &result); + if (boolContinueLoop == result) + err = MatchRfc2047String (walkAddresses.get(), charset, charsetOverride, &result); + } namePos += walkNames.Length() + 1; addressPos += walkAddresses.Length() + 1;