restructure filter code to start on imap filters

This commit is contained in:
bienvenu%netscape.com 1999-06-11 07:07:04 +00:00
Родитель d0f17077e7
Коммит aa6f741aaa
5 изменённых файлов: 441 добавлений и 164 удалений

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

@ -39,6 +39,12 @@
#include "nsMsgBaseCID.h" #include "nsMsgBaseCID.h"
#include "nsMsgLocalCID.h" #include "nsMsgLocalCID.h"
#ifdef DOING_FILTERS
#include "nsIMsgFilter.h"
#include "nsIMsgFilterService.h"
static NS_DEFINE_CID(kMsgFilterServiceCID, NS_MSGFILTERSERVICE_CID);
#endif
// we need this because of an egcs 1.0 (and possibly gcc) compiler bug // we need this because of an egcs 1.0 (and possibly gcc) compiler bug
// that doesn't allow you to call ::nsISupports::GetIID() inside of a class // that doesn't allow you to call ::nsISupports::GetIID() inside of a class
// that multiply inherits from nsISupports // that multiply inherits from nsISupports
@ -127,7 +133,12 @@ NS_IMETHODIMP nsImapMailFolder::QueryInterface(REFNSIID aIID, void** aInstancePt
{ {
*aInstancePtr = NS_STATIC_CAST(nsIUrlListener *, this); *aInstancePtr = NS_STATIC_CAST(nsIUrlListener *, this);
} }
#ifdef DOING_FILTERS
else if (aIID.Equals(nsIMsgFilterHitNotify::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST(nsIMsgFilterHitNotify *, this);
}
#endif
if(*aInstancePtr) if(*aInstancePtr)
{ {
AddRef(); AddRef();
@ -401,8 +412,7 @@ NS_IMETHODIMP nsImapMailFolder::GetMessages(nsIEnumerator* *result)
char *folderName = nsnull; char *folderName = nsnull;
rv = GetName(&folderName); rv = GetName(&folderName);
// if (folderName && !PL_strcasecmp(folderName, "INBOX")) selectFolder = PR_TRUE;
selectFolder = PR_TRUE;
delete [] folderName; delete [] folderName;
@ -1271,6 +1281,19 @@ NS_IMETHODIMP nsImapMailFolder::SetupHeaderParseStream(
if (!mDatabase) if (!mDatabase)
GetDatabase(); GetDatabase();
#ifdef DOING_FILTERS
if (mFlags & MSG_FOLDER_FLAG_INBOX && !m_filterList)
{
NS_WITH_SERVICE(nsIMsgFilterService, filterService, kMsgFilterServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
// need a file spec for filters...
nsFileSpec filterFile("rules.dat");
nsresult res = filterService->OpenFilterList(&filterFile, getter_AddRefs(m_filterList));
}
#endif
m_nextMessageByteLength = aStreamInfo->size; m_nextMessageByteLength = aStreamInfo->size;
if (!m_msgParser) if (!m_msgParser)
{ {
@ -1334,8 +1357,24 @@ NS_IMETHODIMP nsImapMailFolder::NormalEndHeaderParseStream(nsIImapProtocol*
m_msgParser->GetNewMsgHdr(getter_AddRefs(newMsgHdr)); m_msgParser->GetNewMsgHdr(getter_AddRefs(newMsgHdr));
if (NS_SUCCEEDED(rv) && newMsgHdr) if (NS_SUCCEEDED(rv) && newMsgHdr)
{ {
char *headers;
PRInt32 headersSize;
newMsgHdr->SetMessageKey(m_curMsgUid); newMsgHdr->SetMessageKey(m_curMsgUid);
TweakHeaderFlags(aProtocol, newMsgHdr); TweakHeaderFlags(aProtocol, newMsgHdr);
// If this is the inbox, try to apply filters.
if (mFlags & MSG_FOLDER_FLAG_INBOX)
{
rv = m_msgParser->GetAllHeaders(&headers, &headersSize);
if (NS_SUCCEEDED(rv) && headers)
{
#ifdef DOING_FILTERS
m_filterList->ApplyFiltersToHdr(nsMsgFilterInboxRule, newMsgHdr, this, mDatabase,
headers, headersSize, this);
#endif
}
}
// here we need to tweak flags from uid state.. // here we need to tweak flags from uid state..
mDatabase->AddNewHdrToDB(newMsgHdr, PR_TRUE); mDatabase->AddNewHdrToDB(newMsgHdr, PR_TRUE);
m_msgParser->FinishHeader(); m_msgParser->FinishHeader();
@ -1413,6 +1452,218 @@ NS_IMETHODIMP nsImapMailFolder::EndCopy(PRBool copySucceeded)
return rv; return rv;
} }
#ifdef DOING_FILTERS
NS_IMETHODIMP nsImapMailFolder::ApplyFilterHit(nsIMsgFilter *filter, PRBool *applyMore)
{
nsMsgRuleActionType actionType;
void *value = nsnull;
PRUint32 newFlags;
nsresult rv = NS_OK;
if (!applyMore)
{
NS_ASSERTION(PR_FALSE, "need to return status!");
return NS_ERROR_NULL_POINTER;
}
// look at action - currently handle move
#ifdef DEBUG_bienvenu
printf("got a rule hit!\n");
#endif
if (NS_SUCCEEDED(filter->GetAction(&actionType, &value)))
{
nsCOMPtr<nsIMsgDBHdr> msgHdr;
nsresult rv = NS_OK;
if (m_msgParser)
m_msgParser->GetNewMsgHdr(getter_AddRefs(msgHdr));
if (NS_SUCCEEDED(rv) && msgHdr)
{
PRUint32 msgFlags;
msgHdr->GetFlags(&msgFlags);
PRBool isRead = (msgFlags & MSG_FLAG_READ);
switch (actionType)
{
case nsMsgFilterActionDelete:
{
#ifdef DOING_DELETE
MSG_IMAPFolderInfoMail *imapFolder = m_folder->GetIMAPFolderInfoMail();
PRBool serverIsImap = GetMaster()->GetPrefs()->GetMailServerIsIMAP4();
PRBool deleteToTrash = !imapFolder || imapFolder->DeleteIsMoveToTrash();
PRBool showDeletedMessages = (!imapFolder) || imapFolder->ShowDeletedMessages();
if (deleteToTrash || !serverIsImap)
{
// set value to trash folder
MSG_FolderInfoMail *mailTrash = GetTrashFolder();
if (mailTrash)
value = (void *) mailTrash->GetPathname();
msgHdr->OrFlags(MSG_FLAG_READ); // mark read in trash.
}
else // (!deleteToTrash && serverIsImap)
{
msgHdr->OrFlags(MSG_FLAG_READ | MSG_FLAG_IMAP_DELETED);
nsMsgKeyArray keysToFlag;
keysToFlag.Add(msgHdr->GetMessageKey());
if (imapFolder)
imapFolder->StoreImapFlags(m_pane, kImapMsgSeenFlag | kImapMsgDeletedFlag, TRUE, keysToFlag, ((ParseIMAPMailboxState *) this)->GetFilterUrlQueue());
if (!showDeletedMessages)
msgMoved = TRUE; // this will prevent us from adding the header to the db.
}
#endif // DOING_DELETE
}
case nsMsgFilterActionMoveToFolder:
{
// if moving to a different file, do it.
char *folderName = nsnull;
rv = GetName(&folderName);
if (value && PL_strcasecmp(folderName, (char *) value))
{
PRUint32 msgFlags;
msgHdr->GetFlags(&msgFlags);
if (msgFlags & MSG_FLAG_MDN_REPORT_NEEDED &&
!isRead)
{
#if DOING_MDN // leave it to the user aciton
struct message_header to;
struct message_header cc;
GetAggregateHeader (m_toList, &to);
GetAggregateHeader (m_ccList, &cc);
msgHdr->SetFlags(msgFlags & ~MSG_FLAG_MDN_REPORT_NEEDED);
msgHdr->OrFlags(MSG_FLAG_MDN_REPORT_SENT, &newFlags);
if (actionType == nsMsgFilterActionDelete)
{
MSG_ProcessMdnNeededState processMdnNeeded
(MSG_ProcessMdnNeededState::eDeleted,
m_pane, m_folder, msgHdr->GetMessageKey(),
&state->m_return_path, &state->m_mdn_dnt,
&to, &cc, &state->m_subject,
&state->m_date, &state->m_mdn_original_recipient,
&state->m_message_id, state->m_headers,
(PRInt32) state->m_headers_fp, TRUE);
}
else
{
MSG_ProcessMdnNeededState processMdnNeeded
(MSG_ProcessMdnNeededState::eProcessed,
m_pane, m_folder, msgHdr->GetMessageKey(),
&state->m_return_path, &state->m_mdn_dnt,
&to, &cc, &state->m_subject,
&state->m_date, &state->m_mdn_original_recipient,
&state->m_message_id, state->m_headers,
(PRInt32) state->m_headers_fp, TRUE);
}
char *tmp = (char*) to.value;
PR_FREEIF(tmp);
tmp = (char*) cc.value;
PR_FREEIF(tmp);
#endif
}
nsresult err = MoveIncorporatedMessage(msgHdr, mDatabase, (char *) value, filter);
if (NS_SUCCEEDED(err))
m_msgMovedByFilter = PR_TRUE;
}
delete [] folderName;
}
break;
case nsMsgFilterActionMarkRead:
MarkFilteredMessageRead(msgHdr);
break;
case nsMsgFilterActionKillThread:
// for ignore and watch, we will need the db
// to check for the flags in msgHdr's that
// get added, because only then will we know
// the thread they're getting added to.
msgHdr->OrFlags(MSG_FLAG_IGNORED, &newFlags);
break;
case nsMsgFilterActionWatchThread:
msgHdr->OrFlags(MSG_FLAG_WATCHED, &newFlags);
break;
case nsMsgFilterActionChangePriority:
msgHdr->SetPriority(*(nsMsgPriority *) &value);
break;
default:
break;
}
}
return rv;
}
}
nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter)
{
nsresult err = NS_OK;
if (fUrlQueue && fUrlQueue->GetPane())
{
// look for matching imap folders, then pop folders
MSG_FolderInfoContainer *imapContainer = m_imapContainer;
nsIMsgFolder *sourceFolder = imapContainer->FindMailPathname(m_mailboxName);
nsIMsgFolder *destinationFolder = imapContainer->FindMailPathname(destFolder);
if (!destinationFolder)
destinationFolder = m_mailMaster->FindMailFolder(destFolder, FALSE);
if (destinationFolder)
{
nsIMsgFolder *inbox=nsnull;
imapContainer->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, &inbox, 1);
if (inbox)
{
MSG_FolderInfoMail *destMailFolder = destinationFolder->GetMailFolderInfo();
// put the header into the source db, since it needs to be there when we copy it
// and we need a valid header to pass to StartAsyncCopyMessagesInto
nsMsgKey keyToFilter = mailHdr->GetMessageKey();
if (sourceDB && destMailFolder)
{
PRBool imapDeleteIsMoveToTrash = m_host->GetDeleteIsMoveToTrash();
nsMsgKeyArray *idsToMoveFromInbox = destMailFolder->GetImapIdsToMoveFromInbox();
idsToMoveFromInbox->Add(keyToFilter);
// this is our last best chance to log this
if (m_filterList->LoggingEnabled())
filter->LogRuleHit(GetLogFile(), mailHdr);
if (imapDeleteIsMoveToTrash)
{
if (m_parseMsgState->m_newMsgHdr)
{
m_parseMsgState->m_newMsgHdr->Release();
m_parseMsgState->m_newMsgHdr = nsnull;
}
}
destinationFolder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
if (imapDeleteIsMoveToTrash)
err = 0;
}
}
}
}
// we have to return an error because we do not actually move the message
// it is done async and that can fail
return err;
}
#endif // DOING_FILTERS
// both of these algorithms assume that key arrays and flag states are sorted by increasing key. // both of these algorithms assume that key arrays and flag states are sorted by increasing key.
void nsImapMailFolder::FindKeysToDelete(const nsMsgKeyArray &existingKeys, nsMsgKeyArray &keysToDelete, nsImapFlagAndUidState *flagState) void nsImapMailFolder::FindKeysToDelete(const nsMsgKeyArray &existingKeys, nsMsgKeyArray &keysToDelete, nsImapFlagAndUidState *flagState)
{ {

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

@ -29,6 +29,13 @@
#include "nsIUrlListener.h" #include "nsIUrlListener.h"
#include "nsIImapIncomingServer.h" // we need this for its IID #include "nsIImapIncomingServer.h" // we need this for its IID
#include "nsIMsgParseMailMsgState.h" #include "nsIMsgParseMailMsgState.h"
#ifdef DEBUG_bienvenu
//#define DOING_FILTERS
#endif
#ifdef DOING_FILTERS
#include "nsIMsgFilterHitNotify.h"
#include "nsIMsgFilterList.h"
#endif
/* fa32d000-f6a0-11d2-af8d-001083002da8 */ /* fa32d000-f6a0-11d2-af8d-001083002da8 */
#define NS_IMAPRESOURCE_CID \ #define NS_IMAPRESOURCE_CID \
@ -43,6 +50,9 @@ class nsImapMailFolder : public nsMsgDBFolder,
public nsIImapMiscellaneousSink, public nsIImapMiscellaneousSink,
public nsICopyMessageListener, public nsICopyMessageListener,
public nsIUrlListener public nsIUrlListener
#ifdef DOING_FILTERS
,public nsIMsgFilterHitNotify
#endif
{ {
public: public:
nsImapMailFolder(); nsImapMailFolder();
@ -231,6 +241,15 @@ public:
NS_IMETHOD ProcessTunnel(nsIImapProtocol* aProtocol, NS_IMETHOD ProcessTunnel(nsIImapProtocol* aProtocol,
TunnelInfo *aInfo); TunnelInfo *aInfo);
#ifdef DOING_FILTERS
// nsIMsgFilterHitNotification method(s)
NS_IMETHOD ApplyFilterHit(nsIMsgFilter *filter, PRBool *applyMore);
nsresult MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter)
#endif // DOING_FILTERS
protected: protected:
// Helper methods // Helper methods
void FindKeysToAdd(const nsMsgKeyArray &existingKeys, nsMsgKeyArray void FindKeysToAdd(const nsMsgKeyArray &existingKeys, nsMsgKeyArray
@ -263,6 +282,10 @@ protected:
PRBool m_haveDiscoverAllFolders; PRBool m_haveDiscoverAllFolders;
PRBool m_haveReadNameFromDB; PRBool m_haveReadNameFromDB;
nsCOMPtr<nsIMsgParseMailMsgState> m_msgParser; nsCOMPtr<nsIMsgParseMailMsgState> m_msgParser;
#ifdef DOING_FILTERS
nsCOMPtr<nsIMsgFilterList> m_filterList;
PRBool m_msgMovedByFilter;
#endif
nsMsgKey m_curMsgUid; nsMsgKey m_curMsgUid;
PRInt32 m_nextMessageByteLength; PRInt32 m_nextMessageByteLength;
nsCOMPtr<nsIEventQueue> m_eventQueue; nsCOMPtr<nsIEventQueue> m_eventQueue;

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

@ -46,6 +46,7 @@ public:
NS_IMETHOD ParseAFolderLine(const char *line, PRUint32 lineLength) = 0; NS_IMETHOD ParseAFolderLine(const char *line, PRUint32 lineLength) = 0;
NS_IMETHOD GetNewMsgHdr(nsIMsgDBHdr ** aMsgHeader) = 0; NS_IMETHOD GetNewMsgHdr(nsIMsgDBHdr ** aMsgHeader) = 0;
NS_IMETHOD FinishHeader() = 0; NS_IMETHOD FinishHeader() = 0;
NS_IMETHOD GetAllHeaders(char **headers, PRInt32 *headersSize) = 0;
}; };
#endif /* nsIMsgParseMailMsgState_h___ */ #endif /* nsIMsgParseMailMsgState_h___ */

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

@ -605,6 +605,16 @@ NS_IMETHODIMP nsParseMailMessageState::FinishHeader()
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsParseMailMessageState::GetAllHeaders(char ** pHeaders, PRInt32 *pHeadersSize)
{
if (!pHeaders || !pHeadersSize)
return NS_ERROR_NULL_POINTER;
*pHeaders = m_headers.GetBuffer();
*pHeadersSize = m_headers.GetBufferPos();
return NS_OK;
}
struct message_header *nsParseMailMessageState::GetNextHeaderInAggregate (nsVoidArray &list) struct message_header *nsParseMailMessageState::GetNextHeaderInAggregate (nsVoidArray &list)
{ {
// When parsing a message with multiple To or CC header lines, we're storing each line in a // When parsing a message with multiple To or CC header lines, we're storing each line in a
@ -1332,6 +1342,10 @@ nsParseNewMailState::nsParseNewMailState()
#endif #endif
} }
#ifdef DOING_FILTERS
NS_IMPL_ISUPPORTS_INHERITED(nsParseNewMailState, nsMsgMailboxParser, nsIMsgFilterHitNotify)
#endif
nsresult nsresult
nsParseNewMailState::Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream) nsParseNewMailState::Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream)
{ {
@ -1538,186 +1552,160 @@ nsIMsgFolder *nsParseNewMailState::GetTrashFolder()
void nsParseNewMailState::ApplyFilters(PRBool *pMoved) void nsParseNewMailState::ApplyFilters(PRBool *pMoved)
{ {
nsIMsgFilter *filter;
PRUint32 filterCount = 0;
PRBool msgMoved = FALSE; PRBool msgMoved = FALSE;
PRUint32 newFlags;
m_msgMovedByFilter = PR_FALSE;
nsIMsgDBHdr *msgHdr = m_newMsgHdr; nsIMsgDBHdr *msgHdr = m_newMsgHdr;
if (m_filterList != nsnull) nsCOMPtr <nsIMsgFolder> inbox;
m_filterList->GetFilterCount(&filterCount); nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(m_rootFolder);
if (rootMsgFolder)
for (PRUint32 filterIndex = 0; filterIndex < filterCount; filterIndex++)
{ {
if (NS_SUCCEEDED(m_filterList->GetFilterAt(filterIndex, &filter))) PRUint32 numFolders;
{ rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, getter_AddRefs(inbox), 1, &numFolders);
PRBool isEnabled; char * headers = m_headers.GetBuffer();
nsMsgFilterType filterType; PRUint32 headersSize = m_headers.GetBufferPos();
nsresult matchTermStatus = m_filterList->ApplyFiltersToHdr(nsMsgFilterInboxRule, msgHdr, inbox,
m_mailDB, headers, headersSize, this);
}
filter->IsFilterEnabled(&isEnabled); if (pMoved)
if (!isEnabled) *pMoved = m_msgMovedByFilter;
continue; }
filter->GetFilterType(&filterType); NS_IMETHODIMP nsParseNewMailState::ApplyFilterHit(nsIMsgFilter *filter, PRBool *applyMore)
if (filterType == nsMsgFilterInboxJavaScript) {
{ nsMsgRuleActionType actionType;
#ifdef DOING_JSFILTERS void *value = nsnull;
if (JSMailFilter_execute(this, filter, msgHdr, m_mailDB, &msgMoved) == SearchError_Success) PRUint32 newFlags;
break; nsresult rv = NS_OK;
#endif
}
else if (filterType == nsMsgFilterInboxRule)
{
nsresult matchTermStatus = NS_OK;
{ if (!applyMore)
// how are we going to do this? Probably we need to load {
// the offline mail search service and run the filter, NS_ASSERTION(PR_FALSE, "need to return status!");
// or perhaps just add an interface on the filter object return NS_ERROR_NULL_POINTER;
// that does it internally. }
// look at action - currently handle move
nsCOMPtr <nsIMsgFolder> inbox;
nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(m_rootFolder);
if (rootMsgFolder)
{
PRUint32 numFolders;
rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, getter_AddRefs(inbox), 1, &numFolders);
char * headers = m_headers.GetBuffer();
PRUint32 headersSize = m_headers.GetBufferPos();
matchTermStatus = filter->MatchHdr(msgHdr, inbox, m_mailDB, headers, headersSize);
}
}
if (matchTermStatus == NS_OK)
{
nsMsgRuleActionType actionType;
void *value = nsnull;
// look at action - currently handle move
#ifdef DEBUG_bienvenu #ifdef DEBUG_bienvenu
printf("got a rule hit!\n"); printf("got a rule hit!\n");
#endif #endif
if (NS_SUCCEEDED(filter->GetAction(&actionType, &value))) if (NS_SUCCEEDED(filter->GetAction(&actionType, &value)))
{ {
PRUint32 msgFlags; nsIMsgDBHdr *msgHdr = m_newMsgHdr;
PRUint32 msgFlags;
msgHdr->GetFlags(&msgFlags); msgHdr->GetFlags(&msgFlags);
PRBool isRead = (msgFlags & MSG_FLAG_READ); PRBool isRead = (msgFlags & MSG_FLAG_READ);
switch (actionType) switch (actionType)
{ {
case nsMsgFilterActionDelete: case nsMsgFilterActionDelete:
{ {
#ifdef DOING_DELETE #ifdef DOING_DELETE
MSG_IMAPFolderInfoMail *imapFolder = m_folder->GetIMAPFolderInfoMail(); MSG_IMAPFolderInfoMail *imapFolder = m_folder->GetIMAPFolderInfoMail();
PRBool serverIsImap = GetMaster()->GetPrefs()->GetMailServerIsIMAP4(); PRBool serverIsImap = GetMaster()->GetPrefs()->GetMailServerIsIMAP4();
PRBool deleteToTrash = !imapFolder || imapFolder->DeleteIsMoveToTrash(); PRBool deleteToTrash = !imapFolder || imapFolder->DeleteIsMoveToTrash();
PRBool showDeletedMessages = (!imapFolder) || imapFolder->ShowDeletedMessages(); PRBool showDeletedMessages = (!imapFolder) || imapFolder->ShowDeletedMessages();
if (deleteToTrash || !serverIsImap) if (deleteToTrash || !serverIsImap)
{ {
// set value to trash folder // set value to trash folder
MSG_FolderInfoMail *mailTrash = GetTrashFolder(); MSG_FolderInfoMail *mailTrash = GetTrashFolder();
if (mailTrash) if (mailTrash)
value = (void *) mailTrash->GetPathname(); value = (void *) mailTrash->GetPathname();
msgHdr->OrFlags(MSG_FLAG_READ); // mark read in trash. msgHdr->OrFlags(MSG_FLAG_READ); // mark read in trash.
} }
else // (!deleteToTrash && serverIsImap) else // (!deleteToTrash && serverIsImap)
{ {
msgHdr->OrFlags(MSG_FLAG_READ | MSG_FLAG_IMAP_DELETED); msgHdr->OrFlags(MSG_FLAG_READ | MSG_FLAG_IMAP_DELETED);
nsMsgKeyArray keysToFlag; nsMsgKeyArray keysToFlag;
keysToFlag.Add(msgHdr->GetMessageKey()); keysToFlag.Add(msgHdr->GetMessageKey());
if (imapFolder) if (imapFolder)
imapFolder->StoreImapFlags(m_pane, kImapMsgSeenFlag | kImapMsgDeletedFlag, TRUE, keysToFlag, ((ParseIMAPMailboxState *) this)->GetFilterUrlQueue()); imapFolder->StoreImapFlags(m_pane, kImapMsgSeenFlag | kImapMsgDeletedFlag, TRUE, keysToFlag, ((ParseIMAPMailboxState *) this)->GetFilterUrlQueue());
if (!showDeletedMessages) if (!showDeletedMessages)
msgMoved = TRUE; // this will prevent us from adding the header to the db. msgMoved = TRUE; // this will prevent us from adding the header to the db.
} }
#endif // DOING_DELETE #endif // DOING_DELETE
} }
case nsMsgFilterActionMoveToFolder: case nsMsgFilterActionMoveToFolder:
// if moving to a different file, do it. // if moving to a different file, do it.
if (value && PL_strcasecmp(m_mailboxName, (char *) value)) if (value && PL_strcasecmp(m_mailboxName, (char *) value))
{ {
PRUint32 msgFlags; PRUint32 msgFlags;
msgHdr->GetFlags(&msgFlags); msgHdr->GetFlags(&msgFlags);
if (msgFlags & MSG_FLAG_MDN_REPORT_NEEDED && if (msgFlags & MSG_FLAG_MDN_REPORT_NEEDED &&
!isRead) !isRead)
{ {
struct message_header to; struct message_header to;
struct message_header cc; struct message_header cc;
GetAggregateHeader (m_toList, &to); GetAggregateHeader (m_toList, &to);
GetAggregateHeader (m_ccList, &cc); GetAggregateHeader (m_ccList, &cc);
msgHdr->SetFlags(msgFlags & ~MSG_FLAG_MDN_REPORT_NEEDED); msgHdr->SetFlags(msgFlags & ~MSG_FLAG_MDN_REPORT_NEEDED);
msgHdr->OrFlags(MSG_FLAG_MDN_REPORT_SENT, &newFlags); msgHdr->OrFlags(MSG_FLAG_MDN_REPORT_SENT, &newFlags);
#if DOING_MDN // leave it to the user aciton #if DOING_MDN // leave it to the user aciton
if (actionType == nsMsgFilterActionDelete) if (actionType == nsMsgFilterActionDelete)
{ {
MSG_ProcessMdnNeededState processMdnNeeded MSG_ProcessMdnNeededState processMdnNeeded
(MSG_ProcessMdnNeededState::eDeleted, (MSG_ProcessMdnNeededState::eDeleted,
m_pane, m_folder, msgHdr->GetMessageKey(), m_pane, m_folder, msgHdr->GetMessageKey(),
&state->m_return_path, &state->m_mdn_dnt, &state->m_return_path, &state->m_mdn_dnt,
&to, &cc, &state->m_subject, &to, &cc, &state->m_subject,
&state->m_date, &state->m_mdn_original_recipient, &state->m_date, &state->m_mdn_original_recipient,
&state->m_message_id, state->m_headers, &state->m_message_id, state->m_headers,
(PRInt32) state->m_headers_fp, TRUE); (PRInt32) state->m_headers_fp, TRUE);
}
else
{
MSG_ProcessMdnNeededState processMdnNeeded
(MSG_ProcessMdnNeededState::eProcessed,
m_pane, m_folder, msgHdr->GetMessageKey(),
&state->m_return_path, &state->m_mdn_dnt,
&to, &cc, &state->m_subject,
&state->m_date, &state->m_mdn_original_recipient,
&state->m_message_id, state->m_headers,
(PRInt32) state->m_headers_fp, TRUE);
}
#endif
char *tmp = (char*) to.value;
PR_FREEIF(tmp);
tmp = (char*) cc.value;
PR_FREEIF(tmp);
}
nsresult err = MoveIncorporatedMessage(msgHdr, m_mailDB, (char *) value, filter);
if (NS_SUCCEEDED(err))
msgMoved = TRUE;
}
break;
case nsMsgFilterActionMarkRead:
MarkFilteredMessageRead(msgHdr);
break;
case nsMsgFilterActionKillThread:
// for ignore and watch, we will need the db
// to check for the flags in msgHdr's that
// get added, because only then will we know
// the thread they're getting added to.
msgHdr->OrFlags(MSG_FLAG_IGNORED, &newFlags);
break;
case nsMsgFilterActionWatchThread:
msgHdr->OrFlags(MSG_FLAG_WATCHED, &newFlags);
break;
case nsMsgFilterActionChangePriority:
msgHdr->SetPriority(*(nsMsgPriority *) &value);
break;
default:
break;
}
PRBool loggingEnabled;
m_filterList->IsLoggingEnabled(&loggingEnabled);
if (loggingEnabled && !msgMoved && actionType != nsMsgFilterActionMoveToFolder)
filter->LogRuleHit(GetLogFile(), msgHdr);
} }
break; else
{
MSG_ProcessMdnNeededState processMdnNeeded
(MSG_ProcessMdnNeededState::eProcessed,
m_pane, m_folder, msgHdr->GetMessageKey(),
&state->m_return_path, &state->m_mdn_dnt,
&to, &cc, &state->m_subject,
&state->m_date, &state->m_mdn_original_recipient,
&state->m_message_id, state->m_headers,
(PRInt32) state->m_headers_fp, TRUE);
}
#endif
char *tmp = (char*) to.value;
PR_FREEIF(tmp);
tmp = (char*) cc.value;
PR_FREEIF(tmp);
} }
nsresult err = MoveIncorporatedMessage(msgHdr, m_mailDB, (char *) value, filter);
if (NS_SUCCEEDED(err))
m_msgMovedByFilter = PR_TRUE;
} }
break;
case nsMsgFilterActionMarkRead:
MarkFilteredMessageRead(msgHdr);
break;
case nsMsgFilterActionKillThread:
// for ignore and watch, we will need the db
// to check for the flags in msgHdr's that
// get added, because only then will we know
// the thread they're getting added to.
msgHdr->OrFlags(MSG_FLAG_IGNORED, &newFlags);
break;
case nsMsgFilterActionWatchThread:
msgHdr->OrFlags(MSG_FLAG_WATCHED, &newFlags);
break;
case nsMsgFilterActionChangePriority:
msgHdr->SetPriority(*(nsMsgPriority *) &value);
break;
default:
break;
} }
PRBool loggingEnabled;
m_filterList->LoggingEnabled(&loggingEnabled);
if (loggingEnabled && !m_msgMovedByFilter && actionType != nsMsgFilterActionMoveToFolder)
filter->LogRuleHit(GetLogFile(), msgHdr);
} }
if (pMoved) return rv;
*pMoved = msgMoved;
} }
int nsParseNewMailState::MarkFilteredMessageRead(nsIMsgDBHdr *msgHdr) int nsParseNewMailState::MarkFilteredMessageRead(nsIMsgDBHdr *msgHdr)
@ -1897,7 +1885,7 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
// We are logging the hit with the old mailHdr, which should work, as long // We are logging the hit with the old mailHdr, which should work, as long
// as LogRuleHit doesn't assume the new hdr. // as LogRuleHit doesn't assume the new hdr.
PRBool loggingEnabled; PRBool loggingEnabled;
m_filterList->IsLoggingEnabled(&loggingEnabled); m_filterList->LoggingEnabled(&loggingEnabled);
if (loggingEnabled) if (loggingEnabled)
filter->LogRuleHit(GetLogFile(), mailHdr); filter->LogRuleHit(GetLogFile(), mailHdr);
@ -2016,7 +2004,7 @@ nsresult ParseIMAPMailboxState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
idsToMoveFromInbox->Add(keyToFilter); idsToMoveFromInbox->Add(keyToFilter);
// this is our last best chance to log this // this is our last best chance to log this
if (m_filterList->IsLoggingEnabled()) if (m_filterList->LoggingEnabled())
filter->LogRuleHit(GetLogFile(), mailHdr); filter->LogRuleHit(GetLogFile(), mailHdr);
if (imapDeleteIsMoveToTrash) if (imapDeleteIsMoveToTrash)

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

@ -32,7 +32,12 @@
#ifdef DEBUG_bienvenu #ifdef DEBUG_bienvenu
#define DOING_FILTERS //#define DOING_FILTERS
#endif
#ifdef DOING_FILTERS
#include "nsIMsgFilterList.h"
#include "nsIMsgFilterHitNotify.h"
#endif #endif
class nsFileSpec; class nsFileSpec;
@ -75,7 +80,7 @@ public:
NS_IMETHOD ParseAFolderLine(const char *line, PRUint32 lineLength); NS_IMETHOD ParseAFolderLine(const char *line, PRUint32 lineLength);
NS_IMETHOD GetNewMsgHdr(nsIMsgDBHdr ** aMsgHeader); NS_IMETHOD GetNewMsgHdr(nsIMsgDBHdr ** aMsgHeader);
NS_IMETHOD FinishHeader(); NS_IMETHOD FinishHeader();
NS_IMETHOD GetAllHeaders(char **headers, PRInt32 *headersSize);
void Init(PRUint32 fileposition); void Init(PRUint32 fileposition);
virtual PRInt32 ParseFolderLine(const char *line, PRUint32 lineLength); virtual PRInt32 ParseFolderLine(const char *line, PRUint32 lineLength);
virtual int StartNewEnvelope(const char *line, PRUint32 lineLength); virtual int StartNewEnvelope(const char *line, PRUint32 lineLength);
@ -233,11 +238,16 @@ private:
}; };
class nsParseNewMailState : public nsMsgMailboxParser class nsParseNewMailState : public nsMsgMailboxParser
#ifdef DOING_FILTERS
, public nsIMsgFilterHitNotify
#endif
{ {
public: public:
nsParseNewMailState(); nsParseNewMailState();
virtual ~nsParseNewMailState(); virtual ~nsParseNewMailState();
#ifdef DOING_FILTERS
NS_DECL_ISUPPORTS_INHERITED
#endif
nsresult Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream); nsresult Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream);
virtual void DoneParsingFolder(); virtual void DoneParsingFolder();
@ -255,6 +265,9 @@ public:
PRBool *pMoved); PRBool *pMoved);
#endif #endif
#ifdef DOING_FILTERS #ifdef DOING_FILTERS
// nsIMsgFilterHitNotification method(s)
NS_IMETHOD ApplyFilterHit(nsIMsgFilter *filter, PRBool *applyMore);
nsOutputFileStream *GetLogFile(); nsOutputFileStream *GetLogFile();
#endif // DOING_FILTERS #endif // DOING_FILTERS
protected: protected:
@ -277,6 +290,7 @@ protected:
char *m_tmpdbName; // Temporary filename of new database char *m_tmpdbName; // Temporary filename of new database
PRBool m_usingTempDB; PRBool m_usingTempDB;
PRBool m_disableFilters; PRBool m_disableFilters;
PRBool m_msgMovedByFilter;
}; };
#ifdef IMAP_NEW_MAIL_HANDLED #ifdef IMAP_NEW_MAIL_HANDLED