changes for mail filters, including setting root folder for server

This commit is contained in:
bienvenu%netscape.com 1999-05-26 23:56:21 +00:00
parent 6c150bc6c8
commit 729931951f
11 changed files with 173 additions and 78 deletions

View File

@ -381,6 +381,12 @@ nsMsgAccountManagerDataSource::createServerResources(nsISupports *element,
rv = rdf->GetResource(serverUri, getter_AddRefs(serverResource));
if (NS_FAILED(rv)) return PR_TRUE;
// make incoming server know about its root server folder so we
// can find sub-folders given an incoming server.
nsCOMPtr <nsIFolder> serverFolder = do_QueryInterface(serverResource);
if (serverFolder)
server->SetRootFolder(serverFolder);
// add the resource to the array
rv = servers->AppendElement(serverResource);
if (NS_FAILED(rv)) return PR_TRUE;

View File

@ -164,6 +164,12 @@ nsMsgFolder::GetSubFolders(nsIEnumerator* *result)
return mSubFolders->Enumerate(result);
}
NS_IMETHODIMP
nsMsgFolder::FindSubFolder(const char *subFolderName, nsIFolder **folder)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMsgFolder::GetHasSubFolders(PRBool *_retval)
{

View File

@ -80,6 +80,7 @@ public:
NS_IMETHOD RemoveFolderListener(nsIFolderListener * listener);
NS_IMETHOD GetParent(nsIFolder * *aParent);
NS_IMETHOD SetParent(nsIFolder * aParent);
NS_IMETHOD FindSubFolder(const char *subFolderName, nsIFolder **folder);
// nsIMsgFolder methods:

View File

@ -64,6 +64,22 @@ nsMsgIncomingServer::SetKey(char * serverKey)
return rv;
}
NS_IMETHODIMP
nsMsgIncomingServer::SetRootFolder(nsIFolder * aRootFolder)
{
m_rootFolder = aRootFolder;
return NS_OK;
}
NS_IMETHODIMP
nsMsgIncomingServer::GetRootFolder(nsIFolder * *aRootFolder)
{
if (!aRootFolder)
return NS_ERROR_NULL_POINTER;
*aRootFolder = m_rootFolder;
NS_ADDREF(*aRootFolder);
return NS_OK;
}
char *
nsMsgIncomingServer::getPrefName(const char *serverKey,

View File

@ -19,7 +19,8 @@
#include "nsIMsgIncomingServer.h"
#include "nsIPref.h"
#include "msgCore.h"
#include "nsIFolder.h"
#include "nsCOMPtr.h"
/*
* base class for nsIMsgIncomingServer - derive your class from here
* if you want to get some free implementation
@ -71,6 +72,10 @@ class NS_MSG_BASE nsMsgIncomingServer : public nsIMsgIncomingServer {
NS_IMETHOD GetLocalPath(char * *aLocalPath);
NS_IMETHOD SetLocalPath(char * aLocalPath);
NS_IMETHOD GetRootFolder(nsIFolder * *aRootFolder);
NS_IMETHOD SetRootFolder(nsIFolder * aRootFolder);
private:
nsIPref *m_prefs;
@ -80,6 +85,7 @@ protected:
char *getPrefName(const char *serverKey, const char *pref);
char *getDefaultPrefName(const char *pref);
nsCOMPtr <nsIFolder> m_rootFolder;
nsresult getCharPref(const char *pref, char **);
nsresult getDefaultCharPref(const char *pref, char **);
nsresult setCharPref(const char *pref, char *);

View File

@ -43,9 +43,9 @@
#include "nsIPop3IncomingServer.h"
#include "nsIPop3Service.h"
#include "nsIMsgIncomingServer.h"
#include "nsString2.h"
#include "nsLocalFolderSummarySpec.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kMailboxServiceCID, NS_MAILBOXSERVICE_CID);
@ -1007,6 +1007,41 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetPath(nsFileSpec& aPathName)
return NS_OK;
}
// OK, this is kind of silly, but for now, we'll just tack the subFolderName
// onto our URI, and ask RDF to find it for us.
NS_IMETHODIMP
nsMsgLocalMailFolder::FindSubFolder(const char *subFolderName, nsIFolder **aFolder)
{
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
if(NS_FAILED(rv))
return rv;
nsString2 uri(eOneByte);
uri.Append(mURI);
uri.Append('/');
uri.Append(subFolderName);
nsCOMPtr<nsIRDFResource> res;
rv = rdf->GetResource(uri.GetBuffer(), getter_AddRefs(res));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFolder> folder(do_QueryInterface(res, &rv));
if (NS_FAILED(rv))
return rv;
if (aFolder)
{
*aFolder = folder;
NS_ADDREF(*aFolder);
return NS_OK;
}
else
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsMsgLocalMailFolder::DeleteMessages(nsISupportsArray *messages)
{
nsresult rv = GetDatabase();

View File

@ -107,6 +107,7 @@ public:
NS_IMETHOD CopyData(nsIInputStream *aIStream, PRInt32 aLength);
NS_IMETHOD EndCopy(PRBool copySucceeded);
NS_IMETHOD FindSubFolder(const char *subFolderName, nsIFolder **folder);
protected:
nsresult ParseFolder(nsFileSpec& path);

View File

@ -1286,15 +1286,18 @@ nsParseNewMailState::nsParseNewMailState()
, m_logFile(nsnull)
#endif
{
m_inboxFileStream = nsnull;
}
nsresult
nsParseNewMailState::Init(nsFileSpec &folder)
nsParseNewMailState::Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream)
{
nsresult rv;
m_mailboxName = nsCRT::strdup(folder);
m_position = folder.GetFileSize();
m_rootFolder = rootFolder;
m_inboxFileStream = inboxFileStream;
// the new mail parser isn't going to get the stream input, it seems, so we can't use
// the OnStartBinding mechanism the mailbox parser uses. So, let's open the db right now.
nsCOMPtr<nsIMsgDatabase> mailDB;
@ -1520,7 +1523,6 @@ void nsParseNewMailState::ApplyFilters(PRBool *pMoved)
else if (filterType == nsMsgFilterInboxRule)
{
nsresult matchTermStatus = NS_OK;
nsIMsgFilter *filter;
{
#ifdef HAVE_PORT
@ -1654,7 +1656,7 @@ void nsParseNewMailState::ApplyFilters(PRBool *pMoved)
msgHdr->OrFlags(MSG_FLAG_WATCHED, &newFlags);
break;
case nsMsgFilterActionChangePriority:
msgHdr->SetPriority(*(nsMsgPriority *) &value));
msgHdr->SetPriority(*(nsMsgPriority *) &value);
break;
default:
break;
@ -1683,76 +1685,70 @@ int nsParseNewMailState::MarkFilteredMessageRead(nsIMsgDBHdr *msgHdr)
return 0;
}
int nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter)
{
int err = 0;
XP_File destFid;
XP_File sourceFid = m_file;
nsIOFileStream *destFile;
// Make sure no one else is writing into this folder
nsIMsgFolder *lockedFolder = m_mailMaster->FindMailFolder (destFolder, FALSE /*create*/);
nsCOMPtr <nsIFolder> destIFolder;
nsCOMPtr <nsIMsgFolder> lockedFolder;
m_rootFolder->FindSubFolder (destFolder, getter_AddRefs(destIFolder));
lockedFolder = do_QueryInterface(destIFolder);
if (lockedFolder && (err = lockedFolder->AcquireSemaphore (this)) != 0)
return err;
if (sourceFid == 0)
{
sourceFid = XP_FileOpen(m_mailboxName,
xpMailFolder, XP_FILE_READ_BIN);
}
XP_ASSERT(sourceFid != 0);
if (sourceFid == 0)
NS_ASSERTION(m_inboxFileStream != 0, "no input file stream");
if (m_inboxFileStream == 0)
{
#ifdef DEBUG_bienvenu
XP_ASSERT(FALSE);
NS_ASSERTION(PR_FALSE, "couldn't get source file in move filter");
#endif
if (lockedFolder)
lockedFolder->ReleaseSemaphore (this);
return MK_MSG_FOLDER_UNREADABLE; // ### dmb
return NS_MSG_FOLDER_UNREADABLE; // ### dmb
}
PRUint32 messageOffset;
mailHdr->GetMessageOffset(&messageOffset);
XP_FileSeek (sourceFid, messageOffset, SEEK_SET);
m_inboxFileStream->seek(PR_SEEK_SET, messageOffset);
int newMsgPos;
destFid = XP_FileOpen(destFolder, xpMailFolder, XP_FILE_APPEND_BIN);
nsFileSpec destDBSpec(destFolder);
destFile = new nsIOFileStream(destDBSpec, PR_WRONLY | PR_CREATE_FILE);
if (!destFid)
if (!destFile)
{
#ifdef DEBUG_bienvenu
XP_ASSERT(FALSE);
NS_ASSERTION(PR_FALSE, "out of memory");
#endif
if (lockedFolder)
lockedFolder->ReleaseSemaphore (this);
XP_FileClose (sourceFid);
return MK_MSG_ERROR_WRITING_MAIL_FOLDER;
return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
}
if (!XP_FileSeek (destFid, 0, SEEK_END))
{
newMsgPos = ftell (destFid);
}
else
{
XP_ASSERT(FALSE);
if (lockedFolder)
lockedFolder->ReleaseSemaphore (this);
XP_FileClose (destFid);
XP_FileClose (sourceFid);
return MK_MSG_ERROR_WRITING_MAIL_FOLDER;
}
destFile->seek(PR_SEEK_END, 0);
newMsgPos = destFile->tell();
nsCOMPtr <nsIMsgDatabase> mailDb = nsnull;
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
nsCOMPtr<nsIMsgDatabase> destMailDB;
nsresult rv = nsComponentManager::CreateInstance(kCMailDB, nsnull, nsIMsgDatabase::GetIID(), (void **) getter_AddRefs(mailDBFactory));
if (NS_SUCCEEDED(rv) && mailDBFactory)
{
nsFileSpec destDBSpec(destFolder);
rv = mailDBFactory->Open(destDBSpec, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(destMailDB), PR_TRUE);
}
NS_ASSERTION(destMailDB, "failed to open mail db parsing folder");
// don't force upgrade in place - open the db here before we start writing to the
// destination file because XP_Stat can return file size including bytes written...
nsresult msgErr = nsMailDatabase::Open (destFolder, TRUE, &mailDb);
PRUint32 length;
mailHdr->SetMessageSize(&length);
mailHdr->GetMessageSize(&length);
m_ibuffer_size = 10240;
m_ibuffer = nsnull;
@ -1766,26 +1762,26 @@ int nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
NS_ASSERTION(m_ibuffer != nsnull, "couldn't get memory to move msg");
while ((length > 0) && m_ibuffer)
{
PRUint32 nRead = XP_FileRead (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size : length, sourceFid);
PRUint32 nRead = m_inboxFileStream->read (m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size : length);
if (nRead == 0)
break;
// we must monitor the number of bytes actually written to the file. (mscott)
if (XP_FileWrite (m_ibuffer, nRead, destFid) != nRead)
if (destFile->write(m_ibuffer, nRead) != nRead)
{
XP_FileClose(sourceFid);
XP_FileClose(destFid);
destFile->close();
// truncate destination file in case message was partially written
XP_FileTruncate(destFolder,xpMailFolder,newMsgPos);
// ### how to do this with a stream?
// destFile->truncate(destFolder,xpMailFolder,newMsgPos);
if (lockedFolder)
lockedFolder->ReleaseSemaphore(this);
if (mailDb)
mailDb->Close(PR_TRUE);
if (destMailDB)
destMailDB->Close(PR_TRUE);
return MK_MSG_ERROR_WRITING_MAIL_FOLDER; // caller (ApplyFilters) currently ignores error conditions
return NS_MSG_ERROR_WRITING_MAIL_FOLDER; // caller (ApplyFilters) currently ignores error conditions
}
length -= nRead;
@ -1794,12 +1790,12 @@ int nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
NS_ASSERTION(length == 0, "didn't read all of original message in filter move");
// if we have made it this far then the message has successfully been written to the new folder
// now add the header to the mailDb.
if (NS_SUCCEEDED(msgErr))
// now add the header to the destMailDB.
if (NS_SUCCEEDED(rv))
{
nsIMsgDBHdr *newHdr = nsnull;
msgErr = mailDB->CopyHdrFromExistingHdr(newMsgPos, mailHdr, &newHdr);
nsresult msgErr = destMailDB->CopyHdrFromExistingHdr(newMsgPos, mailHdr, &newHdr);
if (NS_SUCCEEDED(msgErr) && newHdr)
{
PRUint32 newFlags;
@ -1807,41 +1803,41 @@ int nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
newHdr->SetMessageKey (newMsgPos);
newHdr->OrFlags(MSG_FLAG_NEW, &newFlags);
msgErr = mailDb->AddNewHdrToDB (newHdr, m_updateAsWeGo);
msgErr = destMailDB->AddNewHdrToDB (newHdr, m_updateAsWeGo);
}
}
else
{
if (mailDb)
if (destMailDB)
{
mailDb->Close(PR_TRUE);
mailDb = nsnull;
destMailDB->Close(PR_TRUE);
destMailDB = nsnull;
}
}
XP_FileClose(sourceFid);
XP_FileClose(destFid);
int truncRet = XP_FileTruncate(m_mailboxName, xpMailFolder, mailHdr->GetMessageOffset());
XP_ASSERT(truncRet >= 0);
destFile->close();
// How are we going to do this with a stream?
// int truncRet = XP_FileTruncate(m_mailboxName, xpMailFolder, messageOffset);
// NS_ASSERTION(truncRet >= 0, "unable to truncate file");
if (lockedFolder)
lockedFolder->ReleaseSemaphore (this);
// tell outgoing parser that we've truncated the Inbox
m_parseMsgState->Init(mailHdr->GetMessageOffset());
nsIMsgFolder *folder = m_mailMaster->FindMailFolder(destFolder, FALSE);
// tell parser that we've truncated the Inbox
mailHdr->GetMessageOffset(&messageOffset);
nsParseMailMessageState::Init(messageOffset);
if (folder)
folder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
if (lockedFolder)
lockedFolder->SetFlag(MSG_FOLDER_FLAG_GOT_NEW);
if (mailDb != nsnull)
if (destMailDB != nsnull)
{
// update the folder size so we won't reparse.
UpdateDBFolderInfo(mailDb, destFolder);
if (folder != nsnull)
folder->SummaryChanged();
UpdateDBFolderInfo(destMailDB, destFolder);
if (lockedFolder != nsnull)
lockedFolder->SummaryChanged();
mailDb->Close(PR_TRUE);
destMailDB->Close(PR_TRUE);
}
// We are logging the hit with the old mailHdr, which should work, as long
// as LogRuleHit doesn't assume the new hdr.
@ -1930,12 +1926,12 @@ int ParseIMAPMailboxState::MarkFilteredMessageRead(nsIMsgDBHdr *msgHdr)
}
int ParseIMAPMailboxState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsresult ParseIMAPMailboxState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter)
{
int err = eUNKNOWN;
nsresult err = NS_OK;
if (fUrlQueue && fUrlQueue->GetPane())
{

View File

@ -31,16 +31,18 @@
#ifdef DEBUG_bienvenu
//#define DOING_FILTERS
#define DOING_FILTERS
#endif
class nsFileSpec;
class nsByteArray;
class nsOutputFileStream;
class nsIOFileStream;
class nsInputFileStream;
class nsIMsgFilter;
class MSG_FolderInfoMail;
class nsIMsgFilterList;
class nsIFolder;
/* Used for the various things that parse RFC822 headers...
@ -232,7 +234,7 @@ public:
nsParseNewMailState();
virtual ~nsParseNewMailState();
nsresult Init(nsFileSpec &folder);
nsresult Init(nsIFolder *rootFolder, nsFileSpec &folder, nsIOFileStream *inboxFileStream);
virtual void DoneParsingFolder();
virtual void SetUsingTempDB(PRBool usingTempDB, char *tmpDBName);
@ -256,14 +258,16 @@ protected:
#ifdef DOING_FILTERS
virtual void ApplyFilters(PRBool *pMoved);
virtual nsIMsgFolder *GetTrashFolder();
virtual int MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
virtual nsresult MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter);
virtual int MarkFilteredMessageRead(nsIMsgDBHdr *msgHdr);
void LogRuleHit(nsIMsgFilter *filter, nsIMsgDBHdr *msgHdr);
nsCOMPtr <nsIMsgFilterList> m_filterList;
nsCOMPtr <nsIFolder> m_rootFolder;
nsOutputFileStream *m_logFile;
nsIOFileStream *m_inboxFileStream;
#endif // DOING_FILTERS
char *m_tmpdbName; // Temporary filename of new database
PRBool m_usingTempDB;
@ -294,7 +298,7 @@ protected:
virtual void ApplyFilters(PRBool *pMoved);
virtual MSG_FolderInfoMail *GetTrashFolder();
virtual int MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
virtual nsresult MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
char *destFolder,
nsIMsgFilter *filter);

View File

@ -24,6 +24,8 @@
#include <stdio.h>
#include <time.h>
#include "nsParseMailbox.h"
#include "nsIFolder.h"
#include "nsIMsgIncomingServer.h"
NS_IMPL_ISUPPORTS(nsPop3Sink, nsIPop3Sink::GetIID());
@ -112,7 +114,7 @@ nsPop3Sink::BeginMailDelivery(PRBool* aBool)
nsFileSpec fileSpec(m_mailDirectory);
fileSpec += "Inbox";
m_outFileStream = new nsOutputFileStream(fileSpec,
m_outFileStream = new nsIOFileStream(fileSpec,
PR_WRONLY | PR_CREATE_FILE);
if (m_outFileStream)
m_outFileStream->seek(fileSpec.GetFileSize());
@ -122,7 +124,11 @@ nsPop3Sink::BeginMailDelivery(PRBool* aBool)
m_newMailParser = new nsParseNewMailState;
if (m_newMailParser == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = m_newMailParser->Init(fileSpec);
nsCOMPtr <nsIFolder> serverFolder;
nsresult res = GetServerFolder(getter_AddRefs(serverFolder));
nsresult rv = m_newMailParser->Init(serverFolder, fileSpec, m_outFileStream);
if (NS_FAILED(rv)) return rv;
#ifdef DEBUG
@ -214,6 +220,21 @@ nsPop3Sink::GetPopServer(nsIPop3IncomingServer* *server)
return NS_OK;
}
nsresult
nsPop3Sink::GetServerFolder(nsIFolder **aFolder)
{
if (!aFolder)
return NS_ERROR_NULL_POINTER;
if (m_popServer)
{
nsCOMPtr <nsIMsgIncomingServer> incomingServer = do_QueryInterface(m_popServer);
if (incomingServer)
return incomingServer->GetRootFolder(aFolder);
}
*aFolder = nsnull;
return NS_ERROR_NULL_POINTER;
}
char*
nsPop3Sink::GetDummyEnvelope(void)
{

View File

@ -29,6 +29,7 @@
#include "prenv.h"
class nsParseNewMailState;
class nsIFolder;
class nsPop3Sink : public nsIPop3Sink
{
@ -55,6 +56,8 @@ public:
NS_IMETHOD SetPopServer(nsIPop3IncomingServer *server);
NS_IMETHOD GetPopServer(nsIPop3IncomingServer* *server);
nsresult GetServerFolder(nsIFolder **aFolder);
static char* GetDummyEnvelope(void);
protected:
@ -73,7 +76,7 @@ protected:
#ifdef DEBUG
PRInt32 m_fileCounter;
#endif
nsOutputFileStream* m_outFileStream;
nsIOFileStream* m_outFileStream;
};
#endif