зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
299709208c
Коммит
7692842a78
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче