(not part of the build yet) - more works on hooking up 3-pane ui with protocol

This commit is contained in:
jefft%netscape.com 1999-04-22 19:02:45 +00:00
parent 8f1a286301
commit 119aa05555
4 changed files with 925 additions and 52 deletions

View File

@ -27,50 +27,80 @@
#include "nsFileStream.h"
#include "nsMsgDBCID.h"
#include "nsMsgFolderFlags.h"
#include "nsLocalFolderSummarySpec.h"
#include "nsImapFlagAndUidState.h"
#include "nsParseMailbox.h"
#include "nsIEventQueueService.h"
#include "nsXPComCIID.h"
#include "nsIImapUrl.h"
// we need this because of an egcs 1.0 (and possibly gcc) compiler bug
// that doesn't allow you to call ::nsISupports::GetIID() inside of a class
// that multiply inherits from nsISupports
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kCMailDB, NS_MAILDB_CID);
static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID);
static NS_DEFINE_CID(kCImapDB, NS_IMAPDB_CID);
static NS_DEFINE_CID(kCImapService, NS_IMAPSERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
////////////////////////////////////////////////////////////////////////////////
nsImapMailFolder::nsImapMailFolder() :
nsMsgFolder(), mPathName(""), mMailDatabase(nsnull),
mInitialized(PR_FALSE), mHaveReadNameFromDB(PR_FALSE)
nsMsgFolder(), m_pathName(""), m_mailDatabase(nsnull),
m_initialized(PR_FALSE), m_haveReadNameFromDB(PR_FALSE)
{
//XXXX This is a hack for the moment. I'm assuming the only listener is our rdf:mailnews datasource.
//In reality anyone should be able to listen to folder changes.
//XXXX This is a hack for the moment. I'm assuming the only listener is
//our rdf:mailnews datasource.
//In reality anyone should be able to listen to folder changes.
nsIRDFService* rdfService = nsnull;
nsIRDFDataSource* datasource = nsnull;
nsresult rv = nsServiceManager::GetService(kRDFServiceCID,
nsIRDFService::GetIID(),
(nsISupports**) &rdfService);
if(NS_SUCCEEDED(rv))
{
rv = rdfService->GetDataSource("rdf:mailnewsfolders", &datasource);
if(NS_SUCCEEDED(rv))
{
nsIFolderListener *folderListener;
rv = datasource->QueryInterface(nsIFolderListener::GetIID(),
(void**)&folderListener);
if(NS_SUCCEEDED(rv))
{
AddFolderListener(folderListener);
NS_RELEASE(folderListener);
}
NS_RELEASE(datasource);
}
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
}
nsIRDFService* rdfService = nsnull;
nsIRDFDataSource* datasource = nsnull;
nsresult rv = nsServiceManager::GetService(kRDFServiceCID,
nsIRDFService::GetIID(),
(nsISupports**) &rdfService);
if(NS_SUCCEEDED(rv))
{
if(NS_SUCCEEDED(rv = rdfService->GetDataSource("rdf:mailnewsfolders", &datasource)))
{
nsIFolderListener *folderListener;
if(NS_SUCCEEDED(datasource->QueryInterface(nsIFolderListener::GetIID(), (void**)&folderListener)))
{
AddFolderListener(folderListener);
NS_RELEASE(folderListener);
}
NS_RELEASE(datasource);
}
nsServiceManager::ReleaseService(kRDFServiceCID, rdfService);
}
// Get current thread envent queue
nsIEventQueueService* pEventQService;
m_eventQueue = nsnull;
rv = nsServiceManager::GetService(kEventQueueServiceCID,
nsIEventQueueService::GetIID(),
(nsISupports**)&pEventQService);
if (NS_SUCCEEDED(rv) && pEventQService)
pEventQService->GetThreadEventQueue(PR_GetCurrentThread(),
&m_eventQueue);
if (pEventQService)
nsServiceManager::ReleaseService(kEventQueueServiceCID,
pEventQService);
// NS_INIT_REFCNT(); done by superclass
}
nsImapMailFolder::~nsImapMailFolder()
{
if (mMailDatabase)
mMailDatabase->Close(PR_TRUE);
if (m_mailDatabase)
m_mailDatabase->Close(PR_TRUE);
}
NS_IMPL_ADDREF_INHERITED(nsImapMailFolder, nsMsgFolder)
@ -96,6 +126,18 @@ NS_IMETHODIMP nsImapMailFolder::QueryInterface(REFNSIID aIID, void** aInstancePt
{
*aInstancePtr = NS_STATIC_CAST(nsIImapMailFolderSink*, this);
}
else if (aIID.Equals(nsIImapMessageSink::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST(nsIImapMessageSink*, this);
}
else if (aIID.Equals(nsIImapExtensionSink::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST(nsIImapExtensionSink*, this);
}
else if (aIID.Equals(nsIImapMiscellaneousSink::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST(nsIImapMiscellaneousSink*, this);
}
if(*aInstancePtr)
{
@ -109,12 +151,12 @@ NS_IMETHODIMP nsImapMailFolder::QueryInterface(REFNSIID aIID, void** aInstancePt
NS_IMETHODIMP nsImapMailFolder::GetPathName(nsNativeFileSpec& aPathName)
{
nsFileSpec nopath("");
if (mPathName == nopath)
if (m_pathName == nopath)
{
nsresult rv = nsURI2Path(kMailboxRootURI, mURI, mPathName);
nsresult rv = nsURI2Path(kImapRootURI, mURI, m_pathName);
if (NS_FAILED(rv)) return rv;
}
aPathName = mPathName;
aPathName = m_pathName;
return NS_OK;
}
@ -239,7 +281,7 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
NS_IMETHODIMP nsImapMailFolder::GetSubFolders(nsIEnumerator* *result)
{
if (!mInitialized)
if (!m_initialized)
{
nsresult rv = NS_OK;
nsFileSpec path;
@ -257,13 +299,6 @@ NS_IMETHODIMP nsImapMailFolder::GetSubFolders(nsIEnumerator* *result)
newFlags |= (MSG_FOLDER_FLAG_DIRECTORY | MSG_FOLDER_FLAG_ELIDED);
SetFlag(newFlags);
rv = CreateSubFolders(path);
if (mSubFolders->Count() == 0)
{
nsAutoString inboxString = "Inbox";
nsIMsgFolder *child = nsnull;
AddSubfolder(inboxString, &child);
NS_IF_RELEASE (child);
}
}
else
{
@ -285,7 +320,7 @@ NS_IMETHODIMP nsImapMailFolder::GetSubFolders(nsIEnumerator* *result)
}
if (NS_FAILED(rv)) return rv;
mInitialized = PR_TRUE; // XXX do this on failure too?
m_initialized = PR_TRUE; // XXX do this on failure too?
}
return mSubFolders->Enumerate(result);
}
@ -305,8 +340,29 @@ NS_IMETHODIMP nsImapMailFolder::ReplaceElement(nsISupports* element,
NS_IMETHODIMP nsImapMailFolder::GetMessages(nsIEnumerator* *result)
{
nsresult rv = NS_ERROR_FAILURE;
return rv;
nsresult rv;
if (result)
*result = nsnull;
nsIImapService* imapService = nsnull;
rv = nsServiceManager::GetService(kCImapService, nsIImapService::GetIID(),
(nsISupports **) &imapService);
if (NS_FAILED(rv))
{
if (imapService)
nsServiceManager::ReleaseService(kCImapService, imapService);
return rv;
}
if (imapService && m_eventQueue)
{
rv = imapService->SelectFolder(m_eventQueue, this, this, nsnull);
m_urlRunning = PR_TRUE;
}
if (imapService)
nsServiceManager::ReleaseService(kCImapService, imapService);
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsImapMailFolder::GetThreads(nsIEnumerator** threadEnumerator)
@ -358,12 +414,12 @@ NS_IMETHODIMP nsImapMailFolder::GetName(char ** name)
if(!name)
return NS_ERROR_NULL_POINTER;
if (!mHaveReadNameFromDB)
if (!m_haveReadNameFromDB)
{
if (mDepth == 1)
{
SetName("Imap Host Name");
mHaveReadNameFromDB = TRUE;
m_haveReadNameFromDB = TRUE;
*name = mName.ToNewCString();
return NS_OK;
}
@ -520,6 +576,145 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
nsIImapProtocol* aProtocol, mailbox_spec* aSpec)
{
nsresult rv = NS_ERROR_FAILURE;
nsIMsgDatabase* mailDBFactory;
// **** fix me *** this is temporary stuff
nsString pathName = "/tmp";
pathName += aSpec->allocatedPathName;
nsFileSpec dbName(pathName);
rv = nsComponentManager::CreateInstance(kCImapDB, nsnull,
nsIMsgDatabase::GetIID(),
(void **) &mailDBFactory);
if (NS_FAILED(rv)) return rv;
if (!m_mailDatabase)
{
// if we pass in PR_TRUE for upgrading, the db code will ignore the
// summary out of date problem for now.
rv = mailDBFactory->Open(dbName, PR_TRUE, (nsIMsgDatabase **)
&m_mailDatabase, PR_TRUE);
if (NS_FAILED(rv))
{
NS_IF_RELEASE (mailDBFactory);
return rv;
}
if (!m_mailDatabase)
{
NS_IF_RELEASE (mailDBFactory);
return NS_ERROR_NULL_POINTER;
}
}
if (aSpec->folderSelected)
{
nsMsgKeyArray existingKeys;
nsMsgKeyArray keysToDelete;
nsMsgKeyArray keysToFetch;
nsIDBFolderInfo *dbFolderInfo = nsnull;
PRInt32 imapUIDValidity = 0;
rv = m_mailDatabase->GetDBFolderInfo(&dbFolderInfo);
if (NS_SUCCEEDED(rv) && dbFolderInfo)
dbFolderInfo->GetImapUidValidity(&imapUIDValidity);
m_mailDatabase->ListAllKeys(existingKeys);
if (m_mailDatabase->ListAllOfflineDeletes(&existingKeys) > 0)
existingKeys.QuickSort();
if ((imapUIDValidity != aSpec->folder_UIDVALIDITY) /* && // if UIDVALIDITY Changed
!NET_IsOffline() */)
{
nsIMsgDatabase *saveMailDB = m_mailDatabase;
#if TRANSFER_INFO
TNeoFolderInfoTransfer *originalInfo = NULL;
originalInfo = new TNeoFolderInfoTransfer(dbFolderInfo);
#endif // 0
m_mailDatabase->ForceClosed();
m_mailDatabase = NULL;
nsLocalFolderSummarySpec summarySpec(dbName);
// Remove summary file.
summarySpec.Delete(PR_FALSE);
// Create a new summary file, update the folder message counts, and
// Close the summary file db.
rv = mailDBFactory->Open(dbName, PR_TRUE, &m_mailDatabase, PR_FALSE);
if (NS_SUCCEEDED(rv))
{
#if TRANSFER_INFO
if (originalInfo)
{
originalInfo->TransferFolderInfo(*m_mailDatabase->m_dbFolderInfo);
delete originalInfo;
}
SummaryChanged();
#endif
}
// store the new UIDVALIDITY value
rv = m_mailDatabase->GetDBFolderInfo(&dbFolderInfo);
if (NS_SUCCEEDED(rv) && dbFolderInfo)
dbFolderInfo->SetImapUidValidity(aSpec->folder_UIDVALIDITY);
// delete all my msgs, the keys are bogus now
// add every message in this folder
existingKeys.RemoveAll();
// keysToDelete.CopyArray(&existingKeys);
if (aSpec->flagState)
{
nsMsgKeyArray no_existingKeys;
FindKeysToAdd(no_existingKeys, keysToFetch, aSpec->flagState);
}
}
else if (!aSpec->flagState /*&& !NET_IsOffline() */) // if there are no messages on the server
{
keysToDelete.CopyArray(&existingKeys);
}
else /* if ( !NET_IsOffline()) */
{
FindKeysToDelete(existingKeys, keysToDelete, aSpec->flagState);
// if this is the result of an expunge then don't grab headers
if (!(aSpec->box_flags & kJustExpunged))
FindKeysToAdd(existingKeys, keysToFetch, aSpec->flagState);
}
if (keysToDelete.GetSize())
{
PRUint32 total;
PRBool highWaterDeleted = FALSE;
// It would be nice to notify RDF or whoever of a mass delete here.
m_mailDatabase->DeleteMessages(&keysToDelete,NULL);
total = keysToDelete.GetSize();
nsMsgKey highWaterMark = nsMsgKey_None;
}
if (keysToFetch.GetSize())
{
PrepareToAddHeadersToMailDB(aProtocol, keysToFetch, aSpec);
if (aProtocol)
aProtocol->NotifyBodysToDownload(NULL, 0/*keysToFetch.GetSize() */);
}
else
{
// let the imap libnet module know that we don't need headers
if (aProtocol)
aProtocol->NotifyHdrsToDownload(NULL, 0);
// wait until we can get body id monitor before continuing.
// IMAP_BodyIdMonitor(adoptedBoxSpec->connection, TRUE);
// I think the real fix for this is to seperate the header ids from body id's.
// this is for fetching bodies for offline use
if (aProtocol)
aProtocol->NotifyBodysToDownload(NULL, 0/*keysToFetch.GetSize() */);
// NotifyFetchAnyNeededBodies(aSpec->connection, mailDB);
// IMAP_BodyIdMonitor(adoptedBoxSpec->connection, FALSE);
}
}
if (NS_FAILED(rv))
dbName.Delete(PR_FALSE);
NS_IF_RELEASE (mailDBFactory);
return rv;
}
@ -583,21 +778,78 @@ NS_IMETHODIMP nsImapMailFolder::SetupHeaderParseStream(
nsIImapProtocol* aProtocol, StreamInfo* aStreamInfo)
{
nsresult rv = NS_ERROR_FAILURE;
m_nextMessageByteLength = aStreamInfo->size;
if (!m_msgParser)
{
m_msgParser = new nsParseMailMessageState;
m_msgParser->SetMailDB(m_mailDatabase);
}
else
m_msgParser->Clear();
if (m_msgParser)
{
m_msgParser->m_state = MBOX_PARSE_HEADERS;
return NS_OK;
}
else
return NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_IMETHODIMP nsImapMailFolder::ParseAdoptedHeaderLine(
nsIImapProtocol* aProtocol, msg_line_info* aMsgLineInfo)
{
nsresult rv = NS_ERROR_FAILURE;
return rv;
// we can get blocks that contain more than one line,
// but they never contain partial lines
char *str = aMsgLineInfo->adoptedMessageLine;
m_curMsgUid = aMsgLineInfo->uidOfMessage;
m_msgParser->m_envelope_pos = m_curMsgUid; // OK, this is silly (but
// we'll fix
// it). m_envelope_pos, for
// local folders,
// is the msg key. Setting this will set the msg key for the new header.
PRInt32 len = nsCRT::strlen(str);
char *currentEOL = PL_strstr(str, LINEBREAK);
const char *currentLine = str;
while (currentLine < (str + len))
{
if (currentEOL)
{
m_msgParser->ParseFolderLine(currentLine,
(currentEOL + LINEBREAK_LEN) -
currentLine);
currentLine = currentEOL + LINEBREAK_LEN;
currentEOL = PL_strstr(currentLine, LINEBREAK);
}
else
{
m_msgParser->ParseFolderLine(currentLine, PL_strlen(currentLine));
currentLine = str + len + 1;
}
}
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::NormalEndHeaderParseStream(nsIImapProtocol*
aProtocol)
{
nsresult rv = NS_ERROR_FAILURE;
return rv;
if (m_msgParser && m_msgParser->m_newMsgHdr)
{
m_msgParser->m_newMsgHdr->SetMessageKey(m_curMsgUid);
TweakHeaderFlags(aProtocol, m_msgParser->m_newMsgHdr);
// here we need to tweak flags from uid state..
m_mailDatabase->AddNewHdrToDB(m_msgParser->m_newMsgHdr, PR_TRUE);
m_msgParser->FinishHeader();
if (m_mailDatabase)
m_mailDatabase->Commit(kLargeCommit); // don't really want to do this
// for every message...
// but I can't find the event that
// means we've finished getting
// headers
}
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::AbortHeaderParseStream(nsIImapProtocol*
@ -658,4 +910,499 @@ NS_IMETHODIMP nsImapMailFolder::EndCopy(PRBool copySucceeded)
}
// both of these algorithms assume that key arrays and flag states are sorted by increasing key.
void nsImapMailFolder::FindKeysToDelete(const nsMsgKeyArray &existingKeys, nsMsgKeyArray &keysToDelete, nsImapFlagAndUidState *flagState)
{
PRBool imapDeleteIsMoveToTrash = /* DeleteIsMoveToTrash() */ PR_TRUE;
PRUint32 total = existingKeys.GetSize();
PRInt32 index;
int onlineIndex=0; // current index into flagState
for (PRUint32 keyIndex=0; keyIndex < total; keyIndex++)
{
PRUint32 uidOfMessage;
flagState->GetNumberOfMessages(&index);
while ((onlineIndex < index) &&
(flagState->GetUidOfMessage(onlineIndex, &uidOfMessage), (existingKeys[keyIndex] > uidOfMessage) ))
{
onlineIndex++;
}
imapMessageFlagsType flags;
flagState->GetUidOfMessage(onlineIndex, &uidOfMessage);
flagState->GetMessageFlags(onlineIndex, &flags);
// delete this key if it is not there or marked deleted
if ( (onlineIndex >= index ) ||
(existingKeys[keyIndex] != uidOfMessage) ||
((flags & kImapMsgDeletedFlag) && imapDeleteIsMoveToTrash) )
{
nsMsgKey doomedKey = existingKeys[keyIndex];
if ((PRInt32) doomedKey < 0 && doomedKey != nsMsgKey_None)
continue;
else
keysToDelete.Add(existingKeys[keyIndex]);
}
flagState->GetUidOfMessage(onlineIndex, &uidOfMessage);
if (existingKeys[keyIndex] == uidOfMessage)
onlineIndex++;
}
}
void nsImapMailFolder::FindKeysToAdd(const nsMsgKeyArray &existingKeys, nsMsgKeyArray &keysToFetch, nsImapFlagAndUidState *flagState)
{
PRBool showDeletedMessages = PR_FALSE /* ShowDeletedMessages() */;
int dbIndex=0; // current index into existingKeys
PRInt32 existTotal, numberOfKnownKeys;
PRInt32 index;
existTotal = numberOfKnownKeys = existingKeys.GetSize();
flagState->GetNumberOfMessages(&index);
for (PRInt32 flagIndex=0; flagIndex < index; flagIndex++)
{
PRUint32 uidOfMessage;
flagState->GetUidOfMessage(flagIndex, &uidOfMessage);
while ( (flagIndex < numberOfKnownKeys) && (dbIndex < existTotal) &&
existingKeys[dbIndex] < uidOfMessage)
dbIndex++;
if ( (flagIndex >= numberOfKnownKeys) ||
(dbIndex >= existTotal) ||
(existingKeys[dbIndex] != uidOfMessage ) )
{
numberOfKnownKeys++;
imapMessageFlagsType flags;
flagState->GetMessageFlags(flagIndex, &flags);
if (showDeletedMessages || ! (flags & kImapMsgDeletedFlag))
{
keysToFetch.Add(uidOfMessage);
}
}
}
}
void nsImapMailFolder::PrepareToAddHeadersToMailDB(nsIImapProtocol* aProtocol, const nsMsgKeyArray &keysToFetch,
mailbox_spec *boxSpec)
{
PRUint32 *theKeys = (PRUint32 *) PR_Malloc( keysToFetch.GetSize() * sizeof(PRUint32) );
if (theKeys)
{
PRUint32 total = keysToFetch.GetSize();
for (int keyIndex=0; keyIndex < total; keyIndex++)
theKeys[keyIndex] = keysToFetch[keyIndex];
// m_DownLoadState = kDownLoadingAllMessageHeaders;
nsresult res = NS_OK; /*ImapMailDB::Open(m_pathName,
TRUE, // create if necessary
&mailDB,
m_master,
&dbWasCreated); */
// don't want to download headers in a composition pane
if (NS_SUCCEEDED(res))
{
#if 0
SetParseMailboxState(new ParseIMAPMailboxState(m_master, m_host, this,
urlQueue,
boxSpec->flagState));
boxSpec->flagState = NULL; // adopted by ParseIMAPMailboxState
GetParseMailboxState()->SetPane(url_pane);
GetParseMailboxState()->SetDB(mailDB);
GetParseMailboxState()->SetIncrementalUpdate(TRUE);
GetParseMailboxState()->SetMaster(m_master);
GetParseMailboxState()->SetContext(url_pane->GetContext());
GetParseMailboxState()->SetFolder(this);
GetParseMailboxState()->BeginParsingFolder(0);
#endif // 0 hook up parsing later.
// the imap libnet module will start downloading message headers imap.h
if (aProtocol)
aProtocol->NotifyHdrsToDownload(theKeys, total /*keysToFetch.GetSize() */);
// now, tell it we don't need any bodies.
if (aProtocol)
aProtocol->NotifyBodysToDownload(NULL, 0);
}
else
{
if (aProtocol)
aProtocol->NotifyHdrsToDownload(NULL, 0);
}
}
}
void nsImapMailFolder::TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMessage *tweakMe)
{
if (m_mailDatabase && aProtocol && tweakMe)
{
tweakMe->SetMessageKey(m_curMsgUid);
tweakMe->SetMessageSize(m_nextMessageByteLength);
PRBool foundIt = FALSE;
imapMessageFlagsType imap_flags;
nsresult res = aProtocol->GetFlagsForUID(m_curMsgUid, &foundIt, &imap_flags);
if (NS_SUCCEEDED(res) && foundIt)
{
// make a mask and clear these message flags
PRUint32 mask = MSG_FLAG_READ | MSG_FLAG_REPLIED | MSG_FLAG_MARKED | MSG_FLAG_IMAP_DELETED;
PRUint32 dbHdrFlags;
tweakMe->GetFlags(&dbHdrFlags);
tweakMe->AndFlags(~mask, &dbHdrFlags);
// set the new value for these flags
PRUint32 newFlags = 0;
if (imap_flags & kImapMsgSeenFlag)
newFlags |= MSG_FLAG_READ;
else // if (imap_flags & kImapMsgRecentFlag)
newFlags |= MSG_FLAG_NEW;
// Okay here is the MDN needed logic (if DNT header seen):
/* if server support user defined flag:
MDNSent flag set => clear kMDNNeeded flag
MDNSent flag not set => do nothing, leave kMDNNeeded on
else if
not MSG_FLAG_NEW => clear kMDNNeeded flag
MSG_FLAG_NEW => do nothing, leave kMDNNeeded on
*/
PRUint16 userFlags;
nsresult res = aProtocol->GetSupportedUserFlags(&userFlags);
if (NS_SUCCEEDED(res) && (userFlags & (kImapMsgSupportUserFlag |
kImapMsgSupportMDNSentFlag)))
{
if (imap_flags & kImapMsgMDNSentFlag)
{
newFlags |= MSG_FLAG_MDN_REPORT_SENT;
if (dbHdrFlags & MSG_FLAG_MDN_REPORT_NEEDED)
tweakMe->AndFlags(~MSG_FLAG_MDN_REPORT_NEEDED, &dbHdrFlags);
}
}
else
{
if (!(imap_flags & kImapMsgRecentFlag) &&
dbHdrFlags & MSG_FLAG_MDN_REPORT_NEEDED)
tweakMe->AndFlags(~MSG_FLAG_MDN_REPORT_NEEDED, &dbHdrFlags);
}
if (imap_flags & kImapMsgAnsweredFlag)
newFlags |= MSG_FLAG_REPLIED;
if (imap_flags & kImapMsgFlaggedFlag)
newFlags |= MSG_FLAG_MARKED;
if (imap_flags & kImapMsgDeletedFlag)
newFlags |= MSG_FLAG_IMAP_DELETED;
if (imap_flags & kImapMsgForwardedFlag)
newFlags |= MSG_FLAG_FORWARDED;
if (newFlags)
tweakMe->OrFlags(newFlags, &dbHdrFlags);
}
}
}
NS_IMETHODIMP
nsImapMailFolder::SetupMsgWriteStream(nsIImapProtocol* aProtocol,
StreamInfo* aStreamInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::ParseAdoptedMsgLine(nsIImapProtocol* aProtocol,
msg_line_info* aMsgLineInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::NormalEndMsgWriteStream(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::AbortMsgWriteStream(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
// message move/copy related methods
NS_IMETHODIMP
nsImapMailFolder::OnlineCopyReport(nsIImapProtocol* aProtocol,
ImapOnlineCopyState* aCopyState)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::BeginMessageUpload(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::UploadMessageFile(nsIImapProtocol* aProtocol,
UploadMessageInfo* aMsgInfo)
{
return NS_ERROR_FAILURE;
}
// message flags operation
NS_IMETHODIMP
nsImapMailFolder::NotifyMessageFlags(nsIImapProtocol* aProtocol,
FlagsKeyStruct* aKeyStruct)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::NotifyMessageDeleted(nsIImapProtocol* aProtocol,
delete_message_struct* aStruct)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetMessageSizeFromDB(nsIImapProtocol* aProtocol,
MessageSizeInfo* sizeInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::OnStartRunningUrl(nsIURL *aUrl)
{
NS_PRECONDITION(aUrl, "just a sanity check since this is a test program");
m_urlRunning = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::OnStopRunningUrl(nsIURL *aUrl, nsresult aExitCode)
{
NS_PRECONDITION(aUrl, "just a sanity check since this is a test program");
nsresult rv = NS_OK;
m_urlRunning = PR_FALSE;
if (aUrl)
{
// query it for a mailnews interface for now....
nsIMsgMailNewsUrl * mailUrl = nsnull;
rv = aUrl->QueryInterface(nsIMsgMailNewsUrl::GetIID(),
(void **) mailUrl);
if (NS_SUCCEEDED(rv) && mailUrl)
{
mailUrl->UnRegisterListener(this);
NS_RELEASE (mailUrl);
}
}
return NS_OK;
}
// nsIImapExtensionSink methods
NS_IMETHODIMP
nsImapMailFolder::SetUserAuthenticated(nsIImapProtocol* aProtocol,
PRBool aBool)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::SetMailServerUrls(nsIImapProtocol* aProtocol,
const char* hostName)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::SetMailAccountUrl(nsIImapProtocol* aProtocol,
const char* hostName)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::SetFolderAdminURL(nsIImapProtocol* aProtocol,
FolderQueryInfo* aInfo)
{
return NS_ERROR_FAILURE;
}
// nsIImapMiscellaneousSink methods
NS_IMETHODIMP
nsImapMailFolder::AddSearchResult(nsIImapProtocol* aProtocol,
const char* searchHitLine)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetArbitraryHeaders(nsIImapProtocol* aProtocol,
GenericInfo* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetShouldDownloadArbitraryHeaders(nsIImapProtocol* aProtocol,
GenericInfo* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetShowAttachmentsInline(nsIImapProtocol* aProtocol,
PRBool* aBool)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::HeaderFetchCompleted(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::UpdateSecurityStatus(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
// ****
NS_IMETHODIMP
nsImapMailFolder::FinishImapConnection(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::SetImapHostPassword(nsIImapProtocol* aProtocol,
GenericInfo* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetPasswordForUser(nsIImapProtocol* aProtocol,
const char* userName)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::SetBiffStateAndUpdate(nsIImapProtocol* aProtocol,
nsMsgBiffState biffState)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::GetStoredUIDValidity(nsIImapProtocol* aProtocol,
uid_validity_info* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::LiteSelectUIDValidity(nsIImapProtocol* aProtocol,
PRUint32 uidValidity)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::FEAlert(nsIImapProtocol* aProtocol,
const char* aString)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::FEAlertFromServer(nsIImapProtocol* aProtocol,
const char* aString)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::ProgressStatus(nsIImapProtocol* aProtocol,
const char* statusMsg)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::PercentProgress(nsIImapProtocol* aProtocol,
ProgressInfo* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::PastPasswordCheck(nsIImapProtocol* aProtocol)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::CommitNamespaces(nsIImapProtocol* aProtocol,
const char* hostName)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::CommitCapabilityForHost(nsIImapProtocol* aProtocol,
const char* hostName)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::TunnelOutStream(nsIImapProtocol* aProtocol,
msg_line_info* aInfo)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsImapMailFolder::ProcessTunnel(nsIImapProtocol* aProtocol,
TunnelInfo *aInfo)
{
return NS_ERROR_FAILURE;
}

View File

@ -21,19 +21,30 @@
#include "nsImapCore.h"
#include "nsMsgFolder.h"
#include "nsIImapMailfolderSink.h"
#include "nsIImapMessageSink.h"
#include "nsIImapExtensionSink.h"
#include "nsIImapMiscellaneousSink.h"
#include "nsIDBChangeListener.h"
#include "nsICopyMessageListener.h"
#include "nsIImapService.h"
#include "nsIUrlListener.h"
/* fa32d000-f6a0-11d2-af8d-001083002da8 */
#define NS_IMAPRESOURCE_CID \
{ 0xfa32d000, 0xf6a0, 0x11d2, \
{ 0xaf, 0x8d, 0x00, 0x10, 0x83, 0x00, 0x2d, 0xa8 } }
class nsParseMailMessageState;
class nsImapMailFolder : public nsMsgFolder,
public nsIMsgImapMailFolder,
public nsIImapMailFolderSink,
public nsIImapMessageSink,
public nsIImapExtensionSink,
public nsIImapMiscellaneousSink,
public nsIDBChangeListener,
public nsICopyMessageListener
public nsICopyMessageListener,
public nsIUrlListener
{
public:
nsImapMailFolder();
@ -126,6 +137,33 @@ public:
NS_IMETHOD AbortHeaderParseStream(nsIImapProtocol* aProtocol);
// nsIImapMessageSink methods
NS_IMETHOD SetupMsgWriteStream(nsIImapProtocol* aProtocol,
StreamInfo* aStreamInfo);
NS_IMETHOD ParseAdoptedMsgLine(nsIImapProtocol* aProtocol,
msg_line_info* aMsgLineInfo);
NS_IMETHOD NormalEndMsgWriteStream(nsIImapProtocol* aProtocol);
NS_IMETHOD AbortMsgWriteStream(nsIImapProtocol* aProtocol);
// message move/copy related methods
NS_IMETHOD OnlineCopyReport(nsIImapProtocol* aProtocol,
ImapOnlineCopyState* aCopyState);
NS_IMETHOD BeginMessageUpload(nsIImapProtocol* aProtocol);
NS_IMETHOD UploadMessageFile(nsIImapProtocol* aProtocol,
UploadMessageInfo* aMsgInfo);
// message flags operation
NS_IMETHOD NotifyMessageFlags(nsIImapProtocol* aProtocol,
FlagsKeyStruct* aKeyStruct);
NS_IMETHOD NotifyMessageDeleted(nsIImapProtocol* aProtocol,
delete_message_struct* aStruct);
NS_IMETHOD GetMessageSizeFromDB(nsIImapProtocol* aProtocol,
MessageSizeInfo* sizeInfo);
//nsIDBChangeListener
NS_IMETHOD OnKeyChange(nsMsgKey aKeyChanged, int32 aFlags,
nsIDBChangeListener * aInstigator);
@ -140,18 +178,94 @@ public:
NS_IMETHOD CopyData(nsIInputStream *aIStream, PRInt32 aLength);
NS_IMETHOD EndCopy(PRBool copySucceeded);
// nsIUrlListener methods
NS_IMETHOD OnStartRunningUrl(nsIURL * aUrl);
NS_IMETHOD OnStopRunningUrl(nsIURL * aUrl, nsresult aExitCode);
// nsIImapExtensionSink methods
NS_IMETHOD SetUserAuthenticated(nsIImapProtocol* aProtocol,
PRBool aBool);
NS_IMETHOD SetMailServerUrls(nsIImapProtocol* aProtocol,
const char* hostName);
NS_IMETHOD SetMailAccountUrl(nsIImapProtocol* aProtocol,
const char* hostName);
NS_IMETHOD ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD SetFolderAdminURL(nsIImapProtocol* aProtocol,
FolderQueryInfo* aInfo);
// nsIImapMiscellaneousSink methods
NS_IMETHOD AddSearchResult(nsIImapProtocol* aProtocol,
const char* searchHitLine);
NS_IMETHOD GetArbitraryHeaders(nsIImapProtocol* aProtocol,
GenericInfo* aInfo);
NS_IMETHOD GetShouldDownloadArbitraryHeaders(nsIImapProtocol* aProtocol,
GenericInfo* aInfo);
NS_IMETHOD GetShowAttachmentsInline(nsIImapProtocol* aProtocol,
PRBool* aBool);
NS_IMETHOD HeaderFetchCompleted(nsIImapProtocol* aProtocol);
NS_IMETHOD UpdateSecurityStatus(nsIImapProtocol* aProtocol);
// ****
NS_IMETHOD FinishImapConnection(nsIImapProtocol* aProtocol);
NS_IMETHOD SetImapHostPassword(nsIImapProtocol* aProtocol,
GenericInfo* aInfo);
NS_IMETHOD GetPasswordForUser(nsIImapProtocol* aProtocol,
const char* userName);
NS_IMETHOD SetBiffStateAndUpdate(nsIImapProtocol* aProtocol,
nsMsgBiffState biffState);
NS_IMETHOD GetStoredUIDValidity(nsIImapProtocol* aProtocol,
uid_validity_info* aInfo);
NS_IMETHOD LiteSelectUIDValidity(nsIImapProtocol* aProtocol,
PRUint32 uidValidity);
NS_IMETHOD FEAlert(nsIImapProtocol* aProtocol,
const char* aString);
NS_IMETHOD FEAlertFromServer(nsIImapProtocol* aProtocol,
const char* aString);
NS_IMETHOD ProgressStatus(nsIImapProtocol* aProtocol,
const char* statusMsg);
NS_IMETHOD PercentProgress(nsIImapProtocol* aProtocol,
ProgressInfo* aInfo);
NS_IMETHOD PastPasswordCheck(nsIImapProtocol* aProtocol);
NS_IMETHOD CommitNamespaces(nsIImapProtocol* aProtocol,
const char* hostName);
NS_IMETHOD CommitCapabilityForHost(nsIImapProtocol* aProtocol,
const char* hostName);
NS_IMETHOD TunnelOutStream(nsIImapProtocol* aProtocol,
msg_line_info* aInfo);
NS_IMETHOD ProcessTunnel(nsIImapProtocol* aProtocol,
TunnelInfo *aInfo);
protected:
// Helper methods
void FindKeysToAdd(const nsMsgKeyArray &existingKeys, nsMsgKeyArray
&keysToFetch, nsImapFlagAndUidState *flagState);
void FindKeysToDelete(const nsMsgKeyArray &existingKeys, nsMsgKeyArray
&keysToFetch, nsImapFlagAndUidState *flagState);
void PrepareToAddHeadersToMailDB(nsIImapProtocol* aProtocol, const
nsMsgKeyArray &keysToFetch,
mailbox_spec *boxSpec);
void TweakHeaderFlags(nsIImapProtocol* aProtocol, nsIMessage *tweakMe);
nsresult AddDirectorySeparator(nsFileSpec &path);
nsresult CreateSubFolders(nsFileSpec &path);
//Creates a subfolder with the name 'name' and adds it to the list of
//children. Returns the child as well.
nsresult AddSubfolder(nsAutoString name, nsIMsgFolder **child);
nsNativeFileSpec mPathName;
nsIMsgDatabase* mMailDatabase;
PRBool mInitialized;
PRBool mHaveReadNameFromDB;
nsNativeFileSpec m_pathName;
nsIMsgDatabase* m_mailDatabase;
PRBool m_initialized;
PRBool m_haveReadNameFromDB;
nsParseMailMessageState *m_msgParser;
nsMsgKey m_curMsgUid;
PRInt32 m_nextMessageByteLength;
PLEventQueue* m_eventQueue;
PRBool m_urlRunning;
};
#endif

View File

@ -254,6 +254,7 @@ nsresult nsImapProtocol::Initialize(nsIImapHostSessionList * aHostSessionList, P
m_fetchMsgListMonitor = PR_NewMonitor();
m_fetchBodyListMonitor = PR_NewMonitor();
SetFlag(IMAP_FIRST_PASS_IN_THREAD);
m_thread = PR_CreateThread(PR_USER_THREAD, ImapThreadMain, (void*)
this, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
PR_UNJOINABLE_THREAD, 0);
@ -578,6 +579,16 @@ nsImapProtocol::ImapThreadMainLoop()
// ****** please implement PR_LOG 'ing ******
while (ImapThreadIsRunning())
{
// if we are making our first pass through this loop and
// we already have a url to process then jump right in and
// process the current url. Don't try to wait for the monitor
// the first time because it may have already been signaled.
if (TestFlag(IMAP_FIRST_PASS_IN_THREAD) && m_runningUrl)
{
ProcessCurrentURL();
ClearFlag(IMAP_FIRST_PASS_IN_THREAD);
}
PR_EnterMonitor(m_urlReadyToRunMonitor);
PR_Wait(m_urlReadyToRunMonitor, PR_INTERVAL_NO_TIMEOUT);

View File

@ -46,6 +46,7 @@ class nsIMsgIncomingServer;
// of creating PRBools for everything....
#define IMAP_RECEIVED_GREETING 0x00000001 /* should we pause for the next read */
#define IMAP_FIRST_PASS_IN_THREAD 0x00000002 /* entering thread for the first time? */
class nsImapProtocol : public nsIImapProtocol
{