diff --git a/mozilla/mailnews/base/search/Makefile.in b/mozilla/mailnews/base/search/Makefile.in new file mode 100644 index 00000000000..0a9ceea9fa6 --- /dev/null +++ b/mozilla/mailnews/base/search/Makefile.in @@ -0,0 +1,34 @@ +#!gmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src + +ifdef ENABLE_TESTS +DIRS += tests +endif + +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/mailnews/base/search/makefile.win b/mozilla/mailnews/base/search/makefile.win new file mode 100644 index 00000000000..b768a51d92c --- /dev/null +++ b/mozilla/mailnews/base/search/makefile.win @@ -0,0 +1,24 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH=..\..\.. + +#tests no tests yet + +DIRS=public src + +include <$(DEPTH)\config\rules.mak> diff --git a/mozilla/mailnews/base/search/public/MANIFEST b/mozilla/mailnews/base/search/public/MANIFEST new file mode 100644 index 00000000000..594c9a1d4d1 --- /dev/null +++ b/mozilla/mailnews/base/search/public/MANIFEST @@ -0,0 +1,25 @@ +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1999 Netscape Communications Corporation. All Rights +# Reserved. +# +# This is a list of local files which get copied to the mozilla:dist:mailnews directory +# + + +nsIMsgFilter.h +nsIMsgFilterService.h +nsMsgFilterCore.h +nsIMsgFilterList.h +nsIMsgSearchSession.h +nsMsgSearchCore.h diff --git a/mozilla/mailnews/base/search/public/Makefile.in b/mozilla/mailnews/base/search/public/Makefile.in new file mode 100644 index 00000000000..fd7fea96279 --- /dev/null +++ b/mozilla/mailnews/base/search/public/Makefile.in @@ -0,0 +1,39 @@ +#!gmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1999 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +EXPORTS= \ + nsIMsgFilter.h \ + nsIMsgFilterService.h \ + nsMsgFilterCore.h \ + nsIMsgFilterList.h \ + nsIMsgSearchSession.h \ + nsMsgSearchCore.h \ + $(NULL) + +IDLSRCS = \ + $(NULL) +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/mailnews/base/search/public/makefile.win b/mozilla/mailnews/base/search/public/makefile.win new file mode 100644 index 00000000000..594cf40aa83 --- /dev/null +++ b/mozilla/mailnews/base/search/public/makefile.win @@ -0,0 +1,35 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1999 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH=..\..\..\.. + +IDLSRCS = \ + $(NULL) + +EXPORTS = \ + nsIMsgFilter.h \ + nsIMsgFilterService.h \ + nsMsgFilterCore.h \ + nsIMsgFilterList.h \ + nsIMsgSearchSession.h \ + nsMsgSearchCore.h \ + $(NULL) + +MODULE=mailnews + + +include <$(DEPTH)\config\rules.mak> diff --git a/mozilla/mailnews/base/search/public/nsIMsgFilter.h b/mozilla/mailnews/base/search/public/nsIMsgFilter.h new file mode 100644 index 00000000000..12f2ea1a3b9 --- /dev/null +++ b/mozilla/mailnews/base/search/public/nsIMsgFilter.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _nsIMsgFilter_H_ +#define _nsIMsgFilter_H_ + +#include "nscore.h" +#include "nsISupports.h" +#include "nsMsgFilterCore.h" + +// 605db0f8-04a1-11d3-a50a-0060b0fc04b7 +#define NS_IMSGFILTER_IID \ +{ 0x605db0f8, 0x04a1, 0x11d3, \ + { 0xa5, 0x0a, 0x0, 0x60, 0xb0, 0xfc, 0x04, 0xb7 } } + +class nsIMsgFilter : public nsISupports +{ +public: + static const nsIID& GetIID() { static nsIID iid = NS_IMSGFILTER_IID; return iid; } + + NS_IMETHOD GetFilterType(nsMsgFilterType *filterType)= 0; + NS_IMETHOD EnableFilter(XP_Bool enable)= 0; + NS_IMETHOD IsFilterEnabled(PRBool *enabled)= 0; + NS_IMETHOD GetFilterName(char **name)= 0; + NS_IMETHOD SetFilterName(char *name)= 0; + NS_IMETHOD GetFilterDesc(char **description)= 0; + NS_IMETHOD SetFilterDesc(char *description)= 0; + + NS_IMETHOD AddTerm( + nsMsgSearchAttribute attrib, /* attribute for this term */ + nsMsgSearchOperator op, /* operator e.g. opContains */ + nsMsgSearchValue *value, /* value e.g. "Dogbert" */ + PRBool BooleanAND, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operators */ + char * arbitraryHeader)= 0; /* arbitrary header specified by user. ignored unless attrib = attribOtherHeader */ + + NS_IMETHOD GetNumTerms(PRInt32 *numTerms)= 0; + + NS_IMETHOD GetTerm(PRInt32 termIndex, + nsMsgSearchAttribute *attrib, /* attribute for this term */ + nsMsgSearchOperator *op, /* operator e.g. opContains */ + nsMsgSearchValue *value, /* value e.g. "Dogbert" */ + PRBool *BooleanAnd, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operator */ + char ** arbitraryHeader)= 0; /* arbitrary header specified by user. ignore unless attrib = attribOtherHeader */ + + NS_IMETHOD SetScope(nsMsgScopeTerm *scope)= 0; + NS_IMETHOD GetScope(nsMsgScopeTerm **scope)= 0; + + /* if type is acChangePriority, value is a pointer to priority. + If type is acMoveToFolder, value is pointer to folder name. + Otherwise, value is ignored. + */ + NS_IMETHOD SetAction(nsMsgRuleActionType type, void *value)= 0; + NS_IMETHOD GetAction(nsMsgRuleActionType *type, void **value) = 0; + +}; + +#endif diff --git a/mozilla/mailnews/base/search/public/nsIMsgFilterList.h b/mozilla/mailnews/base/search/public/nsIMsgFilterList.h index dc5d67e10f4..3caaa1baf04 100644 --- a/mozilla/mailnews/base/search/public/nsIMsgFilterList.h +++ b/mozilla/mailnews/base/search/public/nsIMsgFilterList.h @@ -16,11 +16,12 @@ * Reserved. */ -#ifndef _nsMsgFilterList_H_ -#define _nsMsgFilterList_H_ +#ifndef _nsIMsgFilterList_H_ +#define _nsIMsgFilterList_H_ #include "nscore.h" #include "nsISupports.h" +#include "nsMsgFilterCore.h" //////////////////////////////////////////////////////////////////////////////////////// // The Msg Filter List is an interface designed to make accessing filter lists @@ -28,27 +29,34 @@ // or add new filters, or change the order around... // //////////////////////////////////////////////////////////////////////////////////////// +// 08ecbcb4-0493-11d3-a50a-0060b0fc04b7 +#define NS_IMSGFILTERLIST_IID \ +{ 0x08ecbcb4, 0x0493, 0x11d3, \ + { 0xa5, 0x0a, 0x0, 0x60, 0xb0, 0xfc, 0x04, 0xb7 } } + +class nsIMsgFilter; class nsIMsgFilterList : public nsISupports { public: static const nsIID& GetIID() { static nsIID iid = NS_IMSGFILTERLIST_IID; return iid; } -NS_IMETHOD GetFolderForFilterList(nsIMsgFolder **aFolder); -NS_IMETHOD GetFilterCount(PRInt32 *pCount); -NS_IMETHOD GetFilterAt(nsMsgFilterIndex filterIndex, nsIMsgFilter **filter); -/* these methods don't delete filters - they just change the list. FE still must - call MSG_DestroyFilter to delete a filter. -*/ -NS_IMETHOD SetFilterAt(nsMsgFilterIndex filterIndex, nsIMsgFilter *filter); -NS_IMETHOD RemoveFilterAt(nsMsgFilterIndex filterIndex); -NS_IMETHOD MoveFilterAt(nsMsgFilterIndex filterIndex, nsMsgFilterMotion motion); -NS_IMETHOD InsertFilterAt(nsMsgFilterIndex filterIndex, nsMsgFilter *filter); + NS_IMETHOD GetFolderForFilterList(nsIMsgFolder **aFolder)= 0; + NS_IMETHOD GetFilterCount(PRInt32 *pCount)= 0; + NS_IMETHOD GetFilterAt(PRUint32 filterIndex, nsIMsgFilter **filter)= 0; + /* these methods don't delete filters - they just change the list. FE still must + call MSG_DestroyFilter to delete a filter. + */ + NS_IMETHOD SetFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter)= 0; + NS_IMETHOD RemoveFilterAt(PRUint32 filterIndex)= 0; + NS_IMETHOD MoveFilterAt(PRUint32 filterIndex, nsMsgFilterMotion motion)= 0; + NS_IMETHOD InsertFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter)= 0; -NS_IMETHOD EnableLogging(PRBool enable); -NS_IMETHOD IsLoggingEnabled(PRBool *aResult); + NS_IMETHOD EnableLogging(PRBool enable)= 0; + NS_IMETHOD IsLoggingEnabled(PRBool *aResult)= 0; + NS_IMETHOD CreateFilter(char *name, nsIMsgFilter **result)= 0; }; diff --git a/mozilla/mailnews/base/search/public/nsIMsgFilterService.h b/mozilla/mailnews/base/search/public/nsIMsgFilterService.h index 131369eac4d..ae0c3dfd835 100644 --- a/mozilla/mailnews/base/search/public/nsIMsgFilterService.h +++ b/mozilla/mailnews/base/search/public/nsIMsgFilterService.h @@ -16,136 +16,37 @@ * Reserved. */ -#ifndef _nsMsgFilterService_H_ -#define _nsMsgFilterService_H_ +#ifndef _nsIMsgFilterService_H_ +#define _nsIMsgFilterService_H_ +// The filter service is used to acquire and manipulate filter lists. +#define NS_IMSGFILTERSERVICE_IID \ +{ 0x5cbb0700, 0x04bc, 0x11d3, \ + { 0xa5, 0x0a, 0x0, 0x60, 0xb0, 0xfc, 0x04, 0xb7 } } +// 5cbb0700-04bc-11d3-a50a-0060b0fc04b7 -/* Front ends call MSG_OpenFilterList to get a handle to a FilterList, of existing nsMsgFilter *. - These are manipulated by the front ends as a result of user interaction - with dialog boxes. To apply the new list, fe's call MSG_CloseFilterList. +#include "nsISupports.h" - For example, if the user brings up the rule management UI, deletes a rule, - and presses OK, the front end calls MSG_RemoveFilterListAt, and - then MSG_CloseFilterList. +class nsIMsgFilterList; -*/ -nsMsgFilterError MSG_OpenFilterList(nsMsgFilterType type, nsIMsgFilterList **filterList); -nsMsgFilterError MSG_OpenFolderFilterList(MSG_Pane *pane, MSG_FolderInfo *folder, nsMsgFilterType type, nsMsgFilterList **filterList); -nsMsgFilterError MSG_OpenFolderFilterListFromMaster(MSG_Master *master, MSG_FolderInfo *folder, nsMsgFilterType type, nsMsgFilterList **filterList); -nsMsgFilterError MSG_CloseFilterList(nsMsgFilterList *filterList); -nsMsgFilterError MSG_SaveFilterList(nsMsgFilterList *filterList); /* save without deleting */ -nsMsgFilterError MSG_CancelFilterList(nsMsgFilterList *filterList); - -MSG_FolderInfo *MSG_GetFolderInfoForFilterList(nsMsgFilterList *filterList); -nsMsgFilterError MSG_GetFilterCount(nsMsgFilterList *filterList, int32 *pCount); -nsMsgFilterError MSG_GetFilterAt(nsMsgFilterList *filterList, - nsMsgFilterIndex filterIndex, nsMsgFilter **filter); -/* these methods don't delete filters - they just change the list. FE still must - call MSG_DestroyFilter to delete a filter. -*/ -nsMsgFilterError MSG_SetFilterAt(nsMsgFilterList *filterList, - nsMsgFilterIndex filterIndex, nsMsgFilter *filter); -nsMsgFilterError MSG_RemoveFilterAt(nsMsgFilterList *filterList, - nsMsgFilterIndex filterIndex); -nsMsgFilterError MSG_MoveFilterAt(nsMsgFilterList *filterList, - nsMsgFilterIndex filterIndex, nsMsgFilterMotion motion); -nsMsgFilterError MSG_InsertFilterAt(nsMsgFilterList *filterList, - nsMsgFilterIndex filterIndex, nsMsgFilter *filter); - -nsMsgFilterError MSG_EnableLogging(nsMsgFilterList *filterList, XP_Bool enable); -XP_Bool MSG_IsLoggingEnabled(nsMsgFilterList *filterList); - -/* In general, any data gotten with MSG_*Get is good until the owning object - is deleted, or the data is replaced with a MSG_*Set call. For example, the name - returned in MSG_GetFilterName is valid until either the filter is destroyed, - or MSG_SetFilterName is called on the same filter. - */ -nsMsgFilterError MSG_CreateFilter (nsMsgFilterType type, char *name, nsMsgFilter **result); -nsMsgFilterError MSG_DestroyFilter(nsMsgFilter *filter); -nsMsgFilterError MSG_GetFilterType(nsMsgFilter *, nsMsgFilterType *filterType); -nsMsgFilterError MSG_EnableFilter(nsMsgFilter *, XP_Bool enable); -nsMsgFilterError MSG_IsFilterEnabled(nsMsgFilter *, XP_Bool *enabled); -nsMsgFilterError MSG_GetFilterRule(nsMsgFilter *, MSG_Rule ** result); -nsMsgFilterError MSG_GetFilterName(nsMsgFilter *, char **name); -nsMsgFilterError MSG_SetFilterName(nsMsgFilter *, const char *name); -nsMsgFilterError MSG_GetFilterDesc(nsMsgFilter *, char **description); -nsMsgFilterError MSG_SetFilterDesc(nsMsgFilter*, const char *description); -nsMsgFilterError MSG_GetFilterScript(nsMsgFilter *, char **name); -nsMsgFilterError MSG_SetFilterScript(nsMsgFilter *, const char *name); - -nsMsgFilterError MSG_RuleAddTerm(MSG_Rule *, - MSG_SearchAttribute attrib, /* attribute for this term */ - MSG_SearchOperator op, /* operator e.g. opContains */ - MSG_SearchValue *value, /* value e.g. "Dogbert" */ - XP_Bool BooleanAND, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operators */ - char * arbitraryHeader); /* arbitrary header specified by user. ignored unless attrib = attribOtherHeader */ - -nsMsgFilterError MSG_RuleGetNumTerms(MSG_Rule *, int32 *numTerms); - -nsMsgFilterError MSG_RuleGetTerm(MSG_Rule *, int32 termIndex, - MSG_SearchAttribute *attrib, /* attribute for this term */ - MSG_SearchOperator *op, /* operator e.g. opContains */ - MSG_SearchValue *value, /* value e.g. "Dogbert" */ - XP_Bool *BooleanAnd, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operator */ - char ** arbitraryHeader); /* arbitrary header specified by user. ignore unless attrib = attribOtherHeader */ - -nsMsgFilterError MSG_RuleSetScope(MSG_Rule *, MSG_ScopeTerm *scope); -nsMsgFilterError MSG_RuleGetScope(MSG_Rule *, MSG_ScopeTerm **scope); - -/* if type is acChangePriority, value is a pointer to priority. - If type is acMoveToFolder, value is pointer to folder name. - Otherwise, value is ignored. -*/ -nsMsgFilterError MSG_RuleSetAction(MSG_Rule *, MSG_RuleActionType type, void *value); -nsMsgFilterError MSG_RuleGetAction(MSG_Rule *, MSG_RuleActionType *type, void **value); - -/* help FEs manage menu choices in Filter dialog box */ - -/* Use this to help build menus in the filter dialogs. See APIs below */ -typedef struct MSG_RuleMenuItem +class nsIMsgFilterService : public nsISupports { - int16 attrib; - char name[32]; -} MSG_RuleMenuItem; +public: + static const nsIID& GetIID() { static nsIID iid = NS_IMSGFILTERSERVICE_IID; return iid; } -nsMsgFilterError MSG_GetRuleActionMenuItems ( - nsMsgFilterType type, /* type of filter */ - MSG_RuleMenuItem *items, /* array of caller-allocated structs */ - uint16 *maxItems); /* in- max array size; out- num returned */ +/* clients call OpenFilterList to get a handle to a FilterList, of existing nsMsgFilter *. + These are manipulated by the front end as a result of user interaction + with dialog boxes. To apply the new list call MSG_CloseFilterList. -nsMsgFilterError MSG_GetFilterWidgetForAction( MSG_RuleActionType action, - MSG_SearchValueWidget *widget ); - -MSG_SearchError MSG_GetValuesForAction( MSG_RuleActionType action, - MSG_SearchMenuItem *items, - uint16 *maxItems); - -void MSG_ViewFilterLog(MSG_Pane *pane); - -/* -** Adding/editting javascript filters. -** -** The FE calls one of the below functions, along with a callback and some closure -** data. This callback is invoked when the user clicks OK in the JS filter dialog. -** If CANCEL is pressed, the callback is not invoked. -** -** If the user called MSG_EditJSFilter, the filter_index parameter of the callback -** is the same one passed in. If the user called MSG_NewJSFilter, the filter_index -** parameter is -1. -** -** The filter_changed parameter is TRUE if the user modified any of the fields of -** the javascript filter, and FALSE otherwise. */ -typedef void (*JSFilterCallback)(void* arg, nsMsgFilterIndex filter_index, XP_Bool filter_changed); + NS_IMETHOD OpenFilterList(nsFileSpec *filterFile, nsIMsgFilterList **filterList) = 0; + NS_IMETHOD CloseFilterList(nsIMsgFilterList *filterList) = 0; + NS_IMETHOD SaveFilterList(nsIMsgFilterList *filterList) = 0; /* save without deleting */ + NS_IMETHOD CancelFilterList(nsIMsgFilterList *filterList) = 0; -void MSG_EditJSFilter(MWContext *context, nsMsgFilterList *filter_list, - nsMsgFilterIndex filter_index, - JSFilterCallback cb, void *arg); -void MSG_NewJSFilter(MWContext *context, nsMsgFilterList *filter_list, - nsMsgFilterType filter_type, JSFilterCallback cb, void *arg); +}; - -#endif // _nsMsgFilterService_H_ +#endif // _nsIMsgFilterService_H_ diff --git a/mozilla/mailnews/base/search/public/nsMsgFilterCore.h b/mozilla/mailnews/base/search/public/nsMsgFilterCore.h index 341832ef33f..24f8005e2e8 100644 --- a/mozilla/mailnews/base/search/public/nsMsgFilterCore.h +++ b/mozilla/mailnews/base/search/public/nsMsgFilterCore.h @@ -21,7 +21,7 @@ #include "MailNewsTypes.h" #include "nsString2.h" - +#include "nsMsgSearchCore.h" typedef enum { @@ -53,11 +53,6 @@ typedef enum typedef PRInt32 nsMsgFilterIndex; -// shouldn't need these...probably should be interfaces. -struct nsMsgFilter; -struct nsMsgRule; -struct nsMsgRuleAction; -struct nsMsgFilterList; #endif diff --git a/mozilla/mailnews/base/search/public/nsMsgSearchCore.h b/mozilla/mailnews/base/search/public/nsMsgSearchCore.h index ad71ccce460..b59a62c148d 100644 --- a/mozilla/mailnews/base/search/public/nsMsgSearchCore.h +++ b/mozilla/mailnews/base/search/public/nsMsgSearchCore.h @@ -22,6 +22,8 @@ #include "MailNewsTypes.h" #include "nsString2.h" +class nsMsgDatabase; +class nsIMsgFolder; typedef enum { @@ -127,7 +129,7 @@ typedef enum nsMsgSearchOpNameCompletion, /* Name Completion operator...as the name implies =) */ kNumMsgSearchOperators /* must be last operator */ -} MSG_SearchOperator; +} nsMsgSearchOperator; /* FEs use this to help build the search dialog box */ typedef enum @@ -149,6 +151,8 @@ typedef enum nsMsgSearchNameCompletion } nsMsgSearchType; +typedef enum {nsMsgSearchBooleanOR, nsMsgSearchBooleanAND} nsMsgSearchBooleanOp; + /* Use this to specify the value of a search term */ typedef struct nsMsgSearchValue { @@ -156,28 +160,111 @@ typedef struct nsMsgSearchValue union { char *string; - MSG_PRIORITY priority; + nsMsgPriority priority; time_t date; PRUint32 msgStatus; /* see MSG_FLAG in msgcom.h */ PRUint32 size; nsMsgKey key; PRUint32 age; /* in days */ - MSG_FolderInfo *folder; + nsIMsgFolder *folder; } u; } nsMsgSearchValue; +struct nsMsgScopeTerm; +struct nsMsgResultElement; +struct nsMsgDIRServer; + +//--------------------------------------------------------------------------- +// nsMsgSearchTerm specifies one criterion, e.g. name contains phil +//--------------------------------------------------------------------------- + +class nsMsgSearchTerm +{ +public: + nsMsgSearchTerm(); + nsMsgSearchTerm (nsMsgSearchAttribute, nsMsgSearchOperator, nsMsgSearchValue *, PRBool, char * arbitraryHeader); // the bool is true if AND, FALSE if OR + nsMsgSearchTerm (nsMsgSearchAttribute, nsMsgSearchOperator, nsMsgSearchValue *, nsMsgSearchBooleanOp, char * arbitraryHeader); + + virtual ~nsMsgSearchTerm (); + + void StripQuotedPrintable (unsigned char*); + int32 GetNextIMAPOfflineMsgLine (char * buf, int bufferSize, int msgOffset, nsIMessage * msg, nsMsgDatabase * db); + + + nsresult MatchBody (nsMsgScopeTerm*, PRUint32 offset, PRUint32 length, PRInt16 csid, nsIMsgFolder * msg, nsMsgDatabase * db); + nsresult MatchArbitraryHeader (nsMsgScopeTerm *,PRUint32 offset, PRUint32 length, PRInt16 csid, nsIMsgFolder * msg, nsMsgDatabase *db, + char * headers, /* NULL terminated header list for msgs being filtered. Ignored unless ForFilters */ + PRUint32 headersSize, /* size of the NULL terminated list of headers */ + PRBool ForFilters /* true if we are filtering */); + nsresult MatchString (const char *, PRInt16 csid, PRBool body = FALSE); + nsresult MatchDate (time_t); + nsresult MatchStatus (PRUint32); + nsresult MatchPriority (nsMsgPriority); + nsresult MatchSize (PRUint32); + nsresult MatchRfc822String(const char *, int16 csid); + nsresult MatchAge (time_t); + + nsresult EnStreamNew (char **, PRInt16 *length); + nsresult DeStream (char *, PRInt16 length); + nsresult DeStreamNew (char *, PRInt16 length); + + nsresult GetLocalTimes (time_t, time_t, struct tm &, struct tm &); + + PRBool IsBooleanOpAND() { return m_booleanOp == nsMsgSearchBooleanAND ? PR_TRUE : PR_FALSE;} + nsMsgSearchBooleanOp GetBooleanOp() {return m_booleanOp;} + char * GetArbitraryHeader() {return m_arbitraryHeader;} + + static char * EscapeQuotesInStr(const char *str); + PRBool MatchAllBeforeDeciding (); + nsMsgSearchAttribute m_attribute; + nsMsgSearchOperator m_operator; + nsMsgSearchValue m_value; + nsMsgSearchBooleanOp m_booleanOp; // boolean operator to be applied to this search term and the search term which precedes it. + char * 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 OutputValue(nsString2 &outputStr); + nsMsgSearchAttribute ParseAttribute(char *inStream); + nsMsgSearchOperator ParseOperator(char *inStream); + nsresult ParseValue(char *inStream); + virtual PRUint32 GetExpectedMagic (); + static PRUint32 m_expectedMagic; +}; + +inline PRUint32 nsMsgSearchTerm::GetExpectedMagic () +{ + return m_expectedMagic; +} + + /* Use this to help build menus in the search dialog. See APIs below */ #define kMsgSearchMenuLength 64 typedef struct nsMsgSearchMenuItem { int16 attrib; - char name[kSearchMenuLength]; + char name[kMsgSearchMenuLength]; PRBool isEnabled; } nsMsgSearchMenuItem; -struct nsMsgScopeTerm; -struct nsMsgResultElement; -struct nsMsgDIRServer; + +class nsMsgSearchTermArray : public nsVoidArray +{ +public: + nsMsgSearchTerm *ElementAt(PRUint32 i) const { return (nsMsgSearchTerm*) nsVoidArray::ElementAt(i); } +}; + +class nsMsgSearchValueArray : public nsVoidArray +{ +public: + nsMsgSearchValue *ElementAt(PRUint32 i) const { return (nsMsgSearchValue*) nsVoidArray::ElementAt(i); } +}; + +class nsMsgScopeTermArray : public nsVoidArray +{ +public: + nsMsgScopeTerm *ElementAt(PRUint32 i) const { return (nsMsgScopeTerm*) nsVoidArray::ElementAt(i); } +}; + #endif // _nsMsgSearchCore_H_ diff --git a/mozilla/mailnews/base/search/src/Makefile.in b/mozilla/mailnews/base/search/src/Makefile.in new file mode 100644 index 00000000000..a86650db3ac --- /dev/null +++ b/mozilla/mailnews/base/search/src/Makefile.in @@ -0,0 +1,55 @@ +#!gmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = search +LIBRARY_NAME=search_s + +EXPORTS = \ + $(NULL) + +CPPSRCS = \ + nsMsgFilterService.cpp\ + nsMsgFilterList.cpp\ + nsMsgFilter.cpp\ + $(NULL) + +EXTRA_DSO_LDOPTS = \ + -L$(DIST)/bin \ + -L$(DIST)/lib \ + $(NSPR_LIBS) \ + -lxpcom \ + -lreg \ + -lraptorbase \ + -lmork \ + -lmsgbaseutil \ + $(NULL) + +# we don't want the shared lib, but we want to force the creation of a static lib. +override NO_SHARED_LIB=1 +override NO_STATIC_LIB= + +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/mailnews/base/search/src/makefile.win b/mozilla/mailnews/base/search/src/makefile.win new file mode 100644 index 00000000000..49afe1e8fd7 --- /dev/null +++ b/mozilla/mailnews/base/search/src/makefile.win @@ -0,0 +1,64 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public License +# Version 1.0 (the "NPL"); you may not use this file except in +# compliance with the NPL. You may obtain a copy of the NPL at +# http://www.mozilla.org/NPL/ +# +# Software distributed under the NPL is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL +# for the specific language governing rights and limitations under the +# NPL. +# +# The Initial Developer of this code under the NPL is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1999 Netscape Communications Corporation. All Rights +# Reserved. + +DEPTH=..\..\..\.. +IGNORE_MANIFEST=1 + +include <$(DEPTH)\config\config.mak> + +LIBRARY_NAME=search +MODULE= mailnews +REQUIRES= + +DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN + +CPPSRCS= nsMsgFilterService.cpp\ + nsMsgFilterList.cpp\ + nsMsgFilter.cpp\ + $(NULL) + +CPP_OBJS= .\$(OBJDIR)\nsMsgFilterService.obj \ + .\$(OBJDIR)\nsMsgFilterList.obj\ + .\$(OBJDIR)\nsMsgFilter.obj\ + $(NULL) + + +EXPORTS= \ + $(NULL) + + +LINCS=-I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\mailnews \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\mime \ + -I$(PUBLIC)\locale \ + -I$(PUBLIC)\pref \ + -I$(PUBLIC)\js + + +LCFLAGS = \ + $(LCFLAGS) \ + $(DEFINES) \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +libs:: $(LIBRARY) + $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib + +clobber:: + rm -f $(DIST)\lib\$(LIBRARY_NAME).lib diff --git a/mozilla/mailnews/base/search/src/nsMsgFilter.cpp b/mozilla/mailnews/base/search/src/nsMsgFilter.cpp new file mode 100644 index 00000000000..71aaf416952 --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilter.cpp @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +// this file implements the nsMsgFilterList interface + +#include "msgCore.h" +#include "nsMsgFilterList.h" +#include "nsMsgFilter.h" + +nsMsgFilter::nsMsgFilter() +{ + m_filterList = nsnull; +} + +nsMsgFilter::SetFilterList(nsMsgFilterList *filterList) +{ + m_filterList = filterList; +} + +nsresult nsMsgFilter::ConvertMoveToFolderValue(nsString2 &relativePath) +{ + + m_action.m_value.m_folderName = relativePath; + return NS_OK; + // set m_action.m_value.m_folderName +} diff --git a/mozilla/mailnews/base/search/src/nsMsgFilter.h b/mozilla/mailnews/base/search/src/nsMsgFilter.h new file mode 100644 index 00000000000..0e3c3fabfa9 --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilter.h @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _nsMsgFilter_H_ +#define _nsMsgFilter_H_ + +#include "nscore.h" +#include "nsISupports.h" +#include "nsIMsgFilter.h" + + +typedef struct nsMsgRuleAction +{ + nsMsgRuleActionType m_type; + union + { + nsMsgPriority m_priority; /* priority to set rule to */ + nsString2 m_folderName; /* Or some folder identifier, if such a thing is invented */ + } m_value; + char *m_originalServerPath; +} nsMsgRuleAction; + + +class nsMsgFilter : public nsIMsgFilter +{ +public: + NS_DECL_ISUPPORTS + static const nsIID& GetIID() { static nsIID iid = NS_IMSGFILTER_IID; return iid; } + + nsMsgFilter(); + virtual ~nsMsgFilter (); + + NS_IMETHOD GetFilterType(nsMsgFilterType *filterType); + NS_IMETHOD EnableFilter(XP_Bool enable); + NS_IMETHOD IsFilterEnabled(PRBool *enabled); + NS_IMETHOD GetFilterName(char **name); + NS_IMETHOD SetFilterName(char *name); + NS_IMETHOD GetFilterDesc(char **description); + NS_IMETHOD SetFilterDesc(char *description); + + NS_IMETHOD AddTerm( + nsMsgSearchAttribute attrib, /* attribute for this term */ + nsMsgSearchOperator op, /* operator e.g. opContains */ + nsMsgSearchValue *value, /* value e.g. "Dogbert" */ + PRBool BooleanAND, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operators */ + char * arbitraryHeader); /* arbitrary header specified by user. ignored unless attrib = attribOtherHeader */ + + NS_IMETHOD GetNumTerms(PRInt32 *numTerms); + + NS_IMETHOD GetTerm(PRInt32 termIndex, + nsMsgSearchAttribute *attrib, /* attribute for this term */ + nsMsgSearchOperator *op, /* operator e.g. opContains */ + nsMsgSearchValue *value, /* value e.g. "Dogbert" */ + PRBool *BooleanAnd, /* TRUE if AND is the boolean operator. FALSE if OR is the boolean operator */ + char ** arbitraryHeader); /* arbitrary header specified by user. ignore unless attrib = attribOtherHeader */ + + NS_IMETHOD SetScope(nsMsgScopeTerm *scope); + NS_IMETHOD GetScope(nsMsgScopeTerm **scope); + + /* if type is acChangePriority, value is a pointer to priority. + If type is acMoveToFolder, value is pointer to folder name. + Otherwise, value is ignored. + */ + NS_IMETHOD SetAction(nsMsgRuleActionType type, void *value); + NS_IMETHOD GetAction(nsMsgRuleActionType *type, void **value) ; + + + nsMsgFilterType GetType() {return m_type;} + void SetType(nsMsgFilterType type) {m_type = type;} + void SetEnabled(PRBool enabled) {m_enabled = enabled;} + PRBool GetEnabled() {return m_enabled;} + nsresult GetName(nsString2 *name); + nsresult SetName(nsString2 *name); + nsresult SetDescription(nsString2 *desc); + nsresult GetDescription(nsString2 *desc); + void SetFilterScript(nsString2 *filterName) ; + void SetFilterList(nsMsgFilterList *filterList) ; + nsresult SaveToTextFile(nsIOFileStream *stream); + PRInt16 GetVersion() {return (m_filterList) ? m_filterList->GetVersion() : 0;} + nsMsgFilterList *GetFilterList() {return m_filterList;} + void SetDontFileMe(PRBool bDontFileMe) {m_dontFileMe = bDontFileMe;} + nsMsgSearchTermArray GetTermList() {return m_termList;} /* linked list of criteria terms */ +#ifdef DEBUG + void Dump(); +#endif + + nsresult ConvertMoveToFolderValue(nsString2 &relativePath); +static char *GetActionStr(nsMsgRuleActionType action); +static const char *GetActionFilingStr(nsMsgRuleActionType action); +static nsMsgRuleActionType GetActionForFilingStr(nsString2 &actionStr); + nsMsgRuleAction m_action; +protected: + nsMsgFilterType m_type; + PRBool m_enabled; + nsString2 m_filterName; + nsString2 m_description; + PRBool m_dontFileMe; + + nsMsgFilterList *m_filterList; /* owning filter list */ + nsMsgSearchTermArray m_termList; /* linked list of criteria terms */ + nsMsgScopeTerm *m_scope; /* default for mail rules is inbox, but news rules could +have a newsgroup - LDAP would be invalid */ + +}; + +#endif diff --git a/mozilla/mailnews/base/search/src/nsMsgFilterList.cpp b/mozilla/mailnews/base/search/src/nsMsgFilterList.cpp new file mode 100644 index 00000000000..9bb0e6a5454 --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilterList.cpp @@ -0,0 +1,671 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +// this file implements the nsMsgFilterList interface + +#include "msgCore.h" +#include "nsMsgFilterList.h" +#include "nsMsgFilter.h" + +#include "nsFileStream.h" + +const int16 kFileVersion = 6; +const int16 kFileVersionOldMoveTarget = 5; +#if defined(XP_WIN) || defined(XP_OS2) +const int16 kFileVersionAbsPath = 3; +#endif +const int16 kFileVersionOldStream = 2; + + +nsMsgFilterList::nsMsgFilterList(nsIOFileStream *fileStream) +{ + m_fileStream = fileStream; + // I don't know how we're going to report this error if we failed to create the isupports array... + nsresult rv = NS_NewISupportsArray(getter_AddRefs(m_filters)); +} + +nsMsgFilterList::~nsMsgFilterList() +{ +} + +#if 0 +nsresult nsMsgFilterList::Open(nsMsgFilterType type, nsIMsgFolder *folder, nsIMsgFilterList **filterList) +{ + nsresult err = NS_OK; + nsMsgFilterList *newFilterList; + + if (type != filterInbox + && type != filterNews) + return FilterError_InvalidFilterType; + + if (nsnull == filterList) + return NS_ERROR_NULL_POINTER; + + newFilterList = new nsMsgFilterList; + if (newFilterList == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + newFilterList->m_master = master; + + // hack up support for news filters by checking the current folder of the pane and massaging input params. + if (pane != nsnull && folderInfo == nsnull) + { + folderInfo = pane->GetFolder(); + if (folderInfo) + { + if (folderInfo->IsNews()) + type = filterNews; + } + } + + newFilterList->m_folderInfo = folderInfo; + newFilterList->m_pane = pane; + + *filterList = newFilterList; + const char *upgradeIMAPFiltersDestFileName = 0; + + if (type == filterNews) + { + MSG_FolderInfoNews *newsFolder = folderInfo->GetNewsFolderInfo(); + if (newsFolder) + newFilterList->m_filterFileName = newsFolder->GetXPRuleFileName(); + newFilterList->m_fileType = xpNewsSort; + } + else + { + MSG_IMAPFolderInfoMail *imapMailFolder = (folderInfo) ? folderInfo->GetIMAPFolderInfoMail() : (MSG_IMAPFolderInfoMail *)nsnull; + + newFilterList->m_filterFileName = ""; + newFilterList->m_fileType = xpMailSort; + if (imapMailFolder) + { + MSG_IMAPHost *defaultHost = imapMailFolder->GetMaster()->GetIMAPHostTable()->GetDefaultHost(); + if (imapMailFolder->GetIMAPHost() == defaultHost) + { + PRBool defaultHostFiltersExist = !XP_Stat(imapMailFolder->GetIMAPHost()->GetHostName(), &outStat, newFilterList->m_fileType); + if (!defaultHostFiltersExist) + upgradeIMAPFiltersDestFileName = imapMailFolder->GetIMAPHost()->GetHostName(); + } + + // if it's not the default imap host or there are no filters for the default host, or the old local mail filters + // don't exist, set the filter file name to the filter name for the imap host. + if (!upgradeIMAPFiltersDestFileName || XP_Stat(newFilterList->m_filterFileName, &outStat, newFilterList->m_fileType)) + newFilterList->m_filterFileName = imapMailFolder->GetIMAPHost()->GetHostName(); + } + + } + + if (XP_Stat(newFilterList->m_filterFileName, &outStat, newFilterList->m_fileType)) + { + // file must not exist - no rules, we're done. + return NS_OK; + } + fid = XP_FileOpen(newFilterList->m_filterFileName, newFilterList->m_fileType, XP_FILE_READ_BIN); + if (fid) + { + err = newFilterList->LoadTextFilters(fid); + XP_FileClose(fid); + // if the file version changed, save it out right away. + if (newFilterList->GetVersion() != kFileVersion || upgradeIMAPFiltersDestFileName) + { + if (upgradeIMAPFiltersDestFileName) + newFilterList->m_filterFileName = upgradeIMAPFiltersDestFileName; + newFilterList->Close(); + } + } + else + { + err = FilterError_FileError; + } + + return err; +} + +extern "C" MSG_FolderInfo *MSG_GetFolderInfoForFilterList(nsMsgFilterList *filterList) +{ + return filterList ? filterList->GetFolderInfo() : (MSG_FolderInfo *)nsnull; +} +#endif + + +typedef struct +{ + nsMsgFilterFileAttrib attrib; + const char *attribName; +} FilterFileAttribEntry; + +static FilterFileAttribEntry FilterFileAttribTable[] = +{ + {nsMsgFilterAttribNone, ""}, + {nsMsgFilterAttribVersion, "version"}, + {nsMsgFilterAttribLogging, "logging"}, + {nsMsgFilterAttribName, "name"}, + {nsMsgFilterAttribEnabled, "enabled"}, + {nsMsgFilterAttribDescription, "description"}, + {nsMsgFilterAttribType, "type"}, + {nsMsgFilterAttribScriptFile, "scriptName"}, + {nsMsgFilterAttribAction, "action"}, + {nsMsgFilterAttribActionValue, "actionValue"}, + {nsMsgFilterAttribCondition, "condition"} +}; + +// If we want to buffer file IO, wrap it in here. +char nsMsgFilterList::ReadChar() +{ + char newChar; + *m_fileStream >> newChar; + return (m_fileStream->eof() ? -1 : newChar); +} + +PRBool nsMsgFilterList::IsWhitespace(char ch) +{ + return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'); +} + +char nsMsgFilterList::SkipWhitespace() +{ + char ch; + do + { + ch = ReadChar(); + } while (IsWhitespace(ch)); + return ch; +} + +PRBool nsMsgFilterList::StrToBool(nsString2 &str) +{ + return str.Equals("yes") ; +} + +char nsMsgFilterList::LoadAttrib(nsMsgFilterFileAttrib &attrib) +{ + char attribStr[100]; + char curChar; + + curChar = SkipWhitespace(); + int i; + for (i = 0; i + 1 < sizeof(attribStr); ) + { + if (curChar == (char) -1 || IsWhitespace(curChar) || curChar == '=') + break; + attribStr[i++] = curChar; + curChar = ReadChar(); + } + attribStr[i] = '\0'; + for (int tableIndex = 0; tableIndex < sizeof(FilterFileAttribTable) / sizeof(FilterFileAttribTable[0]); tableIndex++) + { + if (!PL_strcasecmp(attribStr, FilterFileAttribTable[tableIndex].attribName)) + { + attrib = FilterFileAttribTable[tableIndex].attrib; + break; + } + } + return curChar; +} + +const char *nsMsgFilterList::GetStringForAttrib(nsMsgFilterFileAttrib attrib) +{ + for (int tableIndex = 0; tableIndex < sizeof(FilterFileAttribTable) / sizeof(FilterFileAttribTable[0]); tableIndex++) + { + if (attrib == FilterFileAttribTable[tableIndex].attrib) + return FilterFileAttribTable[tableIndex].attribName; + } + return nsnull; +} + +nsresult nsMsgFilterList::LoadValue(nsString2 &value) +{ + nsString2 valueStr; + char curChar; + value = ""; + curChar = SkipWhitespace(); + if (curChar != '"') + { + NS_ASSERTION(PR_FALSE, "expecting quote as start of value"); + return NS_MSG_FILTER_PARSE_ERROR; + } + curChar = ReadChar(); + for (int i = 0; i + 2 < sizeof(valueStr); ) + { + if (curChar == '\\') + { + char nextChar = ReadChar(); + if (nextChar == '"') + curChar = '"'; + else if (nextChar == '\\') // replace "\\" with "\" + { + curChar = ReadChar(); + } + else + { + valueStr.SetCharAt(curChar, i++) ; + curChar = nextChar; + } + } + else + { + if (curChar == (char) -1 || curChar == '"' || curChar == '\n' || curChar == '\r') + { + valueStr.SetCharAt(0, i); + value += valueStr; + break; + } + } + valueStr.SetCharAt(curChar, i++); + curChar = ReadChar(); + if (i + 2 >= sizeof(valueStr)) + { + valueStr.SetCharAt(0, i); + value += valueStr; + i = 0; + } + } + return NS_OK; +} + +nsresult nsMsgFilterList::LoadTextFilters() +{ + nsresult err = NS_OK; + nsMsgFilterFileAttrib attrib; + + // We'd really like to move lot's of these into the objects that they refer to. + m_fileStream->seek(PR_SEEK_SET, 0); + do + { + nsString2 value(eOneByte); + PRInt32 intToStringResult; + + char curChar = LoadAttrib(attrib); + if (attrib == nsMsgFilterAttribNone) + break; + err = LoadValue(value); + if (err != NS_OK) + break; + switch(attrib) + { + case nsMsgFilterAttribNone: + break; + case nsMsgFilterAttribVersion: + m_fileVersion = value.ToInteger(&intToStringResult, 10); + if (intToStringResult != 0) + { + attrib = nsMsgFilterAttribNone; + NS_ASSERTION(PR_FALSE, "error parsing filter file version"); + } + break; + case nsMsgFilterAttribLogging: + m_loggingEnabled = StrToBool(value); + break; + case nsMsgFilterAttribName: + { + nsMsgFilter *filter = new nsMsgFilter; + if (filter == nsnull) + { + err = NS_ERROR_OUT_OF_MEMORY; + break; + } + filter->SetFilterList(this); + filter->SetName(&value); + m_curFilter = filter; + m_filters->AppendElement(filter); + } + break; + case nsMsgFilterAttribEnabled: + if (m_curFilter) + m_curFilter->SetEnabled(StrToBool(value)); + break; + case nsMsgFilterAttribDescription: + if (m_curFilter) + m_curFilter->SetDescription(&value); + break; + case nsMsgFilterAttribType: + if (m_curFilter) + { + m_curFilter->SetType((nsMsgFilterType) value.ToInteger(&intToStringResult, 10)); + } + break; + case nsMsgFilterAttribScriptFile: + if (m_curFilter) + m_curFilter->SetFilterScript(&value); + break; + case nsMsgFilterAttribAction: + m_curFilter->m_action.m_type = nsMsgFilter::GetActionForFilingStr(value); + break; + case nsMsgFilterAttribActionValue: + if (m_curFilter->m_action.m_type == nsMsgFilterActionMoveToFolder) + err = m_curFilter->ConvertMoveToFolderValue(value); + else if (m_curFilter->m_action.m_type == nsMsgFilterActionChangePriority) + m_curFilter->SetAction(m_curFilter->m_action.m_type, (void *) (int32) MSG_GetPriorityFromString(value)); + break; + case nsMsgFilterAttribCondition: + err = ParseCondition(value); + break; + } + } while (attrib != nsMsgFilterAttribNone); + return err; +} + +// parse condition like "(subject, contains, fred) AND (body, isn't, "foo)")" +// values with close parens will be quoted. +// what about values with close parens and quotes? e.g., (body, isn't, "foo")") +// I guess interior quotes will need to be escaped - ("foo\")") +// which will get written out as (\"foo\\")\") and read in as ("foo\")" +nsresult nsMsgFilterList::ParseCondition(nsString2 &value) +{ + PRBool done = PR_FALSE; + nsresult err = NS_OK; + const char *curPtr = value.GetBuffer(); + while (!done) + { + // insert code to save the boolean operator if there is one for this search term.... + const char *openParen = PL_strchr(curPtr, '('); + const char *orTermPos = PL_strchr(curPtr, 'O'); // determine if an "OR" appears b4 the openParen... + PRBool ANDTerm = PR_TRUE; + if (orTermPos && orTermPos < openParen) // make sure OR term falls before the '(' + ANDTerm = PR_FALSE; + + char *termDup = nsnull; + if (openParen) + { + PRBool foundEndTerm = PR_FALSE; + PRBool inQuote = PR_FALSE; + for (curPtr = openParen +1; *curPtr; curPtr++) + { + if (*curPtr == '\\' && *(curPtr + 1) == '"') + curPtr++; + else if (*curPtr == ')' && !inQuote) + { + foundEndTerm = PR_TRUE; + break; + } + else if (*curPtr == '"') + inQuote = !inQuote; + } + if (foundEndTerm) + { + int termLen = curPtr - openParen - 1; + termDup = (char *) PR_Malloc(termLen + 1); + if (termDup) + PL_strcnpy(termDup, openParen + 1, termLen + 1); + else + { + err = NS_ERROR_OUT_OF_MEMORY; + break; + } + } + } + else + break; + if (termDup) + { + nsMsgSearchTerm *newTerm = new nsMsgSearchTerm; + if (newTerm) + newTerm->m_booleanOp = ANDTerm ? nsMsgSearchBooleanAND : nsMsgSearchBooleanOR; + if (newTerm->DeStreamNew(termDup, PL_strlen(termDup)) == NS_OK) + m_curFilter->GetTermList().Add(newTerm); + PR_FREEIF(termDup); + } + else + break; + } + return err; +} + +nsresult nsMsgFilterList::WriteIntAttr(nsMsgFilterFileAttrib attrib, int value) +{ + const char *attribStr = GetStringForAttrib(attrib); + if (attribStr) + { + m_fileStream >> attribStr; + m_fileStream >> "=\""; + m_fileStream >> value; + m_fileStream >> "\"" LINEBREAK; + } +// XP_FilePrintf(fid, "%s=\"%d\"%s", attribStr, value, LINEBREAK); + return NS_OK; +} + +nsresult nsMsgFilterList::WriteStrAttr(nsMsgFilterAttrib attrib, const char *str) +{ + if (str && m_fileStream) // only proceed if we actually have a string to write out. + { + char *escapedStr = nsnull; + if (PL_strchr(str, '"')) + escapedStr = nsMsgSearchTerm::EscapeQuotesInStr(str); + + const char *attribStr = GetStringForAttrib(attrib); + if (attribStr) + { + m_fileStream >> attribStr; + m_fileStream >> "=\""; + m_fileStream >> (escapedStr) ? escapedStr : str; + m_fileStream >> "\"" LINEBREAK; +// XP_FilePrintf(fid, "%s=\"%s\"%s", attribStr, (escapedStr) ? escapedStr : str, LINEBREAK); + } + PR_FREEIF(escapedStr); + } + return NS_OK; +} + +nsresult nsMsgFilterList::WriteBoolAttr(nsMsgFilterAttrib attrib, PRBool boolVal) +{ + return WriteStrAttr(attrib, (boolVal) ? "yes" : "no"); +} + +nsresult nsMsgFilterList::SaveTextFilters() +{ + nsresult err = NS_OK; + const char *attribStr; + int32 filterCount = m_filters->Count(); + + attribStr = GetStringForAttrib(nsMsgFilterAttribVersion); + err = WriteIntAttr(nsMsgFilterAttribVersion, kFileVersion); + err = WriteBoolAttr(nsMsgFilterAttribLogging, m_loggingEnabled); + for (int i = 0; i < filterCount; i ++) + { + nsMsgFilter *filter; + if (GetFilterAt(i, &filter) == NS_OK && filter != nsnull) + { + filter->SetFilterList(this); + if ((err = filter->SaveToTextFile(fid)) != NS_OK) + break; + } + else + break; + } + return err; +} + +nsMsgFilterList::nsMsgFilterList() +{ + m_loggingEnabled = PR_FALSE; + m_curFilter = nsnull; +} + +nsMsgFilterList::~nsMsgFilterList() +{ + for (int32 i = 0; i < m_filters->Count(); i++) + { + nsMsgFilter *filter; + if (GetFilterAt(i, &filter) == NS_OK) + delete filter; + } +} + +uint32 nsMsgFilterList::GetExpectedMagic () +{ + return m_expectedMagic; +} + +// What should we do about file errors here? If we blow away the +// filter list even when we have an error, we can't let the user +// correct the problem. But if we don't blow it away, we'll have +// memory leaks. +nsresult MSG_CloseFilterList(nsMsgFilterList *filterList) +{ + nsresult err; + + if (filterList == nsnull) + return NS_ERROR_NULL_POINTER; + + err = filterList->Close(); + if (err == NS_OK) + delete filterList; + return err; +} + +nsresult MSG_CancelFilterList(nsMsgFilterList *filterList) +{ + if (filterList == nsnull) + return NS_ERROR_NULL_POINTER; + + delete filterList; + return NS_OK; +} + +nsresult MSG_SaveFilterList(nsMsgFilterList *filterList) +{ + if (filterList == nsnull) + return NS_ERROR_NULL_POINTER; + + return filterList->Close(); +} + +nsresult nsMsgFilterList::Close() +{ +#ifdef HAVE_PORT + nsresult err = FilterError_FileError; + XP_File fid; + XP_FileType retType; + const char *finalName = m_filterFileName; + char *tmpName = (finalName) ? FE_GetTempFileFor(nsnull, finalName, m_fileType, &retType) : (char *)nsnull; + + + if (!tmpName || !finalName) + return NS_ERROR_OUT_OF_MEMORY; + m_fileStream = new nsIOFileStream + fid = XP_FileOpen(tmpName, xpTemporary, + XP_FILE_TRUNCATE_BIN); + if (fid) + { + err = SaveTextFilters(fid); + XP_FileClose(fid); + if (err == NS_OK) + { + int status = XP_FileRename(tmpName, xpTemporary, finalName, m_fileType); + XP_ASSERT(status >= 0); + } + } + + PR_FREEIF(tmpName); + // tell open DB's that the filter list might have changed. + NewsGroupDB::NotifyOpenDBsOfFilterChange(m_folderInfo); + + return err; +#else + return NS_ERROR_NOT_IMPLEMENTED; +#endif +} + +nsresult nsMsgFilterList::GetFilterCount(PRInt32 *pCount) +{ + if (pCount == nsnull) + return NS_ERROR_NULL_POINTER; + *pCount = m_filters->Count(); + return NS_OK; +} + +nsresult nsMsgFilterList::GetFilterAt(PRUint32 filterIndex, nsIMsgFilter **filter) +{ + if (!m_filters->IsValidIndex(filterIndex)) + return FilterError_InvalidIndex; + if (filter == nsnull) + return NS_ERROR_NULL_POINTER; + *filter = (nsIMsgFilter *) m_filters->GetAt(filterIndex); + return NS_OK; +} + + +nsresult nsMsgFilterList::SetFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter) +{ + m_filters->SetElementAtGrow(filterIndex, filter); + return NS_OK; +} + + +nsresult nsMsgFilterList::RemoveFilterAt(PRUint32 filterIndex) +{ + m_filters->RemoveAt(filterIndex, 1); + return NS_OK; +} + +nsresult nsMsgFilterList::InsertFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter) +{ + m_filters->InsertAt(filterIndex, filter); + return NS_OK; +} + +// Attempt to move the filter at index filterIndex in the specified direction. +// If motion not possible in that direction, we still return success. +// We could return an error if the FE's want to beep or something. +nsresult nsMsgFilterList::MoveFilterAt(PRUint32 filterIndex, + nsMsgFilterMotion motion) +{ + nsIMsgFilter *tempFilter; + + if (!m_filters->IsValidIndex(filterIndex)) + return FilterError_InvalidIndex; + + tempFilter = (nsIMsgFilter *) m_filters->GetAt(filterIndex); + if (motion == filterUp) + { + if (filterIndex == 0) + return NS_OK; + m_filters->SetElementAt(filterIndex, m_filters->GetAt(filterIndex - 1)); + m_filters->SetElementAt(filterIndex - 1, tempFilter); + } + else if (motion == filterDown) + { + if (filterIndex + 1 > (PRUint32) (m_filters->Count() - 1)) + return NS_OK; + m_filters->SetElementAt(filterIndex, m_filters->GetAt(filterIndex + 1)); + m_filters->SetElementAt(filterIndex + 1, tempFilter); + } + else + { + return FilterError_InvalidMotion; + } + return NS_OK; +} + +#ifdef DEBUG +void nsMsgFilterList::Dump() +{ + printf("%d filters\n", m_filters->Count()); + + for (int32 i = 0; i < m_filters->Count(); i++) + { + nsIMsgFilter *filter; + if (GetFilterAt(i, &filter) == NS_OK) + filter->Dump(); + } + +} +#endif + +// ------------ End FilterList methods ------------------ diff --git a/mozilla/mailnews/base/search/src/nsMsgFilterList.h b/mozilla/mailnews/base/search/src/nsMsgFilterList.h new file mode 100644 index 00000000000..a783ee69541 --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilterList.h @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _nsMsgFilterList_H_ +#define _nsMsgFilterList_H_ + +#include "nscore.h" +#include "nsIMsgFilterList.h" +#include "nsCOMPtr.h" +#include "nsISupportsArray.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// The Msg Filter List is an interface designed to make accessing filter lists +// easier. Clients typically open a filter list and either enumerate the filters, +// or add new filters, or change the order around... +// +//////////////////////////////////////////////////////////////////////////////////////// + +class nsIMsgFilter; +class nsIOFileStream; +class nsMsgFilter; + +typedef enum +{ + nsMsgFilterAttribNone, + nsMsgFilterAttribVersion, + nsMsgFilterAttribLogging, + nsMsgFilterAttribName, + nsMsgFilterAttribEnabled, + nsMsgFilterAttribDescription, + nsMsgFilterAttribType, + nsMsgFilterAttribScriptFile, + nsMsgFilterAttribAction, + nsMsgFilterAttribActionValue, + nsMsgFilterAttribCondition +} nsMsgFilterFileAttrib; + +class nsMsgFilterList : public nsIMsgFilterList +{ +public: + NS_DECL_ISUPPORTS + static const nsIID& GetIID() { static nsIID iid = NS_IMSGFILTERLIST_IID; return iid; } + + nsMsgFilterList(nsIOFileStream *fileStream); + virtual ~nsMsgFilterList(); + + NS_IMETHOD GetFolderForFilterList(nsIMsgFolder **aFolder); + NS_IMETHOD GetFilterCount(PRInt32 *pCount); + NS_IMETHOD GetFilterAt(PRUint32 filterIndex, nsIMsgFilter **filter); + /* these methods don't delete filters - they just change the list. FE still must + call MSG_DestroyFilter to delete a filter. + */ + NS_IMETHOD SetFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter); + NS_IMETHOD RemoveFilterAt(PRUint32 filterIndex); + NS_IMETHOD MoveFilterAt(PRUint32 filterIndex, nsMsgFilterMotion motion); + NS_IMETHOD InsertFilterAt(PRUint32 filterIndex, nsIMsgFilter *filter); + + NS_IMETHOD EnableLogging(PRBool enable); + NS_IMETHOD IsLoggingEnabled(PRBool *aResult); + + NS_IMETHOD CreateFilter(char *name, nsIMsgFilter **result); + + nsresult LoadTextFilters(); + + PRInt16 GetVersion() {return m_fileVersion;} +protected: + nsresult WriteIntAttr( nsMsgFilterFileAttrib attrib, int value); + nsresult WriteStrAttr(nsMsgFilterFileAttrib attrib, const char *str); + nsresult WriteBoolAttr(nsMsgFilterFileAttrib attrib, XP_Bool boolVal); +#ifdef DEBUG + void Dump(); +#endif +protected: + virtual uint32 GetExpectedMagic (); + nsresult SaveTextFilters(); + // file streaming methods + char ReadChar(); + PRBool IsWhitespace(char ch); + char SkipWhitespace(); + PRBool StrToBool(nsString2 &str); + char LoadAttrib(nsMsgFilterFileAttrib &attrib); + const char *GetStringForAttrib(nsMsgFilterFileAttrib attrib); + nsresult LoadValue(nsString2 &value); + nsresult ParseCondition(nsString2 &value); + PRInt16 m_fileVersion; + PRBool m_loggingEnabled; + nsCOMPtr m_folder; + nsMsgFilter *m_curFilter; // filter we're filing in or out(?) + const char *m_filterFileName; + nsIOFileStream *m_fileStream; + nsCOMPtr m_filters; + +}; + +#endif + + + diff --git a/mozilla/mailnews/base/search/src/nsMsgFilterService.cpp b/mozilla/mailnews/base/search/src/nsMsgFilterService.cpp new file mode 100644 index 00000000000..67cef9f7885 --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilterService.cpp @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +// this file implements the nsMsgFilterService interface + +#include "msgCore.h" +#include "nsMsgFilterService.h" +#include "nsFileStream.h" +#include "nsMsgFilterList.h" + +NS_IMPL_ADDREF(nsMsgFilterService) +NS_IMPL_RELEASE(nsMsgFilterService) + +NS_IMETHODIMP nsMsgFilterService::QueryInterface(REFNSIID aIID, void** aResult) +{ + if (aResult == NULL) + return NS_ERROR_NULL_POINTER; + + if (aIID.Equals(nsIMsgFilterService::GetIID()) || + aIID.Equals(::nsISupports::GetIID())) { + *aResult = NS_STATIC_CAST(nsIMsgFilterService*, this); + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + +NS_IMETHODIMP nsMsgFilterService::OpenFilterList(nsFileSpec *filterFile, nsIMsgFilterList **resultFilterList) +{ + nsresult ret; + + nsIOFileStream *fileStream = new nsIOFileStream(*filterFile); + if (!fileStream) + return NS_ERROR_OUT_OF_MEMORY; + + nsMsgFilterList *filterList = new nsMsgFilterList(fileStream); + if (!filterList) + return NS_ERROR_OUT_OF_MEMORY; + ret = filterList->LoadTextFilters(); + if (NS_SUCCEEDED(ret)) + *resultFilterList = filterList; + else + NS_RELEASE(filterList); + return ret; +} + +NS_IMETHODIMP nsMsgFilterService::CloseFilterList(nsIMsgFilterList *filterList) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + /* save without deleting */ +NS_IMETHODIMP nsMsgFilterService::SaveFilterList(nsIMsgFilterList *filterList) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsMsgFilterService::CancelFilterList(nsIMsgFilterList *filterList) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + + diff --git a/mozilla/mailnews/base/search/src/nsMsgFilterService.h b/mozilla/mailnews/base/search/src/nsMsgFilterService.h new file mode 100644 index 00000000000..a77c473bd9c --- /dev/null +++ b/mozilla/mailnews/base/search/src/nsMsgFilterService.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef _nsMsgFilterService_H_ +#define _nsMsgFilterService_H_ + +#include "nsIMsgFilterService.h" + +// The filter service is used to acquire and manipulate filter lists. + +class nsMsgFilterService : public nsIMsgFilterService +{ + +public: + NS_DECL_ISUPPORTS +/* clients call OpenFilterList to get a handle to a FilterList, of existing nsMsgFilter *. + These are manipulated by the front end as a result of user interaction + with dialog boxes. To apply the new list call MSG_CloseFilterList. + +*/ + NS_IMETHOD OpenFilterList(nsFileSpec *filterFile, nsIMsgFilterList **filterList); + NS_IMETHOD CloseFilterList(nsIMsgFilterList *filterList); + NS_IMETHOD SaveFilterList(nsIMsgFilterList *filterList); /* save without deleting */ + NS_IMETHOD CancelFilterList(nsIMsgFilterList *filterList); + +}; + +#endif // _nsMsgFilterService_H_ +