170555 r=mscott sr=bienvenu Adding ability to purge junk folder automatically at interval of 1 day. Also

added code to specialize/unspecialize junk folder when the user changes junk folder from UI
This commit is contained in:
naving%netscape.com 2002-10-04 22:32:15 +00:00
parent 7dda838fe9
commit f04220e6bd
18 changed files with 835 additions and 13 deletions

View File

@ -180,6 +180,17 @@
{ 0x8a, 0x88, 0x0, 0x60, 0xb0, 0xfc, 0x4, 0xd2 } }
//
// nsMsgPurgeService
//
#define NS_MSGPURGESERVICE_CONTRACTID \
"@mozilla.org/messenger/purgeService;1"
/* a687b474-afd8-418f-8ad9-f362202ae9a9 */
#define NS_MSGPURGESERVICE_CID \
{ 0xa687b474, 0xafd8, 0x418f, \
{ 0x8a, 0xd9, 0xf3, 0x62, 0x20, 0x2a, 0xe9, 0xa9 } }
//
// nsStatusBarBiffManager
//

View File

@ -72,6 +72,7 @@
#include "nsMsgAccountManagerDS.h"
#include "nsMsgBiffManager.h"
#include "nsMsgPurgeService.h"
#include "nsStatusBarBiffManager.h"
#include "nsCopyMessageStreamListener.h"
@ -131,6 +132,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgFilterService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgFilterDataSource)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgFilterDelegateFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgBiffManager, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgPurgeService)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusBarBiffManager, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCopyMessageStreamListener)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgCopyService)
@ -253,6 +255,10 @@ static const nsModuleComponentInfo gComponents[] = {
NS_MSGBIFFMANAGER_CONTRACTID,
nsMsgBiffManagerConstructor,
},
{ "Messenger Purge Service", NS_MSGPURGESERVICE_CID,
NS_MSGPURGESERVICE_CONTRACTID,
nsMsgPurgeServiceConstructor,
},
{ "Status Bar Biff Manager", NS_STATUSBARBIFFMANAGER_CID,
NS_STATUSBARBIFFMANAGER_CONTRACTID,
nsStatusBarBiffManagerConstructor,

View File

@ -1090,6 +1090,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMsgPurgeService.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMessengerBootstrap.cpp</PATH>
@ -1449,6 +1456,11 @@
<PATH>nsMsgBiffManager.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMsgPurgeService.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMessengerBootstrap.cpp</PATH>
@ -2663,6 +2675,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMsgPurgeService.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS>Debug</FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMessengerBootstrap.cpp</PATH>
@ -3022,6 +3041,11 @@
<PATH>nsMsgBiffManager.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMsgPurgeService.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMessengerBootstrap.cpp</PATH>
@ -3262,6 +3286,12 @@
<PATH>nsMsgBiffManager.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>mailnewsDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsMsgPurgeService.cpp</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>mailnewsDebug.shlb</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

View File

@ -856,6 +856,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMessenger.idl</PATH>
@ -1235,6 +1242,11 @@
<PATH>nsIMsgBiffManager.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMessenger.idl</PATH>
@ -2245,6 +2257,13 @@
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
<FILEKIND>Text</FILEKIND>
<FILEFLAGS></FILEFLAGS>
</FILE>
<FILE>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMessenger.idl</PATH>
@ -2624,6 +2643,16 @@
<PATH>nsIMsgBiffManager.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMessenger.idl</PATH>
@ -2926,6 +2955,12 @@
<PATH>nsIMsgBiffManager.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>headers</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>nsIMsgPurgeService.idl</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
<TARGETNAME>headers</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>

View File

@ -24,6 +24,7 @@ nsIMsgVCard.idl
nsIUrlListener.idl
nsIUrlListenerManager.idl
nsIMsgBiffManager.idl
nsIMsgPurgeService.idl
nsIMsgCopyService.idl
nsIMsgCopyServiceListener.idl
nsIMsgStatusFeedback.idl

View File

@ -60,6 +60,7 @@ XPIDLSRCS = \
nsIUrlListener.idl \
nsIUrlListenerManager.idl \
nsIMsgBiffManager.idl \
nsIMsgPurgeService.idl \
nsIMsgCopyService.idl \
nsIMsgCopyServiceListener.idl \
nsIMsgStatusFeedback.idl \

View File

@ -419,4 +419,7 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne
attribute nsIDBFolderInfo dBTransferInfo;
string getStringProperty(in string propertyName);
void setStringProperty(in string propertyName, in string propertyValue);
};

