nsresult nsImapOfflineSync::AdvanceToNextFolder() { nsresult rv; // we always start by changing flags mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kFlagsChanged; if (m_currentFolder) { m_currentFolder->SetMsgDatabase(nsnull); m_currentFolder = nsnull; } if (!m_currentServer) rv = AdvanceToNextServer(); else rv = m_serverEnumerator->Next(); if (NS_FAILED(rv)) rv = AdvanceToNextServer(); if (NS_SUCCEEDED(rv) && m_serverEnumerator) { nsCOMPtr <nsISupports> supports; rv = m_serverEnumerator->CurrentItem(getter_AddRefs(supports)); m_currentFolder = do_QueryInterface(supports); } ClearDB(); return rv; }
CSkillTableMap::~CSkillTableMap() { ClearDB(); }
nsresult nsImapOfflineSync::ProcessNextOperation() { nsresult rv = NS_OK; // find a folder that needs to process operations nsIMsgFolder *deletedAllOfflineEventsInFolder = nsnull; // if we haven't created offline folders, and we're updating all folders, // first, find offline folders to create. if (!m_createdOfflineFolders) { if (m_singleFolderToUpdate) { if (!m_pseudoOffline) { AdvanceToFirstIMAPFolder(); if (CreateOfflineFolders()) return NS_OK; } } else { if (CreateOfflineFolders()) return NS_OK; m_currentServer = nsnull; AdvanceToNextFolder(); } m_createdOfflineFolders = PR_TRUE; } // if updating one folder only, restore m_currentFolder to that folder if (m_singleFolderToUpdate) m_currentFolder = m_singleFolderToUpdate; PRUint32 folderFlags; nsCOMPtr <nsIDBFolderInfo> folderInfo; while (m_currentFolder && !m_currentDB) { m_currentFolder->GetFlags(&folderFlags); // need to check if folder has offline events, /* or is configured for offline */ // shouldn't need to check if configured for offline use, since any folder with // events should have nsMsgFolderFlags::OfflineEvents set. if (folderFlags & (nsMsgFolderFlags::OfflineEvents /* | nsMsgFolderFlags::Offline */)) { m_currentFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(m_currentDB)); if (m_currentDB) m_currentDB->AddListener(this); } if (m_currentDB) { m_CurrentKeys.Clear(); m_KeyIndex = 0; if ((m_currentDB->ListAllOfflineOpIds(&m_CurrentKeys) != 0) || m_CurrentKeys.IsEmpty()) { ClearDB(); folderInfo = nsnull; // can't hold onto folderInfo longer than db m_currentFolder->ClearFlag(nsMsgFolderFlags::OfflineEvents); } else { // trash any ghost msgs PRBool deletedGhostMsgs = PR_FALSE; for (PRUint32 fakeIndex=0; fakeIndex < m_CurrentKeys.Length(); fakeIndex++) { nsCOMPtr <nsIMsgOfflineImapOperation> currentOp; m_currentDB->GetOfflineOpForKey(m_CurrentKeys[fakeIndex], PR_FALSE, getter_AddRefs(currentOp)); if (currentOp) { nsOfflineImapOperationType opType; currentOp->GetOperation(&opType); if (opType == nsIMsgOfflineImapOperation::kMoveResult) { nsMsgKey curKey; currentOp->GetMessageKey(&curKey); m_currentDB->RemoveOfflineOp(currentOp); deletedGhostMsgs = PR_TRUE; // for imap folders, we should adjust the pending counts, because we // have a header that we know about, but don't have in the db. nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_currentFolder); if (imapFolder) { PRBool hdrIsRead; m_currentDB->IsRead(curKey, &hdrIsRead); imapFolder->ChangePendingTotal(1); if (!hdrIsRead) imapFolder->ChangePendingUnread(1); } m_currentDB->DeleteMessage(curKey, nsnull, PR_FALSE); } } } if (deletedGhostMsgs) m_currentFolder->SummaryChanged(); m_CurrentKeys.Clear(); if ( (m_currentDB->ListAllOfflineOpIds(&m_CurrentKeys) != 0) || m_CurrentKeys.IsEmpty() ) { ClearDB(); if (deletedGhostMsgs) deletedAllOfflineEventsInFolder = m_currentFolder; } else if (folderFlags & nsMsgFolderFlags::ImapBox) { // if pseudo offline, falls through to playing ops back. if (!m_pseudoOffline) { // there are operations to playback so check uid validity SetCurrentUIDValidity(0); // force initial invalid state // do a lite select here and hook ourselves up as a listener. nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_currentFolder, &rv); if (imapFolder) rv = imapFolder->LiteSelect(this, m_window); // this is async, we will be called again by OnStopRunningUrl. return rv; } } } } if (!m_currentDB) { // only advance if we are doing all folders if (!m_singleFolderToUpdate) AdvanceToNextFolder(); else m_currentFolder = nsnull; // force update of this folder now. } } if (m_currentFolder) m_currentFolder->GetFlags(&folderFlags); // do the current operation if (m_currentDB) { PRBool currentFolderFinished = PR_FALSE; if (!folderInfo) m_currentDB->GetDBFolderInfo(getter_AddRefs(folderInfo)); // user canceled the lite select! if GetCurrentUIDValidity() == 0 if (folderInfo && (m_KeyIndex < m_CurrentKeys.Length()) && (m_pseudoOffline || (GetCurrentUIDValidity() != 0) || !(folderFlags & nsMsgFolderFlags::ImapBox))) { PRInt32 curFolderUidValidity; folderInfo->GetImapUidValidity(&curFolderUidValidity); PRBool uidvalidityChanged = (!m_pseudoOffline && folderFlags & nsMsgFolderFlags::ImapBox) && (GetCurrentUIDValidity() != curFolderUidValidity); nsCOMPtr <nsIMsgOfflineImapOperation> currentOp; if (uidvalidityChanged) DeleteAllOfflineOpsForCurrentDB(); else m_currentDB->GetOfflineOpForKey(m_CurrentKeys[m_KeyIndex], PR_FALSE, getter_AddRefs(currentOp)); if (currentOp) { nsOfflineImapOperationType opType; currentOp->GetOperation(&opType); // loop until we find the next db record that matches the current playback operation while (currentOp && !(opType & mCurrentPlaybackOpType)) { currentOp = nsnull; ++m_KeyIndex; if (m_KeyIndex < m_CurrentKeys.Length()) m_currentDB->GetOfflineOpForKey(m_CurrentKeys[m_KeyIndex], PR_FALSE, getter_AddRefs(currentOp)); if (currentOp) currentOp->GetOperation(&opType); } // if we did not find a db record that matches the current playback operation, // then move to the next playback operation and recurse. if (!currentOp) { // we are done with the current type if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kFlagsChanged) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kAddKeywords; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAddKeywords) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kRemoveKeywords; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kRemoveKeywords) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kMsgCopy; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kMsgCopy) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kMsgMoved; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kMsgMoved) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kAppendDraft; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAppendDraft) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kAppendTemplate; // recurse to deal with next type of operation m_KeyIndex = 0; ProcessNextOperation(); } else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAppendTemplate) { mCurrentPlaybackOpType = nsIMsgOfflineImapOperation::kDeleteAllMsgs; m_KeyIndex = 0; ProcessNextOperation(); } else { DeleteAllOfflineOpsForCurrentDB(); currentFolderFinished = PR_TRUE; } } else { if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kFlagsChanged) ProcessFlagOperation(currentOp); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAddKeywords ||mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kRemoveKeywords) ProcessKeywordOperation(currentOp); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kMsgCopy) ProcessCopyOperation(currentOp); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kMsgMoved) ProcessMoveOperation(currentOp); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAppendDraft) ProcessAppendMsgOperation(currentOp, nsIMsgOfflineImapOperation::kAppendDraft); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kAppendTemplate) ProcessAppendMsgOperation(currentOp, nsIMsgOfflineImapOperation::kAppendTemplate); else if (mCurrentPlaybackOpType == nsIMsgOfflineImapOperation::kDeleteAllMsgs) { // empty trash is going to delete the db, so we'd better release the // reference to the offline operation first. currentOp = nsnull; ProcessEmptyTrash(); } else NS_ERROR("invalid playback op type"); } } else currentFolderFinished = PR_TRUE; } else currentFolderFinished = PR_TRUE; if (currentFolderFinished) { ClearDB(); if (!m_singleFolderToUpdate) { AdvanceToNextFolder(); ProcessNextOperation(); return NS_OK; } else m_currentFolder = nsnull; } } if (!m_currentFolder && !m_mailboxupdatesStarted) { m_mailboxupdatesStarted = PR_TRUE; // if we are updating more than one folder then we need the iterator if (!m_singleFolderToUpdate) { m_currentServer = nsnull; AdvanceToNextFolder(); } if (m_singleFolderToUpdate) { m_singleFolderToUpdate->ClearFlag(nsMsgFolderFlags::OfflineEvents); m_singleFolderToUpdate->UpdateFolder(m_window); // do we have to do anything? Old code would do a start update... } else { } // MSG_FolderIterator *updateFolderIterator = m_singleFolderToUpdate ? (MSG_FolderIterator *) 0 : m_folderIterator; // we are done playing commands back, now queue up the sync with each imap folder // If we're using the iterator, m_currentFolder will be set correctly // nsIMsgFolder * folder = m_singleFolderToUpdate ? m_singleFolderToUpdate : m_currentFolder; // while (folder) // { // PRBool loadingFolder = m_workerPane->GetLoadingImapFolder() == folder; // if ((folder->GetType() == FOLDER_IMAPMAIL) && (deletedAllOfflineEventsInFolder == folder || (folder->GetFolderPrefFlags() & nsMsgFolderFlags::Offline) // || loadingFolder) // && !(folder->GetFolderPrefFlags() & MSG_FOLDER_PREF_IMAPNOSELECT) ) // { // PRBool lastChance = ((deletedAllOfflineEventsInFolder == folder) && m_singleFolderToUpdate) || loadingFolder; // if deletedAllOfflineEventsInFolder == folder and we're only updating one folder, then we need to update newly selected folder // I think this also means that we're really opening the folder...so we tell StartUpdate that we're loading a folder. // if (!updateFolderIterator || !(imapMail->GetFlags() & nsMsgFolderFlags::Inbox)) // avoid queueing the inbox twice // imapMail->StartUpdateOfNewlySelectedFolder(m_workerPane, lastChance, queue, nsnsnull, PR_FALSE, PR_FALSE); // } // folder= m_singleFolderToUpdate ? (MSG_FolderInfo *)nsnull : updateFolderIterator->Next(); // } } // if we get here, then I *think* we're done. Not sure, though. #ifdef DEBUG_bienvenu printf("done with offline imap sync\n"); #endif nsCOMPtr <nsIUrlListener> saveListener = m_listener; m_listener = nsnull; if (saveListener) saveListener->OnStopRunningUrl(nsnull /* don't know url */, rv); return rv; }
void nsImapOfflineSync::ProcessEmptyTrash() { m_currentFolder->EmptyTrash(m_window, this); ClearDB(); // EmptyTrash closes and deletes the trash db. }
/* void OnAnnouncerGoingAway (in nsIDBChangeAnnouncer instigator); */ NS_IMETHODIMP nsImapOfflineSync::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator) { ClearDB(); return NS_OK; }
nsresult nsImapOfflineDownloader::ProcessNextOperation() { nsresult rv = NS_OK; if (!m_mailboxupdatesStarted) { m_mailboxupdatesStarted = PR_TRUE; // Update the INBOX first so the updates on the remaining // folders pickup the results of any filter moves. nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsISupportsArray> servers; rv = accountManager->GetAllServers(getter_AddRefs(servers)); if (NS_FAILED(rv)) return rv; } if (!m_mailboxupdatesFinished) { AdvanceToNextServer(); if (m_currentServer) { nsCOMPtr <nsIMsgFolder> rootMsgFolder; m_currentServer->GetRootFolder(getter_AddRefs(rootMsgFolder)); nsCOMPtr<nsIMsgFolder> inbox; if (rootMsgFolder) { rootMsgFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, getter_AddRefs(inbox)); if (inbox) { nsCOMPtr <nsIMsgFolder> offlineImapFolder; nsCOMPtr <nsIMsgImapMailFolder> imapInbox = do_QueryInterface(inbox); if (imapInbox) { rootMsgFolder->GetFolderWithFlags(nsMsgFolderFlags::Offline, getter_AddRefs(offlineImapFolder)); if (!offlineImapFolder) { // no imap folders configured for offline use - check if the account is set up // so that we always download inbox msg bodies for offline use nsCOMPtr <nsIImapIncomingServer> imapServer = do_QueryInterface(m_currentServer); if (imapServer) { PRBool downloadBodiesOnGetNewMail = PR_FALSE; imapServer->GetDownloadBodiesOnGetNewMail(&downloadBodiesOnGetNewMail); if (downloadBodiesOnGetNewMail) offlineImapFolder = inbox; } } } // if this isn't an imap inbox, or we have an offline imap sub-folder, then update the inbox. // otherwise, it's an imap inbox for an account with no folders configured for offline use, // so just advance to the next server. if (!imapInbox || offlineImapFolder) { // here we should check if this a pop3 server/inbox, and the user doesn't want // to download pop3 mail for offline use. if (!imapInbox) { } rv = inbox->GetNewMessages(m_window, this); if (NS_SUCCEEDED(rv)) return rv; // otherwise, fall through. } } } return ProcessNextOperation(); // recurse and do next server. } else { m_allServers = nsnull; m_mailboxupdatesFinished = PR_TRUE; } } AdvanceToNextFolder(); while (m_currentFolder) { PRUint32 folderFlags; ClearDB(); nsCOMPtr <nsIMsgImapMailFolder> imapFolder; if (m_currentFolder) imapFolder = do_QueryInterface(m_currentFolder); m_currentFolder->GetFlags(&folderFlags); // need to check if folder has offline events, or is configured for offline if (imapFolder && folderFlags & nsMsgFolderFlags::Offline && ! (folderFlags & nsMsgFolderFlags::Virtual)) { rv = m_currentFolder->DownloadAllForOffline(this, m_window); if (NS_SUCCEEDED(rv) || rv == NS_BINDING_ABORTED) return rv; // if this fails and the user didn't cancel/stop, fall through to code that advances to next folder } AdvanceToNextFolder(); } if (m_listener) m_listener->OnStopRunningUrl(nsnull, NS_OK); return rv; }