Ongoing spam-filtering work for the front end (not yet exposed to the user in default builds). Cleans up unnecessary and partially working UI items; fixes gcc warnings; fixes 3/5 state plugin by adding junkscoreorigin property; moves some plugin interaction from mailCommand.js to nsMsgDBView.cpp. r=sspitzer@netscape.com, sr=bienvenu@netscape.com, a=asa@mozilla.org

This commit is contained in:
dmose%netscape.com 2002-10-24 07:03:04 +00:00
Родитель 299709208c
Коммит 7692842a78
12 изменённых файлов: 268 добавлений и 186 удалений

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

@ -444,184 +444,61 @@ function getJunkmailComponent()
}
}
function analyze(aMessage, aNextFunction)
function analyze(aMsgHdr, aNextFunction)
{
var listener = {
onMessageClassified: function(aMsgURL, aClassification)
{
dump(aMsgURL + ' is ' + (aClassification == nsIJunkMailPlugin.JUNK ? 'JUNK' : 'GOOD') + '\n');
dump(aMsgURL + ' is '
+ (aClassification == nsIJunkMailPlugin.JUNK
? 'JUNK' : 'GOOD') + '\n');
// XXX TODO, make the cut off 50, like in nsMsgSearchTerm.cpp
var score = (aClassification == nsIJunkMailPlugin.JUNK ? "100" : "0");
aMessage.setStringProperty("junkscore", score);
var score =
aClassification == nsIJunkMailPlugin.JUNK ? "100" : "0";
// set these props via the db (instead of the message header
// directly) so that the nsMsgDBView knows to update the UI
//
var db = aMsgHdr.folder.getMsgDatabase(msgWindow);
db.setStringProperty(aMsgHdr.messageKey, "junkscore", score);
db.setStringProperty(aMsgHdr.messageKey, "junkscoreorigin",
"plugin");
aNextFunction();
}
};
// XXX TODO jumping through hoops here.
var messageURI = aMessage.folder.generateMessageURI(aMessage.messageKey) + "?fetchCompleteMessage=true";
var messageURI = aMsgHdr.folder.generateMessageURI(aMsgHdr.messageKey)
+ "?fetchCompleteMessage=true";
gJunkmailComponent.classifyMessage(messageURI, listener);
}
function analyzeFolder()
{
function processNext()
{
if (messages.hasMoreElements()) {
// XXX TODO jumping through hoops here.
var message = messages.getNext().QueryInterface(nsIMsgDBHdr);
while (!message.isRead) {
if (!messages.hasMoreElements()) {
gJunkmailComponent.batchUpdate = false;
return;
}
message = messages.getNext().QueryInterface(nsIMsgDBHdr);
}
analyze(message, processNext);
}
else {
gJunkmailComponent.batchUpdate = false;
}
}
getJunkmailComponent();
var folder = GetFirstSelectedMsgFolder();
var messages = folder.getMessages(msgWindow);
gJunkmailComponent.batchUpdate = true;
processNext();
}
function analyzeMessages()
{
function processNext()
{
if (counter < messages.length) {
// XXX TODO jumping through hoops here.
var messageUri = messages[counter];
var message = messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
++counter;
while (!message.isRead) {
if (counter == messages.length) {
dump('[bayesian filter message analysis complete.]\n');
gJunkmailComponent.mBatchUpdate = false;
return;
}
messageUri = messages[counter];
message = messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
++counter;
}
analyze(message, processNext);
}
else {
dump('[bayesian filter message analysis complete.]\n');
gJunkmailComponent.batchUpdate = false;
gJunkmailComponent.endBatch();
}
}
getJunkmailComponent();
var messages = GetSelectedMessages();
var counter = 0;
gJunkmailComponent.batchUpdate = true;
gJunkmailComponent.startBatch();
dump('[bayesian filter message analysis begins.]\n');
processNext();
}
function writeHash()
{
getJunkmailComponent();
gJunkmailComponent.mTable.writeHash();
}
function mark(aMessage, aSpam, aNextFunction)
{
// XXX TODO jumping through hoops here.
var score = aMessage.getStringProperty("junkscore");
var oldClassification = ((score == "100") ? nsIJunkMailPlugin.JUNK :
(score == "0") ? nsIJunkMailPlugin.GOOD : nsIJunkMailPlugin.UNCLASSIFIED);
var newClassification = (aSpam ? nsIJunkMailPlugin.JUNK : nsIJunkMailPlugin.GOOD);
var messageURI = aMessage.folder.generateMessageURI(aMessage.messageKey) + "?fetchCompleteMessage=true";
var listener = (aNextFunction == null ? null :
{
onMessageClassified: function(aMsgURL, aClassification)
{
aNextFunction();
}
});
gJunkmailComponent.setMessageClassification(messageURI, oldClassification, newClassification, listener);
}
function JunkSelectedMessages(setAsJunk)
{
getJunkmailComponent();
var messages = GetSelectedMessages();
// start the batch of messages
//
gJunkmailComponent.batchUpdate = true;
// mark each one
//
for ( var msg in messages ) {
var message = messenger.messageServiceFromURI(messages[msg])
.messageURIToMsgHdr(messages[msg]);
mark(message, setAsJunk, null);
}
// end the batch (tell the component to write out its data)
//
gJunkmailComponent.batchUpdate = false;
// this actually sets the score on the selected messages
// so we need to call it after we call mark()
gDBView.doCommand(setAsJunk ? nsMsgViewCommandType.junk
: nsMsgViewCommandType.unjunk);
}
// temporary
function markFolderAsJunk(aSpam)
{
getJunkmailComponent();
var listener = {
messageCount: 0,
onMessageClassified: function(aMsgURL, aClassification)
{
if (--this.messageCount == 0) {
dump('[folder marking complete.]\n');
gJunkmailComponent.batchUpdate = false;
}
}
};
var process = function(aMessage)
{
var score = aMessage.getStringProperty("junkscore");
var oldClassification = ((score == "100") ? nsIJunkMailPlugin.JUNK :
(score == "0") ? nsIJunkMailPlugin.GOOD : nsIJunkMailPlugin.UNCLASSIFIED);
var newClassification = (aSpam ? nsIJunkMailPlugin.JUNK : nsIJunkMailPlugin.GOOD);
var messageURI = aMessage.folder.generateMessageURI(aMessage.messageKey) + "?fetchCompleteMessage=true";
++listener.messageCount;
gJunkmailComponent.setMessageClassification(messageURI, oldClassification, newClassification, listener);
}
var folder = GetFirstSelectedMsgFolder();
var messages = folder.getMessages(msgWindow);
var newScore = (aSpam ? "100" : "0");
gJunkmailComponent.batchUpdate = true;
dump('[folder marking starting.]\n');
while (messages.hasMoreElements()) {
var message = messages.getNext().QueryInterface(nsIMsgDBHdr);
process(message);
// now set the score
// XXX TODO invalidate the row
message.setStringProperty("junkscore", newScore);
}
}

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