View File

@ -0,0 +1,47 @@
/* -*- 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
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Navin Gupta <naving@netscape.com> (Original Author)
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(c73294b2-b619-4915-b0e8-314d4215e08d)]
interface nsIMsgPurgeService : nsISupports {
void init();
void shutdown();
};

View File

@ -30,6 +30,7 @@ nsMsgAccount.h
nsMsgAccountManager.h
nsMsgRDFDataSource.h
nsMsgBiffManager.h
nsMsgPurgeService.h
nsCopyMessageStreamListener.h
nsMsgCopyService.h
nsMsgStatusFeedback.h

View File

@ -83,6 +83,7 @@ CPPSRCS = \
nsMsgAccountManagerDS.cpp \
nsMsgRDFUtils.cpp \
nsMsgBiffManager.cpp \
nsMsgPurgeService.cpp \
nsMsgCopyService.cpp \
nsMsgFolderCache.cpp \
nsMsgFolderCacheElement.cpp \
@ -126,6 +127,7 @@ EXPORTS = \
nsMsgRDFDataSource.h \
nsMsgRDFUtils.h \
nsMsgBiffManager.h \
nsMsgPurgeService.h \
nsCopyMessageStreamListener.h \
nsMsgCopyService.h \
nsMsgStatusFeedback.h \

View File

@ -67,6 +67,7 @@
#include "nsNetCID.h"
#include "nsISmtpService.h"
#include "nsIMsgBiffManager.h"
#include "nsIMsgPurgeService.h"
#include "nsIObserverService.h"
#include "nsIMsgMailSession.h"
#include "nsIEventQueueService.h"
@ -215,6 +216,11 @@ nsresult nsMsgAccountManager::Shutdown()
nsCOMPtr<nsIMsgBiffManager> biffService = do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && biffService)
biffService->Shutdown();
//shutdown removes nsIIncomingServer listener from purge service, so do it after accounts have been unloaded
nsCOMPtr<nsIMsgPurgeService> purgeService = do_GetService(NS_MSGPURGESERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && purgeService)
purgeService->Shutdown();
if (m_prefs) {
nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
@ -1314,6 +1320,13 @@ nsMsgAccountManager::LoadAccounts()
if (NS_SUCCEEDED(rv))
biffService->Init();
//Ensure purge service has started
nsCOMPtr<nsIMsgPurgeService> purgeService =
do_GetService(NS_MSGPURGESERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
purgeService->Init();
// Ensure messenger OS integration service has started
// note, you can't expect the integrationService to be there
@ -1403,6 +1416,8 @@ nsMsgAccountManager::LoadAccounts()
}
}
}
m_accountsLoaded = PR_TRUE; //It is ok to return null accounts like when we create new profile
if (!accountList || !accountList[0]) {
#ifdef DEBUG_ACCOUNTMANAGER
@ -1410,8 +1425,6 @@ nsMsgAccountManager::LoadAccounts()
#endif
return NS_OK;
}
m_accountsLoaded = PR_TRUE;
/* parse accountList and run loadAccount on each string, comma-separated */
#ifdef DEBUG_ACCOUNTMANAGER

View File

@ -0,0 +1,498 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Navin Gupta <naving@netscape.com> (Original Author)
*
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMsgPurgeService.h"
#include "nsCRT.h"
#include "nsIMsgAccountManager.h"
#include "nsMsgBaseCID.h"
#include "nsMsgUtils.h"
#include "nsMsgSearchCore.h"
#include "msgCore.h"
#include "nsISpamSettings.h"
#include "nsIMsgSearchTerm.h"
#include "nsIMsgHdr.h"
#include "nsIRDFService.h"
#include "nsIFileSpec.h"
#include "nsIMsgProtocolInfo.h"
#define ONE_DAY_IN_MILLISECONDS 86400000000
#define MIN_DELAY_BETWEEN_PURGES 300000000 //minimum delay between two consecutive purges
NS_IMPL_ISUPPORTS3(nsMsgPurgeService, nsIMsgPurgeService, nsIIncomingServerListener, nsIMsgSearchNotify)
void OnPurgeTimer(nsITimer *timer, void *aPurgeService)
{
nsMsgPurgeService *purgeService = (nsMsgPurgeService*)aPurgeService;
purgeService->PerformPurge();
}
nsMsgPurgeService::nsMsgPurgeService()
{
NS_INIT_ISUPPORTS();
mPurgeArray = nsnull;
mHaveShutdown = PR_FALSE;
}
nsMsgPurgeService::~nsMsgPurgeService()
{
if (mPurgeTimer) {
mPurgeTimer->Cancel();
}
PRInt32 count = mPurgeArray->Count();
PRInt32 i;
for(i=0; i < count; i++)
{
nsPurgeEntry *purgeEntry = (nsPurgeEntry*)mPurgeArray->ElementAt(i);
delete purgeEntry;
}
delete mPurgeArray;
if(!mHaveShutdown)
{
Shutdown();
}
}
NS_IMETHODIMP nsMsgPurgeService::Init()
{
nsresult rv;
nsCOMPtr<nsIMsgAccountManager> accountManager =
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
accountManager->AddIncomingServerListener(this);
if(mHaveShutdown) //in turbo mode on profile change we don't need to do anything below this
{
mHaveShutdown = PR_FALSE;
return NS_OK;
}
mPurgeArray = new nsVoidArray();
if(!mPurgeArray)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsMsgPurgeService::Shutdown()
{
if (mPurgeTimer)
{
mPurgeTimer->Cancel();
mPurgeTimer = nsnull;
}
nsresult rv;
nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
{
accountManager->RemoveIncomingServerListener(this);
}
mHaveShutdown = PR_TRUE;
return NS_OK;
}
nsresult nsMsgPurgeService::AddServer(nsIMsgIncomingServer *server)
{
if (FindServer(server) != -1)
return NS_OK;
//Only add it if it hasn't been added already
nsXPIDLCString type;
nsresult rv = server->GetType(getter_Copies(type));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString contractid(NS_MSGPROTOCOLINFO_CONTRACTID_PREFIX);
contractid.Append(type);
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo =
do_GetService(contractid.get(), &rv);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
PRBool canGetIncomingMessages = PR_FALSE;
protocolInfo->GetCanGetIncomingMessages(&canGetIncomingMessages);
if (!canGetIncomingMessages)
return NS_OK;
nsCOMPtr <nsISpamSettings> spamSettings;
rv = server->GetSpamSettings(getter_AddRefs(spamSettings));
NS_ENSURE_SUCCESS(rv, rv);
PRBool purgeSpam;
spamSettings->GetPurge(&purgeSpam);
if (!purgeSpam)
return NS_OK;
nsXPIDLCString junkFolderURI;
spamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI));
if (junkFolderURI.IsEmpty())
return NS_OK;
//we cannot do GetExistingFolder because folder tree has not been built yet.
nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(junkFolderURI.get(), getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgFolder> junkFolder = do_QueryInterface(resource, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsTime lastPurgeTime=0;
nsXPIDLCString lastPurgeTimeString;
rv = junkFolder->GetStringProperty("lastPurgeTime", getter_Copies(lastPurgeTimeString));
if (NS_FAILED(rv)) //it is ok to fail, junk folder may not exist
return NS_OK;
if (!lastPurgeTimeString.IsEmpty())
{
PRInt64 theTime;
PR_ParseTimeString(lastPurgeTimeString.get(), PR_FALSE, &theTime);
lastPurgeTime = theTime;
}
nsPurgeEntry *purgeEntry = new nsPurgeEntry;
if (!purgeEntry)
return NS_ERROR_OUT_OF_MEMORY;
purgeEntry->server = server;
purgeEntry->folderURI = junkFolderURI.get();
nsTime nextPurgeTime;
if (lastPurgeTime)
{
nextPurgeTime = lastPurgeTime;
nextPurgeTime += ONE_DAY_IN_MILLISECONDS;
nsTime currentTime;
if ( nextPurgeTime < currentTime)
nextPurgeTime = currentTime;
}
rv = SetNextPurgeTime(purgeEntry, nextPurgeTime);
NS_ENSURE_SUCCESS(rv, rv);
AddPurgeEntry(purgeEntry);
SetupNextPurge();
return NS_OK;
}
nsresult nsMsgPurgeService::RemoveServer(nsIMsgIncomingServer *server)
{
PRInt32 pos = FindServer(server);
if(pos != -1)
{
nsPurgeEntry *purgeEntry = (nsPurgeEntry*)mPurgeArray->ElementAt(pos);
mPurgeArray->RemoveElementAt(pos);
delete purgeEntry;
}
//Should probably reset purge time if this was the server that gets purged next.
return NS_OK;
}
NS_IMETHODIMP nsMsgPurgeService::OnServerLoaded(nsIMsgIncomingServer *server)
{
NS_ENSURE_ARG_POINTER(server);
return AddServer(server);
}
NS_IMETHODIMP nsMsgPurgeService::OnServerUnloaded(nsIMsgIncomingServer *server)
{
NS_ENSURE_ARG_POINTER(server);
return RemoveServer(server);
}
NS_IMETHODIMP nsMsgPurgeService::OnServerChanged(nsIMsgIncomingServer *server)
{
// nothing required. If the hostname or username changed
// the next time purge fires, we'll ping the right server
return NS_OK;
}
PRInt32 nsMsgPurgeService::FindServer(nsIMsgIncomingServer *server)
{
PRInt32 count = mPurgeArray->Count();
for(PRInt32 i = 0; i < count; i++)
{
nsPurgeEntry *purgeEntry = (nsPurgeEntry*)mPurgeArray->ElementAt(i);
if(server == purgeEntry->server.get())
return i;
}
return -1;
}
nsresult nsMsgPurgeService::AddPurgeEntry(nsPurgeEntry *purgeEntry)
{
PRInt32 i;
PRInt32 count = mPurgeArray->Count();
for(i = 0; i < count; i++)
{
nsPurgeEntry *current = (nsPurgeEntry*)mPurgeArray->ElementAt(i);
if(purgeEntry->nextPurgeTime < current->nextPurgeTime)
break;
}
mPurgeArray->InsertElementAt(purgeEntry, i);
return NS_OK;
}
nsresult nsMsgPurgeService::SetNextPurgeTime(nsPurgeEntry *purgeEntry, nsTime startTime)
{
nsIMsgIncomingServer *server = purgeEntry->server;
if(!server)
return NS_ERROR_FAILURE;
purgeEntry->nextPurgeTime = startTime;
purgeEntry->nextPurgeTime += MIN_DELAY_BETWEEN_PURGES * (mPurgeArray->Count()+1); //let us stagger them out by 5 mins if they happen to start at same time
return NS_OK;
}
nsresult nsMsgPurgeService::SetupNextPurge()
{
if(mPurgeArray->Count() > 0)
{
//Get the next purge entry
nsPurgeEntry *purgeEntry = (nsPurgeEntry*)mPurgeArray->ElementAt(0);
nsTime currentTime;
nsInt64 purgeDelay;
nsInt64 ms(1000);
if(currentTime > purgeEntry->nextPurgeTime)
purgeDelay = MIN_DELAY_BETWEEN_PURGES;
else
purgeDelay = purgeEntry->nextPurgeTime - currentTime;
//Convert purgeDelay into milliseconds
nsInt64 timeInMS = purgeDelay / ms;
PRUint32 timeInMSUint32 = (PRUint32)timeInMS;
//Can't currently reset a timer when it's in the process of
//calling Notify. So, just release the timer here and create a new one.
if(mPurgeTimer)
{
mPurgeTimer->Cancel();
}
mPurgeTimer = do_CreateInstance("@mozilla.org/timer;1");
mPurgeTimer->InitWithFuncCallback(OnPurgeTimer, (void*)this, timeInMSUint32,
nsITimer::TYPE_ONE_SHOT);
}
return NS_OK;
}
//This is the function that does a purge on all of the servers whose time it is to purge.
nsresult nsMsgPurgeService::PerformPurge()
{
nsTime currentTime;
for(PRInt32 i = 0;i < mPurgeArray->Count(); i++)
{
nsPurgeEntry *current = (nsPurgeEntry*)mPurgeArray->ElementAt(i);
if(current->nextPurgeTime < currentTime)
{
PRBool serverBusy = PR_FALSE;
PRBool serverRequiresPassword = PR_TRUE;
nsXPIDLCString password;
// we don't want to prompt the user for password UI so pass in false to
// the server->GetPassword method. If we don't already know the passsword then
// we just won't purge this server
current->server->GetPassword(getter_Copies(password));
current->server->GetServerBusy(&serverBusy);
//Make sure we're logged on before doing a purge
// and make sure the server isn't already in the middle of downloading new messages
nsTime nextPurgeTime;
if(!mSearchSession && !serverBusy && !password.IsEmpty())
{
nsresult rv = PurgeJunkFolder(current);
if (NS_SUCCEEDED(rv))
nextPurgeTime += ONE_DAY_IN_MILLISECONDS;
else
current = nsnull;
}
mPurgeArray->RemoveElementAt(i);
i--; //Because we removed it we need to look at the one that just moved up.
if (current)
{
SetNextPurgeTime(current, nextPurgeTime);
AddPurgeEntry(current);
}
}
else
//since we're in purge order, there's no reason to keep checking
break;
}
SetupNextPurge();
return NS_OK;
}
nsresult nsMsgPurgeService::PurgeJunkFolder(nsPurgeEntry *entry)
{
nsCOMPtr <nsISpamSettings> spamSettings;
nsresult rv = entry->server->GetSpamSettings(getter_AddRefs(spamSettings));
if (spamSettings)
{
PRBool purgeSpam;
spamSettings->GetPurge(&purgeSpam);
//I didn't want to add another error code; if settings changed from underneath us simply abort - return failure
if (!purgeSpam)
return NS_ERROR_FAILURE;
nsXPIDLCString junkFolderURI;
spamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI));
if (junkFolderURI.IsEmpty()) //fatal error - return failure;
return NS_ERROR_FAILURE;
if (!entry->folderURI.Equals(junkFolderURI.get())) //junkfolder changed, return NS_OK, will purge after a day
{
entry->folderURI.Assign(junkFolderURI.get());
return NS_OK;
}
nsCOMPtr<nsIMsgFolder> junkFolder;
GetExistingFolder(junkFolderURI.get(), getter_AddRefs(junkFolder));
if (junkFolder)
{
//multiple servers can point to same junk folder, so check last purge time before issuing a purge
//we don't want to remove the entry because junk folder can change for the server
nsXPIDLCString lastPurgeTimeString;
junkFolder->GetStringProperty("lastPurgeTime", getter_Copies(lastPurgeTimeString));
if (!lastPurgeTimeString.IsEmpty())
{
PRInt64 theTime;
PR_ParseTimeString(lastPurgeTimeString.get(), PR_FALSE, &theTime);
nsTime lastPurgeTime(theTime);
lastPurgeTime += ONE_DAY_IN_MILLISECONDS;
nsTime currentTime;
if (lastPurgeTime > currentTime)
return NS_OK; //return NS_OK will purge after a day
}
PRInt32 purgeInterval;
spamSettings->GetPurgeInterval(&purgeInterval);
return SearchFolderToPurge(junkFolder, purgeInterval);
}
else
{
//we couldn't find the junk folder to purge so return failure so that entry gets removed
return NS_MSG_ERROR_FOLDER_MISSING;
}
}
return rv;
}
nsresult nsMsgPurgeService::SearchFolderToPurge(nsIMsgFolder *folder, PRInt32 purgeInterval)
{
nsresult rv;
mSearchSession = do_CreateInstance(NS_MSGSEARCHSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mSearchSession->RegisterListener(this);
nsCOMPtr<nsIMsgIncomingServer> server;
rv = folder->GetServer(getter_AddRefs(server)); //we need to get the folder's server scope because imap can have local junk folder
NS_ENSURE_SUCCESS(rv, rv);
nsMsgSearchScopeValue searchScope;
server->GetSearchScope(&searchScope);
mSearchSession->AddScopeTerm(searchScope, folder);
nsCOMPtr <nsIMsgSearchTerm> searchTerm;
mSearchSession->CreateTerm(getter_AddRefs(searchTerm));
if (searchTerm)
{
searchTerm->SetAttrib(nsMsgSearchAttrib::AgeInDays);
searchTerm->SetOp(nsMsgSearchOp::IsGreaterThan);
nsCOMPtr<nsIMsgSearchValue> searchValue;
searchTerm->GetValue(getter_AddRefs(searchValue));
if (searchValue)
{
searchValue->SetAttrib(nsMsgSearchAttrib::AgeInDays);
searchValue->SetAge((PRUint32) purgeInterval);
searchTerm->SetValue(searchValue);
}
searchTerm->SetBooleanAnd(PR_FALSE);
mSearchSession->AppendTerm(searchTerm);
}
if (!mHdrsToDelete) //we are about to search, let us create mHdrsToDelete array
{
mHdrsToDelete = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
mSearchFolder = folder;
return mSearchSession->Search(nsnull);
}
NS_IMETHODIMP nsMsgPurgeService::OnNewSearch()
{
return NS_OK;
}
NS_IMETHODIMP nsMsgPurgeService::OnSearchHit(nsIMsgDBHdr* msgHdr, nsIMsgFolder *folder)
{
return mHdrsToDelete->AppendElement(msgHdr);
}
NS_IMETHODIMP nsMsgPurgeService::OnSearchDone(nsresult status)
{
nsresult rv = NS_OK;
if (NS_SUCCEEDED(status))
{
PRUint32 count;
mHdrsToDelete->Count(&count);
if (count > 0)
rv = mSearchFolder->DeleteMessages(mHdrsToDelete, nsnull, PR_FALSE /*delete storage*/, PR_FALSE /*isMove*/, nsnull, PR_FALSE /*allowUndo*/);
if (NS_SUCCEEDED(rv))
{
char dateBuf[100];
dateBuf[0] = '\0';
PRExplodedTime exploded;
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &exploded);
PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%a %b %d %H:%M:%S %Y", &exploded);
mSearchFolder->SetStringProperty("lastPurgeTime", dateBuf);
}
}
mHdrsToDelete->Clear();
mSearchSession->UnregisterListener(this);
mSearchSession = nsnull; //let us create another search session next time we search, rather than clearing scopes, terms etc.
mSearchFolder = nsnull;
return NS_OK;
}

View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Navin Gupta <naving@netscape.com> (Original Author)
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSMSGPURGESERVICE_H
#define NSMSGPURGESERVICE_H
#include "msgCore.h"
#include "nsIMsgPurgeService.h"
#include "nsIMsgSearchSession.h"
#include "nsITimer.h"
#include "nsVoidArray.h"
#include "nsTime.h"
#include "nsCOMPtr.h"
#include "nsIIncomingServerListener.h"
#include "nsIMsgSearchNotify.h"
#include "nsIMsgFolder.h"
#include "nsIMsgFolderCache.h"
#include "nsIMsgFolderCacheElement.h"
typedef struct {
nsCOMPtr<nsIMsgIncomingServer> server;
nsCAutoString folderURI;
nsTime nextPurgeTime;
} nsPurgeEntry;
class nsMsgPurgeService
: public nsIMsgPurgeService,
public nsIIncomingServerListener,
public nsIMsgSearchNotify
{
public:
nsMsgPurgeService();
virtual ~nsMsgPurgeService();
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGPURGESERVICE
NS_DECL_NSIINCOMINGSERVERLISTENER
NS_DECL_NSIMSGSEARCHNOTIFY
nsresult PerformPurge();
protected:
nsresult AddServer(nsIMsgIncomingServer *server);
nsresult RemoveServer(nsIMsgIncomingServer *server);
PRInt32 FindServer(nsIMsgIncomingServer *server);
nsresult PurgeJunkFolder(nsPurgeEntry *entry);
nsresult SetNextPurgeTime(nsPurgeEntry *purgeEntry, nsTime startTime);
nsresult SetupNextPurge();
nsresult AddPurgeEntry(nsPurgeEntry *purgeEntry);
nsresult PurgeSurver(nsIMsgIncomingServer *server);
nsresult SearchFolderToPurge(nsIMsgFolder *folder, PRInt32 purgeInterval);
protected:
nsCOMPtr<nsITimer> mPurgeTimer;
nsCOMPtr<nsIMsgSearchSession> mSearchSession;
nsCOMPtr<nsIMsgFolder> mSearchFolder;
nsCOMPtr<nsISupportsArray> mHdrsToDelete;
nsVoidArray *mPurgeArray;
PRBool mHaveShutdown;
};
#endif

View File

@ -1620,3 +1620,58 @@ nsMsgDBFolder::SetDBTransferInfo(nsIDBFolderInfo *aTransferInfo)
}
return NS_OK;
}
NS_IMETHODIMP
nsMsgDBFolder::GetStringProperty(const char *propertyName, char **propertyValue)
{
NS_ENSURE_ARG_POINTER(propertyName);
NS_ENSURE_ARG_POINTER(propertyValue);
nsCOMPtr <nsIFileSpec> dbPath;
nsresult rv = GetFolderCacheKey(getter_AddRefs(dbPath));
if (dbPath)
{
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
rv = GetFolderCacheElemFromFileSpec(dbPath, getter_AddRefs(cacheElement));
if (cacheElement) //try to get from cache
rv = cacheElement->GetStringProperty(propertyName, propertyValue);
if (NS_FAILED(rv)) //if failed, then try to get from db
{
nsCOMPtr<nsIDBFolderInfo> folderInfo;
nsCOMPtr<nsIMsgDatabase> db;
PRBool exists;
rv = dbPath->Exists(&exists);
if (NS_FAILED(rv) || !exists)
return NS_MSG_ERROR_FOLDER_MISSING;
rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
if (NS_SUCCEEDED(rv))
rv = folderInfo->GetCharPtrProperty(propertyName, propertyValue);
}
}
return rv;
}
NS_IMETHODIMP
nsMsgDBFolder::SetStringProperty(const char *propertyName, const char *propertyValue)
{
NS_ENSURE_ARG_POINTER(propertyName);
NS_ENSURE_ARG_POINTER(propertyValue);
nsCOMPtr <nsIFileSpec> dbPath;
GetFolderCacheKey(getter_AddRefs(dbPath));
if (dbPath)
{
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
GetFolderCacheElemFromFileSpec(dbPath, getter_AddRefs(cacheElement));
if (cacheElement) //try to set in the cache
cacheElement->SetStringProperty(propertyName, propertyValue);
}
nsCOMPtr<nsIDBFolderInfo> folderInfo;
nsCOMPtr<nsIMsgDatabase> db;
nsresult rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
if(NS_SUCCEEDED(rv))
{
folderInfo->SetCharPtrProperty(propertyName, propertyValue);
db->Commit(nsMsgDBCommitType::kLargeCommit); //commiting the db also commits the cache
}
return NS_OK;
}

