Пример #1
0
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;
}
Пример #2
0
CSkillTableMap::~CSkillTableMap()
{
	ClearDB();
}
Пример #3
0
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;
}
Пример #4
0
void nsImapOfflineSync::ProcessEmptyTrash()
{
  m_currentFolder->EmptyTrash(m_window, this);
  ClearDB(); // EmptyTrash closes and deletes the trash db.
}
Пример #5
0
/* void OnAnnouncerGoingAway (in nsIDBChangeAnnouncer instigator); */
NS_IMETHODIMP
nsImapOfflineSync::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator)
{
  ClearDB();
  return NS_OK;
}
Пример #6
0
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;
}