more work on search and filters, not part of build yet

This commit is contained in:
bienvenu%netscape.com 1999-05-10 01:59:23 +00:00
parent cfeb915805
commit c94b64e307
18 changed files with 1556 additions and 147 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <nsIMsgFolder> m_folder;
nsMsgFilter *m_curFilter; // filter we're filing in or out(?)
const char *m_filterFileName;
nsIOFileStream *m_fileStream;
nsCOMPtr<nsISupportsArray> m_filters;
};
#endif

View File

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

View File

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