fix for #161002. implement filter logging. add some UI for applying

filters after the fact.  code cleanup.
r=mscott, sr=bienvenu
This commit is contained in:
sspitzer%netscape.com 2002-09-11 05:03:36 +00:00
Родитель f9b72b149a
Коммит 35dcce26de
21 изменённых файлов: 512 добавлений и 227 удалений

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

@ -162,12 +162,15 @@ interface nsIMsgAccountManager : nsISupports {
void LoadAccounts();
void SetSpecialFoldersForIdentities();
/* unload accounts frees all the account manager data structures */
void UnloadAccounts();
void WriteToFolderCache(in nsIMsgFolderCache folderCache);
void CloseCachedConnections();
void closeCachedConnections();
void shutdownServers();
void CleanupOnExit();
void SetFolderDoingEmptyTrash(in nsIMsgFolder folder);
boolean GetEmptyTrashInProgress();

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

@ -198,6 +198,9 @@ interface nsIMsgIncomingServer : nsISupports {
/* close any server connections */
void CloseCachedConnections();
/* ... */
void shutdown();
/* access to generic attributes */
boolean getBoolValue(in string attr);

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* Alec Flett <alecf@netscape.com>
* Seth Spitzer <sspitzer@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
@ -80,38 +81,41 @@ function MsgFolderPickerOnLoad(pickerID)
function PickedMsgFolder(selection,pickerID)
{
var selectedUri = selection.getAttribute('id');
SetFolderPicker(selectedUri,pickerID);
var selectedUri = selection.getAttribute('id');
SetFolderPicker(selectedUri,pickerID);
}
function SetFolderPicker(uri,pickerID)
{
if (!gMessengerBundle)
gMessengerBundle = document.getElementById("bundle_messenger");
var picker = document.getElementById(pickerID);
var msgfolder = GetMsgFolderFromUri(uri, true);
var picker = document.getElementById(pickerID);
var msgfolder = GetMsgFolderFromUri(uri, true);
if (!msgfolder)
return;
if (!msgfolder) return;
var selectedValue = null;
var serverName;
var selectedValue = null;
var serverName;
if (msgfolder.isServer)
selectedValue = msgfolder.name;
else {
if (msgfolder.server)
serverName = msgfolder.server.prettyName;
else {
dump("Can't find server for " + uri + "\n");
serverName = "???";
}
if (pickerID == "runFiltersFolder")
selectedValue = msgfolder.name;
else {
if (!gMessengerBundle)
gMessengerBundle = document.getElementById("bundle_messenger");
selectedValue = gMessengerBundle.getFormattedString("verboseFolderFormat",
[msgfolder.name, serverName]);
}
}
if (msgfolder.isServer)
selectedValue = msgfolder.name;
else {
if (msgfolder.server)
serverName = msgfolder.server.prettyName;
else {
dump("Cant' find server for " + uri + "\n");
serverName = "???";
}
selectedValue = gMessengerBundle.getFormattedString("verboseFolderFormat",
[msgfolder.name,
serverName]);
}
picker.setAttribute("label",selectedValue);
picker.setAttribute("uri",uri);
picker.setAttribute("label",selectedValue);
picker.setAttribute("uri",uri);
}

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

@ -425,6 +425,7 @@ Rights Reserved.
</rule>
</template>
</menulist>
<menulist id="actionTargetFolder"
containment="http://home.netscape.com/NC-rdf#child"
sortResource="http://home.netscape.com/NC-rdf#FolderTreeName"
@ -485,4 +486,61 @@ Rights Reserved.
</template>
<menupopup/>
</menulist>
<menulist id="runFiltersFolder"
containment="http://home.netscape.com/NC-rdf#child"
sortResource="http://home.netscape.com/NC-rdf#FolderTreeName"
sortDirection="ascending"
datasources="rdf:msgaccountmanager rdf:mailnewsfolders">
<template>
<rule nc:CanFileMessages="true" iscontainer="true" isempty="false">
<menupopup>
<menu uri="..."
class="folderMenuItem menu-iconic"
oncommand="PickedMsgFolder(event.target,'runFiltersFolder')"
SpecialFolder="rdf:http://home.netscape.com/NC-rdf#SpecialFolder"
BiffState="rdf:http://home.netscape.com/NC-rdf#BiffState"
IsServer="rdf:http://home.netscape.com/NC-rdf#IsServer"
IsSecure="rdf:http://home.netscape.com/NC-rdf#IsSecure"
ServerType="rdf:http://home.netscape.com/NC-rdf#ServerType"
label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup class="menulist-menupopup">
<menuitem label="&filemessageschoosethis.label;"
oncommand="PickedMsgFolder(event.target.parentNode.parentNode,'runFiltersFolder')"/>
<menuseparator/>
</menupopup>
</menu>
</menupopup>
</rule>
<rule nc:CanFileMessages="false" iscontainer="true" isempty="false">
<menupopup>
<menu uri="..."
class="folderMenuItem menu-iconic"
oncommand="PickedMsgFolder(event.target,'runFiltersFolder')"
SpecialFolder="rdf:http://home.netscape.com/NC-rdf#SpecialFolder"
BiffState="rdf:http://home.netscape.com/NC-rdf#BiffState"
IsServer="rdf:http://home.netscape.com/NC-rdf#IsServer"
IsSecure="rdf:http://home.netscape.com/NC-rdf#IsSecure"
ServerType="rdf:http://home.netscape.com/NC-rdf#ServerType"
label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup class="menulist-menupopup"/>
</menu>
</menupopup>
</rule>
<rule nc:CanFileMessages="true">
<menupopup>
<menuitem uri="..." value="..."
class="folderMenuItem menuitem-iconic"
oncommand="PickedMsgFolder(event.target,'runFiltersFolder')"
SpecialFolder="rdf:http://home.netscape.com/NC-rdf#SpecialFolder"
BiffState="rdf:http://home.netscape.com/NC-rdf#BiffState"
IsServer="rdf:http://home.netscape.com/NC-rdf#IsServer"
IsSecure="rdf:http://home.netscape.com/NC-rdf#IsSecure"
ServerType="rdf:http://home.netscape.com/NC-rdf#ServerType"
label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</menupopup>
</rule>
</template>
<menupopup/>
</menulist>
</overlay>

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

@ -101,7 +101,7 @@ interface nsIMsgFilter : nsISupports {
// [array, size_is(headerSize)] in string headers,
in unsigned long headerSize, out boolean result);
void LogRuleHit(in nsOutputStream stream, in nsIMsgDBHdr header);
void logRuleHit(in nsIMsgDBHdr header);
};

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@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
@ -41,6 +42,7 @@
#include "nsIMsgFilterHitNotify.idl"
interface nsIOFileStream;
interface nsIOutputStream;
///////////////////////////////////////////////////////////////////////////////
// The Msg Filter List is an interface designed to make accessing filter lists
@ -68,7 +70,7 @@ interface nsIMsgFilterList : nsISupports {
attribute nsIMsgFolder folder;
readonly attribute short version;
readonly attribute string arbitraryHeaders;
readonly attribute string arbitraryHeaders;
readonly attribute boolean shouldDownloadAllHeaders;
readonly attribute unsigned long filterCount;
nsIMsgFilter getFilterAt(in unsigned long filterIndex);
@ -111,14 +113,15 @@ interface nsIMsgFilterList : nsISupports {
in nsIMsgFilterHitNotify listener,
in nsIMsgWindow msgWindow);
// IO routines, used by filter object filing code.
// IO routines, used by filter object filing code.
void writeIntAttr(in nsMsgFilterFileAttribValue attrib, in long value, in nsIOFileStream stream);
void writeStrAttr(in nsMsgFilterFileAttribValue attrib, in string value, in nsIOFileStream stream);
void writeWstrAttr(in nsMsgFilterFileAttribValue attrib, in wstring value, in nsIOFileStream stream);
void writeBoolAttr(in nsMsgFilterFileAttribValue attrib, in boolean value, in nsIOFileStream stream);
boolean matchOrChangeFilterTarget(in string oldUri, in string newUri, in boolean caseInsensitive);
attribute nsIOutputStream logStream;
readonly attribute string logURL;
};

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

@ -24,6 +24,9 @@ var editButton;
var deleteButton;
var reorderUpButton;
var reorderDownButton;
var runFiltersButton;
var runFiltersFolderPickerLabel;
var runFiltersFolderPicker;
const nsMsgFilterMotion = Components.interfaces.nsMsgFilterMotion;
@ -51,11 +54,12 @@ function onLoad()
deleteButton = document.getElementById("deleteButton");
reorderUpButton = document.getElementById("reorderUpButton");
reorderDownButton = document.getElementById("reorderDownButton");
runFiltersButton = document.getElementById("runFiltersButton");
runFiltersFolderPickerLabel = document.getElementById("onLabel");
runFiltersFolderPicker = document.getElementById("runFiltersFolder");
updateButtons();
moveToAlertPosition();
// get the selected server if it can have filters.
var firstItem = getSelectedServerForFilters();
@ -111,16 +115,14 @@ function onCancel()
function onServerClick(event)
{
var item = event.target;
// don't check this in.
setTimeout("setServer(\"" + item.id + "\");", 0);
setServer(item.id, true);
}
// roots the tree at the specified server
function setServer(uri)
function setServer(uri, rebuild)
{
var resource = rdf.GetResource(uri);
var msgFolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder);
var msgFolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder);
//Calling getFilterList will detect any errors in rules.dat, backup the file, and alert the user
//we need to do this because gFilterTree.setAttribute will cause rdf to call getFilterList and there is
@ -129,8 +131,32 @@ function setServer(uri)
if (msgFolder)
msgFolder.getFilterList(gFilterListMsgWindow);
gFilterTree.setAttribute("ref", uri);
updateButtons();
gFilterTree.setAttribute("ref", uri);
// root the folder picker to this server
runFiltersFolderPicker.setAttribute("ref", uri);
// select the first folder., for POP3 and IMAP, the INBOX
runFiltersFolderPicker.selectedIndex = 0;
SetFolderPicker(runFiltersFolderPicker.selectedItem.getAttribute("id"),"runFiltersFolder");
// rebuild tree, since we changed the uri, and clear selection
if (rebuild) {
gFilterTree.view.selection.clearSelection();
gFilterTree.builder.rebuild();
}
var logFilters = document.getElementById("logFilters");
var curFilterList = currentFilterList();
logFilters.checked = curFilterList.loggingEnabled;
updateButtons();
}
function toggleLogFilters()
{
var logFilters = document.getElementById("logFilters");
var curFilterList = currentFilterList();
curFilterList.loggingEnabled = logFilters.checked;
}
function toggleFilter(aFilterURI)
@ -149,19 +175,28 @@ function selectServer(uri)
var serverMenu = document.getElementById("serverMenu");
var menuitems = serverMenu.getElementsByAttribute("id", uri);
serverMenu.selectedItem = menuitems[0];
setServer(uri);
setServer(uri, false);
}
function getFilter(index)
{
var filter = gFilterTree.builderView.getResourceAtIndex(index);
filter = filter.GetDelegate("filter", Components.interfaces.nsIMsgFilter);
return filter;
}
function currentFilter()
{
if (gFilterTree.currentIndex == -1)
return null;
var currentIndex = gFilterTree.currentIndex;
if (currentIndex == -1)
return null;
var filter;
try {
filter = gFilterTree.builderView.getResourceAtIndex(gFilterTree.currentIndex);
filter = filter.GetDelegate("filter", Components.interfaces.nsIMsgFilter);
filter = getFilter(currentIndex);
} catch (ex) {
filter = null;
}
return filter;
}
@ -225,6 +260,30 @@ function onDown(event)
moveCurrentFilter(nsMsgFilterMotion.down);
}
function viewLog()
{
var uri = gFilterTree.getAttribute("ref");
var server = rdf.GetResource(uri).QueryInterface(Components.interfaces.nsIMsgFolder).server;
var filterList = currentFilterList();
openTopWin(filterList.logURL);
}
function runSelectedFilters()
{
var folderURI = runFiltersFolderPicker.getAttribute("uri");
var sel = gFilterTree.view.selection;
for (var i = 0; i < sel.getRangeCount(); i++) {
var start = {}, end = {};
sel.getRangeAt(i, start, end);
for (var j = start.value; j <= end.value; j++) {
var filter = getFilter(j);
alert("run filter " + filter.filterName + " on " + folderURI);
}
}
}
function moveCurrentFilter(motion)
{
var filterList = currentFilterList();
@ -244,7 +303,7 @@ function refreshFilterList()
// store the selected resource before we rebuild the tree
var selectedRes = gFilterTree.currentIndex >= 0 ? gFilterTree.builderView.getResourceAtIndex(gFilterTree.currentIndex) : null;
// rebuild the tree
// rebuild the tree
gFilterTree.view.selection.clearSelection();
gFilterTree.builder.rebuild();
@ -261,11 +320,23 @@ function refreshFilterList()
function updateButtons()
{
var filterSelected = gFilterTree.view.selection.count > 0;
editButton.disabled = !filterSelected;
deleteButton.disabled = !filterSelected;
reorderUpButton.disabled = !(filterSelected && gFilterTree.currentIndex > 0);
reorderDownButton.disabled = !(filterSelected && gFilterTree.currentIndex < gFilterTree.view.rowCount-1);
var numFiltersSelected = gFilterTree.view.selection.count;
var oneFilterSelected = (numFiltersSelected == 1);
// "edit" and "delete" only enabled when one filter selected
editButton.disabled = !oneFilterSelected;
deleteButton.disabled = !oneFilterSelected;
// we can run multiple filters on a folder
// so only disable this UI if no filters are selected
runFiltersButton.disabled = !numFiltersSelected;
runFiltersFolderPickerLabel.disabled = !numFiltersSelected;
runFiltersFolderPicker.disabled = !numFiltersSelected;
// "up" enabled only if one filter selected, and it's not the first
reorderUpButton.disabled = !(oneFilterSelected && gFilterTree.currentIndex > 0);
// "down" enabled only if one filter selected, and it's not the last
reorderDownButton.disabled = !(oneFilterSelected && gFilterTree.currentIndex < gFilterTree.view.rowCount-1);
}
/**
@ -390,4 +461,4 @@ function doHelpButton()
openHelp("mail-filters");
}

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

@ -19,13 +19,15 @@ Communications Corporation. Portions created by Netscape are
Rights Reserved.
Contributor(s): Hkan Waara <hwaara@chello.se>
Seth Spitzer <sspitzer@netscape.com>
-->
<?xml-stylesheet href="chrome://messenger/skin/filterDialog.css" type="text/css"?>
<?xml-stylesheet href="chrome://messenger/skin/folderMenus.css" type="text/css"?>
<?xul-overlay href="chrome://messenger/content/msgFolderPickerOverlay.xul"?>
<!DOCTYPE window SYSTEM "chrome://messenger/locale/FilterListDialog.dtd">
<dialog id="filterListDialog"
xmlns:nc="http://home.netscape.com/NC-rdf#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
@ -42,6 +44,7 @@ Contributor(s): Hkan Waara <hwaara@chello.se>
<script type="application/x-javascript" src="chrome://messenger/content/FilterListDialog.js"/>
<script type="application/x-javascript" src="chrome://help/content/contextHelp.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/utilityOverlay.js"/>
<stringbundle id="bundle_filter" src="chrome://messenger/locale/filter.properties"/>
<keyset id="dialogKeys"/>
@ -64,6 +67,11 @@ Contributor(s): Hkan Waara <hwaara@chello.se>
</template>
</menupopup>
</menulist>
<spacer flex="1"/>
<vbox>
<button label="&viewLogButton.label;" accesskey="&viewLogButton.accesskey;" oncommand="viewLog();"/>
<checkbox id="logFilters" label="&logFilters.label;" accesskey="&logFilters.accesskey;" oncommand="toggleLogFilters()"/>
</vbox>
</hbox>
<grid flex="1">
@ -143,6 +151,17 @@ Contributor(s): Hkan Waara <hwaara@chello.se>
</rows>
</grid>
<separator/>
<hbox align="center">
<button id="runFiltersButton" label="&runFilters.label;" accesskey="&runFilters.accesskey;" oncommand="runSelectedFilters();" disabled="true"/>
<label id="onLabel" value="&on.label;" disabled="true" control="runFiltersFolder"/>
<menulist id="runFiltersFolder" disabled="true"/>
<spacer flex="1"/>
</hbox>
<separator/>
</dialog>

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

@ -14,3 +14,11 @@
<!ENTITY filterHeader.label "Enabled filters are run automatically in the order shown below.">
<!ENTITY filtersForPrefix.label "Filters for:">
<!ENTITY filtersForPrefix.accesskey "F">
<!ENTITY viewLogButton.label "View Filter Log">
<!ENTITY viewLogButton.accesskey "V">
<!ENTITY logFilters.label "Log Filter Use">
<!ENTITY logFilters.accesskey "L">
<!ENTITY runFilters.label "Run Selected Filters">
<!ENTITY runFilters.accesskey "R">
<!ENTITY on.label "on">
<!ENTITY choosethis.label "choose this folder">

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Seth Spitzer <sspitzer@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
@ -50,12 +51,14 @@
#include "nsXPIDLString.h"
#include "nsMsgSearchScopeTerm.h"
#include "nsIMsgAccountManager.h"
#include "nsIMsgIncomingServer.h"
#include "nsMsgSearchValue.h"
#include "nsReadableUtils.h"
#include "nsEscape.h"
#include "nsMsgUtf7Utils.h"
#include "nsIImportService.h"
#include "nsISupportsObsolete.h"
#include "nsIOutputStream.h"
static const char *kImapPrefix = "//imap:";
@ -253,72 +256,80 @@ nsMsgFilter::GetActionTargetFolderUri(char** aResult)
return NS_OK;
}
NS_IMETHODIMP nsMsgFilter::LogRuleHit(nsOutputStream *stream, nsIMsgDBHdr *msgHdr)
NS_IMETHODIMP nsMsgFilter::LogRuleHit(nsIMsgDBHdr *msgHdr)
{
PRTime date;
char dateStr[40]; /* 30 probably not enough */
nsMsgRuleActionType actionType;
nsCOMPtr <nsIOutputStream> logStream;
nsresult rv = m_filterList->GetLogStream(getter_AddRefs(logStream));
NS_ENSURE_SUCCESS(rv,rv);
PRTime date;
char dateStr[40]; /* 30 probably not enough */
nsMsgRuleActionType actionType;
nsXPIDLCString actionFolderUri;
nsXPIDLCString author;
nsXPIDLCString subject;
nsXPIDLCString author;
nsXPIDLCString subject;
nsXPIDLString filterName;
GetFilterName(getter_Copies(filterName));
GetAction(&actionType);
nsresult res;
res = msgHdr->GetDate(&date);
PRExplodedTime exploded;
GetFilterName(getter_Copies(filterName));
GetAction(&actionType);
rv = msgHdr->GetDate(&date);
PRExplodedTime exploded;
PR_ExplodeTime(date, PR_LocalTimeParameters, &exploded);
PR_FormatTimeUSEnglish(dateStr, 100, "%m/%d/%Y %I:%M %p", &exploded);
msgHdr->GetAuthor(getter_Copies(author));
msgHdr->GetSubject(getter_Copies(subject));
if (stream)
{
*stream << "Applied filter \"";
*stream << NS_ConvertUCS2toUTF8(filterName).get();
*stream << "\" to message from ";
*stream << (const char*)author;
*stream << " - ";
*stream << (const char *)subject;
*stream << " at ";
*stream << dateStr;
*stream << "\n";
const char *actionStr = GetActionStr(actionType);
*stream << "Action = ";
*stream << actionStr;
*stream << " ";
if (actionType == nsMsgFilterAction::MoveToFolder) {
GetActionTargetFolderUri(getter_Copies(actionFolderUri));
*stream << (const char *)actionFolderUri;
} else {
*stream << "";
}
*stream << "\n\n";
// XP_FilePrintf(*m_logFile, "Action = %s %s\n\n", actionStr, actionValue);
if (actionType == nsMsgFilterAction::MoveToFolder)
{
nsXPIDLCString msgId;
msgHdr->GetMessageId(getter_Copies(msgId));
*stream << "mailbox:";
*stream << (const char *) actionFolderUri;
*stream << "id = ";
*stream << (const char*)msgId;
*stream << "\n";
msgHdr->GetAuthor(getter_Copies(author));
msgHdr->GetSubject(getter_Copies(subject));
// XP_FilePrintf(m_logFile, "mailbox:%s?id=%s\n", value, (const char *) msgId);
}
}
return NS_OK;
nsCString buffer;
buffer.SetCapacity(512);
buffer = "<pre>\n";
buffer += "Applied filter \"";
buffer += NS_ConvertUCS2toUTF8(filterName).get();
buffer += "\" to message from ";
buffer += (const char*)author;
buffer += " - ";
buffer += (const char *)subject;
buffer += " at ";
buffer += dateStr;
buffer += "\n";
const char *actionStr = GetActionStr(actionType);
buffer += "Action = ";
buffer += actionStr;
buffer += " ";
if (actionType == nsMsgFilterAction::MoveToFolder) {
GetActionTargetFolderUri(getter_Copies(actionFolderUri));
buffer += actionFolderUri.get();
}
buffer += "\n";
if (actionType == nsMsgFilterAction::MoveToFolder) {
nsXPIDLCString msgId;
msgHdr->GetMessageId(getter_Copies(msgId));
buffer += (const char *) actionFolderUri;
buffer += " id = ";
buffer += (const char*)msgId;
buffer += "\n";
}
buffer += "</pre>\n";
PRUint32 writeCount;
rv = logStream->Write(buffer.get(), buffer.Length(), &writeCount);
NS_ENSURE_SUCCESS(rv,rv);
// flush to disk after ever log hit
rv = logStream->Flush();
NS_ENSURE_SUCCESS(rv,rv);
NS_ASSERTION(writeCount == buffer.Length(), "did write out full log hit");
if (writeCount != buffer.Length())
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP nsMsgFilter::MatchHdr(nsIMsgDBHdr *msgHdr, nsIMsgFolder *folder, nsIMsgDatabase *db,
const char *headers, PRUint32 headersSize, PRBool *pResult)
{

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Seth Spitzer <sspitzer@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
@ -52,6 +53,7 @@
#include "nsIImportService.h"
#include "nsMsgBaseCID.h"
#include "nsIMsgFilterService.h"
#include "nsIFileStreams.h"
#include "nsISupportsObsolete.h"
static NS_DEFINE_CID(kMsgFilterServiceCID, NS_MSGFILTERSERVICE_CID);
@ -67,13 +69,13 @@ static const PRUnichar unicodeFormatter[] = {
nsMsgFilterList::nsMsgFilterList() :
m_fileVersion(0)
{
// I don't know how we're going to report this error if we failed to create the isupports array...
nsresult rv;
rv = NS_NewISupportsArray(getter_AddRefs(m_filters));
m_loggingEnabled = PR_FALSE;
m_curFilter = nsnull;
// 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));
m_loggingEnabled = PR_FALSE;
m_curFilter = nsnull;
m_arbitraryHeaders.SetLength(0);
NS_INIT_ISUPPORTS();
NS_INIT_ISUPPORTS();
}
NS_IMPL_ADDREF(nsMsgFilterList)
@ -82,18 +84,17 @@ NS_IMPL_QUERY_INTERFACE1(nsMsgFilterList, nsIMsgFilterList)
NS_IMETHODIMP nsMsgFilterList::CreateFilter(const PRUnichar *name,class nsIMsgFilter **aFilter)
{
NS_ENSURE_ARG_POINTER(aFilter);
NS_ENSURE_ARG_POINTER(aFilter);
nsMsgFilter *filter = new nsMsgFilter;
NS_ENSURE_TRUE(filter, NS_ERROR_OUT_OF_MEMORY);
nsMsgFilter *filter = new nsMsgFilter;
NS_ENSURE_TRUE(filter, NS_ERROR_OUT_OF_MEMORY);
*aFilter = filter;
NS_ADDREF(*aFilter);
NS_ADDREF(*aFilter = filter);
filter->SetFilterName(name);
filter->SetFilterList(this);
filter->SetFilterName(name);
filter->SetFilterList(this);
return NS_OK;
return NS_OK;
}
NS_IMPL_GETSET(nsMsgFilterList, LoggingEnabled, PRBool, m_loggingEnabled);
@ -119,6 +120,90 @@ NS_IMETHODIMP nsMsgFilterList::SaveToFile(nsIOFileStream *stream)
return SaveTextFilters(stream);
}
nsresult
nsMsgFilterList::GetLogFileSpec(nsIFileSpec **aFileSpec)
{
nsCOMPtr <nsIMsgFolder> folder;
nsresult rv = GetFolder(getter_AddRefs(folder));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsIMsgIncomingServer> server;
rv = folder->GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv,rv);
rv = server->GetLocalPath(aFileSpec);
NS_ENSURE_SUCCESS(rv,rv);
rv = (*aFileSpec)->AppendRelativeUnixPath("filterlog.html");
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
NS_IMETHODIMP
nsMsgFilterList::GetLogURL(char **aLogURL)
{
nsCOMPtr <nsIFileSpec> file;
nsresult rv = GetLogFileSpec(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv,rv);
rv = file->GetURLString(aLogURL);
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
NS_IMETHODIMP
nsMsgFilterList::SetLogStream(nsIOutputStream *aLogStream)
{
// if there is a log stream already, flush it to disk and close it
if (m_logStream) {
nsresult rv = m_logStream->Flush();
NS_ENSURE_SUCCESS(rv,rv);
rv = m_logStream->Close();
NS_ENSURE_SUCCESS(rv,rv);
}
m_logStream = aLogStream;
return NS_OK;
}
NS_IMETHODIMP
nsMsgFilterList::GetLogStream(nsIOutputStream **aLogStream)
{
NS_ENSURE_ARG_POINTER(aLogStream);
nsresult rv;
if (!m_logStream) {
nsCOMPtr <nsIFileSpec> file;
rv = GetLogFileSpec(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv,rv);
nsXPIDLCString nativePath;
rv = file->GetNativePath(getter_Copies(nativePath));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsILocalFile> logFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = logFile->InitWithNativePath(nsDependentCString(nativePath));
NS_ENSURE_SUCCESS(rv,rv);
// append to the end of the log file
rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_logStream),
logFile,
PR_CREATE_FILE | PR_WRONLY | PR_APPEND,
0600);
NS_ENSURE_SUCCESS(rv,rv);
if (!m_logStream)
return NS_ERROR_FAILURE;
}
NS_ADDREF(*aLogStream = m_logStream);
return NS_OK;
}
NS_IMETHODIMP
nsMsgFilterList::ApplyFiltersToHdr(nsMsgFilterTypeType filterType,
nsIMsgDBHdr *msgHdr,
@ -171,13 +256,11 @@ NS_IMETHODIMP
nsMsgFilterList::SetDefaultFile(nsIFileSpec *aFileSpec)
{
nsresult rv;
m_defaultFile =
do_CreateInstance(NS_FILESPEC_CONTRACTID, &rv);
m_defaultFile = do_CreateInstance(NS_FILESPEC_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = m_defaultFile->FromFileSpec(aFileSpec);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -637,7 +720,6 @@ nsresult nsMsgFilterList::SaveTextFilters(nsIOFileStream *aStream)
nsMsgFilterList::~nsMsgFilterList()
{
// filters should be released for free, because only isupports array
// is holding onto them, right?
// PRUint32 filterCount;

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@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
@ -44,6 +45,7 @@
#include "nsCOMPtr.h"
#include "nsISupportsArray.h"
#include "nsIFileSpec.h"
#include "nsIOutputStream.h"
const PRInt16 kFileVersion = 8;
const PRInt16 k60Beta1Version = 7;
@ -58,50 +60,48 @@ const PRInt16 k45Version = 6;
////////////////////////////////////////////////////////////////////////////////////////
class nsIMsgFilter;
class nsIOFileStream;
class nsMsgFilter;
class nsMsgFilterList : public nsIMsgFilterList
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGFILTERLIST
//should be generated by idl. commenting out
// NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMSGFILTERLIST_IID)
nsMsgFilterList();
virtual ~nsMsgFilterList();
nsMsgFilterList();
virtual ~nsMsgFilterList();
nsresult Close();
nsresult LoadTextFilters(nsIOFileStream *aStream);
nsresult Close();
nsresult LoadTextFilters(nsIOFileStream *aStream);
protected:
// type-safe accessor when you really have to have an nsMsgFilter
nsresult GetMsgFilterAt(PRUint32 filterIndex, nsMsgFilter **filter);
// type-safe accessor when you really have to have an nsMsgFilter
nsresult GetMsgFilterAt(PRUint32 filterIndex, nsMsgFilter **filter);
#ifdef DEBUG
void Dump();
void Dump();
#endif
protected:
nsresult ComputeArbitraryHeaders();
nsresult SaveTextFilters(nsIOFileStream *aStream);
// file streaming methods
char ReadChar(nsIOFileStream *aStream);
char SkipWhitespace(nsIOFileStream *aStream);
PRBool StrToBool(nsCString &str);
char LoadAttrib(nsMsgFilterFileAttribValue &attrib, nsIOFileStream *aStream);
const char *GetStringForAttrib(nsMsgFilterFileAttribValue attrib);
nsresult LoadValue(nsCString &value, nsIOFileStream *aStream);
nsresult ParseCondition(nsCString &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;
nsCOMPtr<nsISupportsArray> m_filters;
nsresult ComputeArbitraryHeaders();
nsresult SaveTextFilters(nsIOFileStream *aStream);
// file streaming methods
char ReadChar(nsIOFileStream *aStream);
char SkipWhitespace(nsIOFileStream *aStream);
PRBool StrToBool(nsCString &str);
char LoadAttrib(nsMsgFilterFileAttribValue &attrib, nsIOFileStream *aStream);
const char *GetStringForAttrib(nsMsgFilterFileAttribValue attrib);
nsresult LoadValue(nsCString &value, nsIOFileStream *aStream);
nsresult ParseCondition(nsCString &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;
nsCOMPtr<nsISupportsArray> m_filters;
nsCString m_arbitraryHeaders;
nsCOMPtr<nsIFileSpec> m_defaultFile;
private:
nsresult GetLogFileSpec(nsIFileSpec **aFileSpec);
nsCOMPtr<nsIOutputStream> m_logStream;
};
#endif

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

@ -209,8 +209,8 @@ nsresult nsMsgAccountManager::Shutdown()
WriteToFolderCache(m_msgFolderCache);
}
CloseCachedConnections();
UnloadAccounts();
(void)ShutdownServers();
(void)UnloadAccounts();
//shutdown removes nsIIncomingServer listener from biff manager, so do it after accounts have been unloaded
nsCOMPtr<nsIMsgBiffManager> biffService = do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
@ -930,8 +930,8 @@ nsMsgAccountManager::hashUnloadServer(nsHashKey *aKey, void *aData,
/* static */ void nsMsgAccountManager::LogoutOfServer(nsIMsgIncomingServer *aServer)
{
nsresult rv = aServer->CloseCachedConnections();
NS_ASSERTION(NS_SUCCEEDED(rv), "CloseCachedConnections failed");
nsresult rv = aServer->Shutdown();
NS_ASSERTION(NS_SUCCEEDED(rv), "Shutdown of server failed");
rv = aServer->ForgetSessionPassword();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove the password associated with server");
}
@ -1113,14 +1113,22 @@ PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aDa
return PR_TRUE;
}
// enumaration for closing cached connections.
PRBool nsMsgAccountManager::closeCachedConnections(nsHashKey *aKey, void *aData, void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
server->CloseCachedConnections();
return PR_TRUE;
server->CloseCachedConnections();
return PR_TRUE;
}
PRBool nsMsgAccountManager::shutdown(nsHashKey *aKey, void *aData, void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
server->Shutdown();
return PR_TRUE;
}
@ -1540,7 +1548,7 @@ nsMsgAccountManager::SetSpecialFoldersForIdentities()
return NS_OK;
}
nsresult
NS_IMETHODIMP
nsMsgAccountManager::UnloadAccounts()
{
// release the default account
@ -1557,18 +1565,25 @@ nsMsgAccountManager::UnloadAccounts()
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::ShutdownServers()
{
m_incomingServers.Enumerate(shutdown, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::CloseCachedConnections()
{
m_incomingServers.Enumerate(closeCachedConnections, nsnull);
return NS_OK;
m_incomingServers.Enumerate(closeCachedConnections, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::CleanupOnExit()
{
m_incomingServers.Enumerate(cleanupOnExit, nsnull);
return NS_OK;
m_incomingServers.Enumerate(cleanupOnExit, nsnull);
return NS_OK;
}
NS_IMETHODIMP

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

@ -127,7 +127,7 @@ private:
static PRBool PR_CALLBACK hashUnloadServer(nsHashKey *aKey, void *aData,
void *closure);
// close connection and forget cached password
// shutdown server and forget cached password
static PRBool PR_CALLBACK hashLogoutOfServer(nsHashKey *aKey, void *aData,
void *closure);
@ -173,6 +173,7 @@ private:
// write out the server's cache through the given folder cache
static PRBool PR_CALLBACK writeFolderCache(nsHashKey *aKey, void *aData, void *closure);
static PRBool PR_CALLBACK shutdown(nsHashKey *aKey, void *aData, void *closure);
static PRBool PR_CALLBACK closeCachedConnections(nsHashKey *aKey, void *aData, void *closure);
static void getUniqueKey(const char* prefix,

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

@ -216,11 +216,27 @@ NS_IMETHODIMP nsMsgIncomingServer::WriteToFolderCache(nsIMsgFolderCache *folderC
return rv;
}
NS_IMETHODIMP
nsMsgIncomingServer::Shutdown()
{
nsresult rv = CloseCachedConnections();
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsIMsgFilterList> filterList;
rv = GetFilterList(nsnull, getter_AddRefs(filterList));
NS_ENSURE_SUCCESS(rv,rv);
// close the filter log stream
rv = filterList->SetLogStream(nsnull);
NS_ENSURE_SUCCESS(rv,rv);
return rv;
}
NS_IMETHODIMP
nsMsgIncomingServer::CloseCachedConnections()
{
// derived class should override if they cache connections.
return NS_OK;
// derived class should override if they cache connections.
return NS_OK;
}
NS_IMETHODIMP

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

@ -970,7 +970,6 @@ NS_IMETHODIMP nsImapIncomingServer::PerformBiff()
NS_IMETHODIMP
nsImapIncomingServer::CloseCachedConnections()
{
nsCOMPtr<nsIImapProtocol> connection;
PR_CEnterMonitor(this);
@ -988,6 +987,7 @@ nsImapIncomingServer::CloseCachedConnections()
if (connection)
connection->TellThreadToDie(PR_TRUE);
}
PR_CExitMonitor(this);
return rv;
}
@ -3652,23 +3652,27 @@ nsImapIncomingServer::GetNewMessagesForNonInboxFolders(nsIMsgFolder *aRootFolder
NS_IMETHODIMP
nsImapIncomingServer::GetShouldDownloadAllHeaders(PRBool *aResult)
{
nsresult rv = NS_OK; //for now checking for filters is enough
nsCOMPtr <nsIMsgFilterList> filterList; //later on we might have to check for MDN ;
if (!mFilterList)
GetFilterList(nsnull, getter_AddRefs(filterList));
if (mFilterList)
rv = mFilterList->GetShouldDownloadAllHeaders(aResult);
else
*aResult = PR_FALSE;
*aResult = PR_FALSE;
//for now checking for filters is enough
//later on we might have to check for MDN
nsCOMPtr <nsIMsgFilterList> filterList;
nsresult rv = GetFilterList(nsnull, getter_AddRefs(filterList));
NS_ENSURE_SUCCESS(rv,rv);
rv = filterList->GetShouldDownloadAllHeaders(aResult);
NS_ENSURE_SUCCESS(rv,rv);
return rv;
}
NS_IMETHODIMP
nsImapIncomingServer::GetArbitraryHeaders(char **aResult)
{
nsresult rv =NS_OK;
if (mFilterList)
rv = mFilterList->GetArbitraryHeaders(aResult);
nsCOMPtr <nsIMsgFilterList> filterList;
nsresult rv = GetFilterList(nsnull, getter_AddRefs(filterList));
NS_ENSURE_SUCCESS(rv,rv);
rv = filterList->GetArbitraryHeaders(aResult);
return rv;
}

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
* Seth Spitzer <sspitzer@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
@ -2843,7 +2844,6 @@ NS_IMETHODIMP nsImapMailFolder::ApplyFilterHit(nsIMsgFilter *filter, nsIMsgWindo
#endif
if (NS_SUCCEEDED(filter->GetAction(&actionType)))
{
if (actionType == nsMsgFilterAction::MoveToFolder)
{
filter->GetActionTargetFolderUri(getter_Copies(actionTargetFolderUri));
@ -2964,9 +2964,19 @@ NS_IMETHODIMP nsImapMailFolder::ApplyFilterHit(nsIMsgFilter *filter, nsIMsgWindo
default:
break;
}
// we log move hits in MoveIncorporatedMessage()
if (actionType != nsMsgFilterAction::MoveToFolder) {
PRBool loggingEnabled = PR_FALSE;
if (m_filterList)
(void)m_filterList->GetLoggingEnabled(&loggingEnabled);
if (loggingEnabled)
(void)filter->LogRuleHit(msgHdr);
}
}
}
return rv;
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::SetImapFlags(const char *uids, PRInt32 flags, nsIURI **url)
@ -3342,10 +3352,12 @@ nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
// keep track of nsIMsgFolder, nsMsgKeyArray pairs here in the imap code.
// nsMsgKeyArray *idsToMoveFromInbox = msgFolder->GetImapIdsToMoveFromInbox();
// idsToMoveFromInbox->Add(keyToFilter);
PRBool loggingEnabled = PR_FALSE;
if (m_filterList)
(void)m_filterList->GetLoggingEnabled(&loggingEnabled);
// this is our last best chance to log this
// if (m_filterList->LoggingEnabled())
// filter->LogRuleHit(GetLogFile(), mailHdr);
if (loggingEnabled)
(void)filter->LogRuleHit(mailHdr);
if (imapDeleteIsMoveToTrash)
{

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

@ -190,7 +190,9 @@ nsShouldIgnoreFile(nsString& name)
if (firstChar == '.' || firstChar == '#' || name.CharAt(name.Length() - 1) == '~')
return PR_TRUE;
if (name.EqualsIgnoreCase("rules.dat") || name.EqualsIgnoreCase("rulesbackup.dat"))
if (name.EqualsIgnoreCase("rules.dat") ||
name.EqualsIgnoreCase("filterlog.html") ||
name.EqualsIgnoreCase("rulesbackup.dat"))
return PR_TRUE;

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

@ -1440,7 +1440,6 @@ nsParseNewMailState::nsParseNewMailState()
: m_tmpdbName(nsnull), m_usingTempDB(PR_FALSE), m_disableFilters(PR_FALSE)
{
m_inboxFileStream = nsnull;
m_logFile = nsnull;
m_ibuffer = nsnull;
m_ibuffer_size = 0;
m_ibuffer_fp = 0;
@ -1477,7 +1476,6 @@ nsParseNewMailState::Init(nsIFolder *rootFolder, nsIMsgFolder *downloadFolder, n
rv = rootMsgFolder->GetServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv))
rv = server->GetFilterList(aMsgWindow, getter_AddRefs(m_filterList));
m_logFile = nsnull;
if (m_filterList)
rv = server->ConfigureTemporaryReturnReceiptsFilter(m_filterList);
@ -1491,11 +1489,6 @@ nsParseNewMailState::Init(nsIFolder *rootFolder, nsIMsgFolder *downloadFolder, n
nsParseNewMailState::~nsParseNewMailState()
{
if (m_logFile != nsnull)
{
m_logFile->close();
delete m_logFile;
}
if (m_mailDB)
m_mailDB->Close(PR_TRUE);
// if (m_usingTempDB)
@ -1578,29 +1571,6 @@ void nsParseNewMailState::SetUsingTempDB(PRBool usingTempDB, char *tmpDBName)
m_tmpdbName = tmpDBName;
}
nsOutputFileStream * nsParseNewMailState::GetLogFile ()
{
// This log file is used by regular filters and JS filters
if (m_logFile == nsnull)
{
nsCOMPtr<nsIFile> logDir;
NS_GetSpecialDirectory(NS_APP_MAIL_50_DIR, getter_AddRefs(logDir));
logDir->AppendNative(NS_LITERAL_CSTRING("filter.log"));
nsCAutoString pathBuf;
nsresult rv = logDir->GetNativePath(pathBuf);
if (NS_FAILED(rv)) return nsnull;
nsFileSpec logFile(pathBuf.get());
m_logFile = new nsOutputFileStream(logFile, PR_WRONLY | PR_CREATE_FILE, 00600);
}
return m_logFile;
}
nsresult nsParseNewMailState::GetTrashFolder(nsIMsgFolder **pTrashFolder)
{
nsresult rv=NS_ERROR_UNEXPECTED;
@ -1745,7 +1715,7 @@ NS_IMETHODIMP nsParseNewMailState::ApplyFilterHit(nsIMsgFilter *filter, nsIMsgWi
if (m_filterList)
m_filterList->GetLoggingEnabled(&loggingEnabled);
if (loggingEnabled && !m_msgMovedByFilter && actionType != nsMsgFilterAction::MoveToFolder)
filter->LogRuleHit(GetLogFile(), msgHdr);
filter->LogRuleHit(msgHdr);
}
return rv;
}
@ -1958,7 +1928,7 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
if (m_filterList)
m_filterList->GetLoggingEnabled(&loggingEnabled);
if (loggingEnabled)
filter->LogRuleHit(GetLogFile(), mailHdr);
filter->LogRuleHit(mailHdr);
// cleanup after mailHdr in source DB because we moved the message.
m_mailDB->RemoveHeaderMdbRow(mailHdr);
@ -2077,8 +2047,11 @@ nsresult ParseIMAPMailboxState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
idsToMoveFromInbox->Add(keyToFilter);
// this is our last best chance to log this
if (m_filterList->LoggingEnabled())
filter->LogRuleHit(GetLogFile(), mailHdr);
PRBool loggingEnabled = PR_FALSE;
if (m_filterList)
m_filterList->GetLoggingEnabled(&loggingEnabled);
if (loggingEnabled)
filter->LogRuleHit(mailHdr);
if (imapDeleteIsMoveToTrash)
{

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

@ -268,7 +268,6 @@ protected:
void LogRuleHit(nsIMsgFilter *filter, nsIMsgDBHdr *msgHdr);
nsCOMPtr <nsIMsgFilterList> m_filterList;
nsCOMPtr <nsIFolder> m_rootFolder;
nsOutputFileStream *m_logFile;
nsIOFileStream *m_inboxFileStream;
nsFileSpec m_inboxFileSpec;
PRBool m_disableFilters;

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

@ -303,3 +303,4 @@ nsPop3IncomingServer::GetOfflineSupportLevel(PRInt32 *aSupportLevel)
*aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE;
return NS_OK;
}