@ -1435,11 +1435,9 @@ Rights Reserved.
accesskey="&junkMailCmd.accesskey;"
oncommand="MsgJunkMail()"/>
<menuseparator/>
<menuitem label="Mark All Messages In Folder As Junk" oncommand="markFolderAsJunk(true);"/>
<menuitem label="Mark All Messages In Folder As Not Junk" oncommand="markFolderAsJunk(false);"/>
<menuitem label="Analyze Folder" oncommand="analyzeFolder();"/>
<menuitem label="Mark Selected Messages As Junk" oncommand="JunkSelectedMessages(true);"/>
<menuitem label="Mark Selected Messages As Not Junk" oncommand="JunkSelectedMessages(false);"/>
<menuitem label="Analyze Messages" oncommand="analyzeMessages();"/>
<menuitem label="Write DB" oncommand="writeHash();"/>
<menuseparator/>
-->
<menuitem label="&filtersApply.label;"

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

@ -63,10 +63,11 @@ interface nsIMsgFilterPlugin : nsISupports
/**
* When a large number of messages are going to be trained or filtered,
* it's typically not worth it to write everything to disk after
* each message. The calling code will set batchUpdate to true before
* starting a set messages, and then to false once it has finished.
* each message. The calling code will call startBatch() before
* starting a set messages, and then endBatch() once it has finished.
*/
attribute boolean batchUpdate;
void startBatch();
void endBatch();
};
/**
@ -104,9 +105,15 @@ interface nsIJunkMailPlugin : nsIMsgFilterPlugin
/**
* Called when a user forces the classification of a message. Should
* cause the training set to be updated appropriately.
*
* @arg aMsgURI URI of the message to be classified
* @arg aOldUserClassification Was it previous manually classified
* by the user? If so, how?
* @arg aNewClassification New manual classification.
* @arg aListener Callback
*/
void setMessageClassification(in string aMsgURI,
in nsMsgJunkStatus aOldClassification,
in nsMsgJunkStatus aNewClassification,
in nsIJunkMailClassificationListener aListener);
void setMessageClassification(
in string aMsgURI, in nsMsgJunkStatus aOldUserClassification,
in nsMsgJunkStatus aNewClassification,
in nsIJunkMailClassificationListener aListener);
};

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