View File

@ -119,6 +119,9 @@ public:
NS_IMETHOD MatchOrChangeFilterDestination(nsIMsgFolder *oldFolder, PRBool caseInsensitive, PRBool *changed);
NS_IMETHOD GetDBTransferInfo(nsIDBFolderInfo **aTransferInfo);
NS_IMETHOD SetDBTransferInfo(nsIDBFolderInfo *aTransferInfo);
NS_IMETHOD GetStringProperty(const char *propertyName, char **propertyValue);
NS_IMETHOD SetStringProperty(const char *propertyName, const char *propertyValue);
protected:
virtual nsresult ReadDBFolderInfo(PRBool force);

View File

@ -1816,6 +1816,13 @@ nsMsgIncomingServer::SetSpamSettings(nsISpamSettings *aSpamSettings)
NS_ENSURE_SUCCESS(rv,rv);
}
nsXPIDLCString junkFolderURI;
mSpamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI));
nsCOMPtr<nsIMsgFolder> junkFolder;
rv = GetExistingFolder(junkFolderURI.get(), getter_AddRefs(junkFolder));
if (NS_SUCCEEDED(rv) && junkFolder) //remove the MSG_FOLDER_FLAG_JUNK on old junk folder
junkFolder->SetFlag(~MSG_FOLDER_FLAG_JUNK);
rv = mSpamSettings->Clone(aSpamSettings);
NS_ENSURE_SUCCESS(rv,rv);
@ -1849,6 +1856,13 @@ nsMsgIncomingServer::SetSpamSettings(nsISpamSettings *aSpamSettings)
NS_ENSURE_SUCCESS(rv,rv);
rv = SetCharValue("spamActionTargetFolder", spamActionTargetFolder.get());
NS_ENSURE_SUCCESS(rv,rv);
junkFolder = nsnull;
junkFolderURI.Assign("");
mSpamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI));
rv = GetExistingFolder(junkFolderURI.get(), getter_AddRefs(junkFolder));
if (NS_SUCCEEDED(rv) && junkFolder) //set MSG_FOLDER_FLAG_JUNK on new junk folder
junkFolder->SetFlag(MSG_FOLDER_FLAG_JUNK);
PRBool useWhiteList;
rv = mSpamSettings->GetUseWhiteList(&useWhiteList);

View File

@ -61,6 +61,8 @@
#include "nsMsgMimeCID.h"
#include "nsICategoryManager.h"
#include "nsCategoryManagerUtils.h"
#include "nsISpamSettings.h"
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
static NS_DEFINE_CID(kCMailboxUrl, NS_MAILBOXURL_CID);
@ -533,27 +535,26 @@ PRBool WeAreOffline()
return offline;
}
PRBool IsValidFolderURI(const char *aFolderURI)
nsresult GetExistingFolder(const char *aFolderURI, nsIMsgFolder **aFolder)
{
nsresult rv;
nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
if (NS_FAILED(rv))
return PR_FALSE;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(aFolderURI, getter_AddRefs(resource));
if (NS_FAILED(rv))
return PR_FALSE;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgFolder> thisFolder;
thisFolder = do_QueryInterface(resource, &rv);
if (NS_FAILED(rv) || !thisFolder)
return PR_FALSE;
NS_ENSURE_SUCCESS(rv, rv);
// Parent doesn't exist means that this folder doesn't exist.
nsCOMPtr<nsIFolder> parentFolder;
rv = thisFolder->GetParent(getter_AddRefs(parentFolder));
return (NS_SUCCEEDED(rv) && parentFolder);
if (NS_SUCCEEDED(rv) && parentFolder)
NS_ADDREF(*aFolder = thisFolder);
return rv;
}
PRBool IsAFromSpaceLine(char *start, const char *end)
@ -620,7 +621,7 @@ nsresult CreateServicesForPasswordManager()
}
return NS_OK;
}
nsresult IsRFC822HeaderFieldName(const char *aHdr, PRBool *aResult)
{
NS_ENSURE_ARG_POINTER(aHdr);

View File

@ -76,8 +76,8 @@ NS_MSG_BASE nsresult NS_MsgDecodeUnescapeURLPath(const char *path, PRUnichar **r
NS_MSG_BASE PRBool WeAreOffline();
// Check if a given folder uri is valid and exists
NS_MSG_BASE PRBool IsValidFolderURI(const char *aFolderURI);
// Check if a folder with aFolderUri exists
NS_MSG_BASE nsresult GetExistingFolder(const char *aFolderURI, nsIMsgFolder **aFolder);
// Escape lines starting with "From ", ">From ", etc. in a buffer.
NS_MSG_BASE nsresult EscapeFromSpaceLine(nsIFileSpec *pDst, char *start, const char *end);