@ -1243,10 +1243,14 @@ nsresult nsMsgSearchTerm::MatchJunkStatus(const char *aJunkScore, PRBool *pResul
nsMsgJunkStatus junkStatus;
if (aJunkScore && *aJunkScore) {
// I set the cut off at 50. this may change
// it works for our bayesian plugin, as "0" is good, and "100" is junk
// but it might need tweaking for other plugins
junkStatus = (atoi(aJunkScore) > 50) ? nsIJunkMailPlugin::JUNK : nsIJunkMailPlugin::GOOD;
// cut off set at 50. this may change
// it works for our bayesian plugin, as "0" is good, and "100" is junk
// but it might need tweaking for other plugins
if ( atoi(aJunkScore) > 50 ) {
junkStatus = nsIJunkMailPlugin::JUNK;
} else {
junkStatus = nsIJunkMailPlugin::GOOD;
}
}
else
junkStatus = nsIJunkMailPlugin::UNCLASSIFIED;

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

@ -115,6 +115,7 @@ NS_INTERFACE_MAP_BEGIN(nsMsgDBView)
NS_INTERFACE_MAP_ENTRY(nsIDBChangeListener)
NS_INTERFACE_MAP_ENTRY(nsITreeView)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIJunkMailClassificationListener)
NS_INTERFACE_MAP_END
nsMsgDBView::nsMsgDBView()
@ -133,6 +134,7 @@ nsMsgDBView::nsMsgDBView()
mIsNews = PR_FALSE;
mDeleteModel = nsMsgImapDeleteModels::MoveToTrash;
m_deletingRows = PR_FALSE;
mOutstandingJunkBatches = 0;
/* mCommandsNeedDisablingBecauseOffline - A boolean that tell us if we needed to disable commands because we're offline w/o a downloaded msg select */
@ -680,7 +682,8 @@ nsresult nsMsgDBView::FetchLabel(nsIMsgHdr *aHdr, PRUnichar ** aLabelString)
NS_ENSURE_ARG_POINTER(aHdr);
NS_ENSURE_ARG_POINTER(aLabelString);
aHdr->GetLabel(&label);
rv = aHdr->GetLabel(&label);
NS_ENSURE_SUCCESS(rv, rv);
// we don't care if label is not between 1 and PREF_LABELS_MAX inclusive.
if ((label < 1) || (label > PREF_LABELS_MAX))
@ -2066,7 +2069,16 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
{
nsresult rv = NS_OK;
nsMsgKeyArray imapUids;
// if numIndices == 0, return quietly, just in case
//
if (numIndices == 0) {
return NS_OK;
}
NS_ASSERTION(numIndices >= 0, "nsMsgDBView::ApplyCommandToIndices(): "
"numIndices is negative!");
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_folder);
PRBool thisIsImapFolder = (imapFolder != nsnull);
@ -2076,6 +2088,39 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
rv = DeleteMessages(mMsgWindow, indices, numIndices, PR_TRUE);
else
{
nsCOMPtr<nsIJunkMailPlugin> junkPlugin;
// if this is a junk command, start a batch. The batch will be ended
// in the last callback.
//
if ( command == nsMsgViewCommandType::junk
|| command == nsMsgViewCommandType::unjunk ) {
// get the folder from the first item (if it's the search view,
// only one item can be touched at a time; if a regular folder view,
// all items will have the same folder).
//
nsCOMPtr<nsIMsgFolder> folder;
rv = GetFolderForViewIndex(GetAt(indices[0]), getter_AddRefs(folder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgIncomingServer> server;
rv = folder->GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgFilterPlugin> filterPlugin;
rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
NS_ENSURE_SUCCESS(rv, rv);
junkPlugin = do_QueryInterface(filterPlugin, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = junkPlugin->StartBatch();
NS_ENSURE_SUCCESS(rv, rv);
mOutstandingJunkBatches++;
}
for (int32 i = 0; i < numIndices; i++)
{
if (thisIsImapFolder && command != nsMsgViewCommandType::markThreadRead)
@ -2110,10 +2155,12 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
rv = SetLabelByIndex(indices[i], (command - nsMsgViewCommandType::label0));
break;
case nsMsgViewCommandType::junk:
rv = SetStringPropertyByIndex(indices[i], "junkscore", "100");
rv = SetJunkScoreByIndex(junkPlugin.get(), indices[i],
nsIJunkMailPlugin::JUNK, (i == numIndices-1));
break;
case nsMsgViewCommandType::unjunk:
rv = SetStringPropertyByIndex(indices[i], "junkscore", "0");
rv = SetJunkScoreByIndex(junkPlugin.get(), indices[i],
nsIJunkMailPlugin::GOOD, (i == numIndices-1));
break;
case nsMsgViewCommandType::undeleteMsg:
break; // this is completely handled in the imap code below.
@ -2122,7 +2169,7 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
break;
}
}
if (thisIsImapFolder)
{
imapMessageFlagsType flags = kNoImapMsgFlag;
@ -2388,6 +2435,120 @@ nsresult nsMsgDBView::SetStringPropertyByIndex(nsMsgViewIndex index, const char
return rv;
}
nsresult nsMsgDBView::SetJunkScoreByIndex(nsIJunkMailPlugin *aJunkPlugin,
nsMsgViewIndex aIndex,
nsMsgJunkStatus aNewClassification,
PRBool aIsLastInBatch)
{
// get the message header (need this to get string properties)
//
nsCOMPtr <nsIMsgDBHdr> msgHdr;
nsresult rv = GetMsgHdrForViewIndex(aIndex, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
// get the old junk score
//
nsXPIDLCString junkScoreStr;
rv = msgHdr->GetStringProperty("junkscore", getter_Copies(junkScoreStr));
// and the old origin
//
nsXPIDLCString oldOriginStr;
rv = msgHdr->GetStringProperty("junkscoreorigin",
getter_Copies(oldOriginStr));
// if this was not classified by the user, say so
//
nsMsgJunkStatus oldUserClassification;
if (oldOriginStr.get()[0] != 'u') {
oldUserClassification = nsIJunkMailPlugin::UNCLASSIFIED;
} else {
// otherwise, pass the actual user classification
//
if (junkScoreStr.IsEmpty()) {
oldUserClassification = nsIJunkMailPlugin::UNCLASSIFIED;
} else if (atoi(junkScoreStr) > 50) {
oldUserClassification = nsIJunkMailPlugin::JUNK;
} else {
oldUserClassification = nsIJunkMailPlugin::GOOD;
}
}
// get the URI for this message so we can pass it to the plugin
//
nsXPIDLCString uri;
rv = GetURIForViewIndex(aIndex, getter_Copies(uri));
NS_ENSURE_SUCCESS(rv, rv);
if ( aIsLastInBatch ) {
// if there's already a batch in progress, just replace the URI,
// thus causing the batches to be coalesced
//
mLastJunkUriInBatch = uri;
}
// tell the plugin about this change, so that it can (potentially)
// adjust its database appropriately
//
rv = aJunkPlugin->SetMessageClassification(
uri, oldUserClassification, aNewClassification, this);
NS_ENSURE_SUCCESS(rv, rv);
// set the junk score on the message itself
//
rv = SetStringPropertyByIndex(
aIndex, "junkscore",
aNewClassification == nsIJunkMailPlugin::JUNK ? "100" : "0");
NS_ENSURE_SUCCESS(rv, rv);
// this routine is only reached if the user someone touched the UI
// and told us the junk status of this message.
//
rv = SetStringPropertyByIndex(aIndex, "junkscoreorigin", "user");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsMsgDBView::OnMessageClassified(const char *aMsgUrl,
nsMsgJunkStatus aClassification)
{
// is this the last url in the batch?
//
if ( mLastJunkUriInBatch.Equals(aMsgUrl) ) {
// XXX are we allowed to assume m_folder exists here?
//
nsCOMPtr<nsIMsgIncomingServer> server;
nsresult rv = m_folder->GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv, rv);
// get the filter, and QI to the interface we want
//
nsCOMPtr<nsIMsgFilterPlugin> filterPlugin;
rv = server->GetSpamFilterPlugin(getter_AddRefs(filterPlugin));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIJunkMailPlugin> junkPlugin =
do_QueryInterface(filterPlugin, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// close out existing coalesced junk batches
//
for ( ; mOutstandingJunkBatches > 0 ; --mOutstandingJunkBatches ) {
// tell the plugin that all outstanding batches from us
// have finished.
//
rv = junkPlugin->EndBatch();
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
// reversing threads involves reversing the threads but leaving the
// expanded messages ordered relative to the thread, so we
@ -5114,7 +5275,6 @@ PRBool nsMsgDBView::OfflineMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndi
if (localFolder)
return PR_TRUE;
nsresult rv = NS_OK;
for (nsMsgViewIndex index = 0; index < (nsMsgViewIndex) numIndices; index++)
{
PRUint32 flags = m_flags.GetAt(indices[index]);

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
@ -16,11 +16,12 @@
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* Portions created by the Initial Developer are Copyright (C) 2001-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@netscape.com>
* Dan Mosedale <dmose@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -61,7 +62,7 @@
#include "nsIPref.h"
#include "nsIWeakReference.h"
#include "nsIObserver.h"
#include "nsIMsgFilterPlugin.h"
#include "nsIStringBundle.h"
#define MESSENGER_STRING_URL "chrome://messenger/locale/messenger.properties"
@ -88,7 +89,9 @@ enum eFieldType {
// I think this will be an abstract implementation class.
// The classes that implement the tree support will probably
// inherit from this class.
class nsMsgDBView : public nsIMsgDBView, public nsIDBChangeListener, public nsITreeView, public nsIObserver
class nsMsgDBView : public nsIMsgDBView, public nsIDBChangeListener,
public nsITreeView, public nsIObserver,
public nsIJunkMailClassificationListener
{
public:
nsMsgDBView();
@ -99,6 +102,7 @@ public:
NS_DECL_NSIDBCHANGELISTENER
NS_DECL_NSITREEVIEW
NS_DECL_NSIOBSERVER
NS_DECL_NSIJUNKMAILCLASSIFICATIONLISTENER
protected:
static nsrefcnt gInstanceCount;
@ -243,6 +247,10 @@ protected:
virtual nsresult CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool isMove, nsIMsgFolder *destFolder);
virtual nsresult DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool deleteStorage);
nsresult SetStringPropertyByIndex(nsMsgViewIndex index, const char *aProperty, const char *aValue);
nsresult SetJunkScoreByIndex(nsIJunkMailPlugin *aJunkPlugin,
nsMsgViewIndex aIndex,
nsMsgJunkStatus aNewClassification,
PRBool aIsLastInBatch);
nsresult ToggleReadByIndex(nsMsgViewIndex index);
nsresult SetReadByIndex(nsMsgViewIndex index, PRBool read);
nsresult SetThreadOfMsgReadByIndex(nsMsgViewIndex index, nsMsgKeyArray &keysMarkedRead, PRBool read);
@ -354,6 +362,12 @@ protected:
nsString mLabelPrefColors[PREF_LABELS_MAX];
// used to cache the atoms created for each color to be displayed
static nsIAtom* mLabelPrefColorAtoms[PREF_LABELS_MAX];
// used to know to finish out the junk mail classification batch when the
// last classification callback happens
//
nsCString mLastJunkUriInBatch;
PRUint8 mOutstandingJunkBatches;
};
#endif

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

@ -1748,17 +1748,20 @@ nsMsgDBFolder::CallFilterPlugins()
// if we can't get the db, we probably want to continue firing spam filters.
}
// tell the plugin this is the beginning of a batch
// tell the plugin this is the beginning of a batch. this is an
// optimization, so if it fails, try to continue anyway.
//
(void)filterPlugin->SetBatchUpdate(PR_TRUE);
rv = filterPlugin->StartBatch();
if (NS_FAILED(rv)) {
NS_WARNING("nsMsgDBFilter::CallFilterPlugins(): "
"filterPlugin->StartBatch failed");
}
// for each message...
//
nsXPIDLCString uri;
nsXPIDLCString url;
PRUint32 numNewMessages = newMessageKeys->GetSize();
PRInt32 numClassifyRequests = 0;
for ( PRUint32 i=0 ; i < numNewMessages ; ++i )
{
nsXPIDLCString junkScore;
@ -1807,7 +1810,12 @@ nsMsgDBFolder::CallFilterPlugins()
}
// this batch is done
(void)filterPlugin->SetBatchUpdate(PR_FALSE);
//
rv = filterPlugin->EndBatch();
if (NS_FAILED(rv)) {
NS_WARNING("nsMsgDBFilter::CallFilterPlugins(): "
"filterPlugin->EndBatch() failed");
}
NS_DELETEXPCOM(newMessageKeys);
return rv;

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

@ -1992,11 +1992,10 @@ nsMsgIncomingServer::GetSpamFilterPlugin(nsIMsgFilterPlugin **aFilterPlugin)
mFilterPlugin = do_GetService("@mozilla.org/messenger/filter-plugin;1?name=bayesianfilter", &rv);
if (NS_FAILED(rv)) {
NS_ERROR("nsMsgIncomingServer::InitializeFilterPlugins():"
" error creating filter plugin");
return rv;
}
}
NS_IF_ADDREF(*aFilterPlugin = mFilterPlugin);
return NS_OK;
}

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

@ -439,7 +439,7 @@ NS_IMPL_ISUPPORTS2(nsBayesianFilter, nsIMsgFilterPlugin, nsIJunkMailPlugin)
nsBayesianFilter::nsBayesianFilter()
: mGoodCount(0), mBadCount(0),
mBatchUpdate(PR_FALSE), mTrainingDataDirty(PR_FALSE)
mBatchLevel(0), mTrainingDataDirty(PR_FALSE)
{
NS_INIT_ISUPPORTS();
@ -591,17 +591,25 @@ NS_IMETHODIMP nsBayesianFilter::GetShouldDownloadAllHeaders(PRBool *aShouldDownl
return NS_OK;
}
/* attribute boolean batchUpdate; */
NS_IMETHODIMP nsBayesianFilter::GetBatchUpdate(PRBool *aBatchUpdate)
NS_IMETHODIMP nsBayesianFilter::StartBatch(void)
{
*aBatchUpdate = mBatchUpdate;
#ifdef DEBUG_dmose
printf("StartBatch() entered with mBatchLevel=%d\n", mBatchLevel);
#endif
++mBatchLevel;
return NS_OK;
}
NS_IMETHODIMP nsBayesianFilter::SetBatchUpdate(PRBool aBatchUpdate)
NS_IMETHODIMP nsBayesianFilter::EndBatch(void)
{
mBatchUpdate = aBatchUpdate;
#ifdef DEBUG_dmose
printf("EndBatch() entered with mBatchLevel=%d\n", mBatchLevel);
#endif
NS_ASSERTION(mBatchLevel > 0, "nsBayesianFilter::EndBatch() called with"
" mBatchLevel <= 0");
--mBatchLevel;
if (!mBatchUpdate && mTrainingDataDirty)
if (!mBatchLevel && mTrainingDataDirty)
writeTrainingData();
return NS_OK;
@ -709,8 +717,8 @@ void nsBayesianFilter::observeMessage(Tokenizer& tokenizer, const char* messageU
if (listener)
listener->OnMessageClassified(messageURL, newClassification);
if (mTrainingDataDirty && !mBatchUpdate)
if (mTrainingDataDirty && !mBatchLevel)
writeTrainingData();
}
@ -827,6 +835,9 @@ static const char kMagicCookie[] = { '\xFE', '\xED', '\xFA', '\xCE' };
void nsBayesianFilter::writeTrainingData()
{
#ifdef DEBUG_dmose
printf("writeTrainingData() entered\n");
#endif
nsCOMPtr<nsILocalFile> file;
nsresult rv = getTrainingFile(file);
if (NS_FAILED(rv)) return;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
@ -126,7 +126,7 @@ public:
protected:
Tokenizer mGoodTokens, mBadTokens;
PRUint32 mGoodCount, mBadCount;
PRPackedBool mBatchUpdate;
PRUint32 mBatchLevel; // allow for nested batches to happen
PRPackedBool mTrainingDataDirty;
};

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

@ -7121,6 +7121,7 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURL, nsMsgJunkStatus aClas
NS_ENSURE_SUCCESS(rv, rv);
mDatabase->SetStringProperty(msgKey, "junkscore", (aClassification == nsIJunkMailPlugin::JUNK) ? "100" : "0");
mDatabase->SetStringProperty(msgKey, "junkscoreorigin", "plugin");
if (aClassification == nsIJunkMailPlugin::JUNK)
{
@ -7141,7 +7142,9 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURL, nsMsgJunkStatus aClas
if (moveOnSpam)
{
spamSettings->GetSpamFolderURI(getter_Copies(spamFolderURI));
if (!spamFolderURI.IsEmpty())
nsXPIDLCString uri;
GetURI(getter_Copies(uri));
if (!spamFolderURI.IsEmpty() && !spamFolderURI.Equals(uri))
{
nsCOMPtr <nsIRDFService> rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1",&rv);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -3408,6 +3408,7 @@ nsMsgLocalMailFolder::OnMessageClassified(const char *aMsgURL, nsMsgJunkStatus a
NS_ENSURE_SUCCESS(rv, rv);
mDatabase->SetStringProperty(msgKey, "junkscore", (aClassification == nsIJunkMailPlugin::JUNK) ? "100" : "0");
mDatabase->SetStringProperty(msgKey, "junkscoreorigin", "plugin");
nsCOMPtr<nsISpamSettings> spamSettings;
nsXPIDLCString spamFolderURI;