Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes
nsMsgFilterAfterTheFact Class Reference
Inheritance diagram for nsMsgFilterAfterTheFact:
Inheritance graph
[legend]
Collaboration diagram for nsMsgFilterAfterTheFact:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsMsgFilterAfterTheFact (nsIMsgWindow *aMsgWindow, nsIMsgFilterList *aFilterList, nsISupportsArray *aFolderList)
virtual ~nsMsgFilterAfterTheFact ()
NS_DECL_ISUPPORTS
NS_DECL_NSIURLLISTENER
NS_DECL_NSIMSGSEARCHNOTIFY
NS_DECL_NSIMSGCOPYSERVICELISTENER
nsresult 
AdvanceToNextFolder ()
void OnStartRunningUrl (in nsIURI url)
void OnStopRunningUrl (in nsIURI url, in nsresult aExitCode)
void onSearchHit (in nsIMsgDBHdr header, in nsIMsgFolder folder)
void onSearchDone (in nsresult status)
void onNewSearch ()
void OnStartCopy ()
 Notify the observer that the message has started to be copied.
void OnProgress (in PRUint32 aProgress, in PRUint32 aProgressMax)
 Notify the observer that progress as occurred for the message copy aProgress - aProgressMax -.
void SetMessageKey (in PRUint32 aKey)
 Setting newly created message key.
void GetMessageId (in nsCString aMessageId)
 Getting the file message message ID.
void OnStopCopy (in nsresult aStatus)
 Notify the observer that the message copied operation has completed.

Protected Member Functions

nsresult RunNextFilter ()
nsresult ApplyFilter ()
nsresult OnEndExecution (nsresult executionStatus)
PRBool ContinueExecutionPrompt ()
nsresult DisplayConfirmationPrompt (nsIMsgWindow *msgWindow, const PRUnichar *confirmString, PRBool *confirmed)

Protected Attributes

nsCOMPtr< nsIMsgWindowm_msgWindow
nsCOMPtr< nsIMsgFilterListm_filters
nsCOMPtr< nsISupportsArraym_folders
nsCOMPtr< nsIMsgFolderm_curFolder
nsCOMPtr< nsIMsgDatabasem_curFolderDB
nsCOMPtr< nsIMsgFilterm_curFilter
PRUint32 m_curFilterIndex
PRUint32 m_curFolderIndex
PRUint32 m_numFilters
PRUint32 m_numFolders
nsMsgKeyArray m_searchHits
nsCOMPtr< nsISupportsArraym_searchHitHdrs
nsCOMPtr< nsIMsgSearchSessionm_searchSession

Detailed Description

Definition at line 322 of file nsMsgFilterService.cpp.


Constructor & Destructor Documentation

Definition at line 356 of file nsMsgFilterService.cpp.

{
  m_curFilterIndex = m_curFolderIndex = 0;
  m_msgWindow = aMsgWindow;
  m_filters = aFilterList;
  m_folders = aFolderList;
  m_filters->GetFilterCount(&m_numFilters);
  m_folders->Count(&m_numFolders);

  NS_ADDREF(this); // we own ourselves, and will release ourselves when execution is done.

  NS_NewISupportsArray(getter_AddRefs(m_searchHitHdrs));
}

Here is the call graph for this function:

Definition at line 370 of file nsMsgFilterService.cpp.

{
}

Member Function Documentation

Definition at line 427 of file nsMsgFilterService.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 489 of file nsMsgFilterService.cpp.

{
  nsresult rv = NS_OK;
  if (m_curFilter && m_curFolder)
  {
    // we're going to log the filter actions before firing them because some actions are async
    PRBool loggingEnabled = PR_FALSE;
    if (m_filters)
      (void)m_filters->GetLoggingEnabled(&loggingEnabled);

    nsCOMPtr<nsISupportsArray> actionList;
    rv = NS_NewISupportsArray(getter_AddRefs(actionList));
    NS_ENSURE_SUCCESS(rv, rv);
    rv = m_curFilter->GetSortedActionList(actionList);
    NS_ENSURE_SUCCESS(rv, rv);
    PRUint32 numActions;
    actionList->Count(&numActions);
    PRBool applyMoreActions = PR_TRUE;

    for (PRUint32 actionIndex =0; actionIndex < numActions && applyMoreActions; actionIndex++)
    {
      nsCOMPtr<nsIMsgRuleAction> filterAction;
      actionList->QueryElementAt(actionIndex, NS_GET_IID(nsIMsgRuleAction), (void **)getter_AddRefs(filterAction));
      nsMsgRuleActionType actionType;
      if (filterAction)
        filterAction->GetType(&actionType);
      else
        continue;
      
      nsXPIDLCString actionTargetFolderUri;
      if (actionType == nsMsgFilterAction::MoveToFolder ||
          actionType == nsMsgFilterAction::CopyToFolder)
      {
        filterAction->GetTargetFolderUri(getter_Copies(actionTargetFolderUri));
        if (actionTargetFolderUri.IsEmpty())
        {
          NS_ASSERTION(PR_FALSE, "actionTargetFolderUri is empty");
          continue;
        }
      }

      if (loggingEnabled) 
      {
          for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
          {
            nsCOMPtr <nsIMsgDBHdr> msgHdr;
            m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
            if (msgHdr)
              (void)m_curFilter->LogRuleHit(filterAction, msgHdr); 
          }
      }
      // all actions that pass "this" as a listener in order to chain filter execution
      // when the action is finished need to return before reaching the bottom of this
      // routine, because we run the next filter at the end of this routine.
      switch (actionType)
      {
      case nsMsgFilterAction::Delete:
        // we can't pass ourselves in as a copy service listener because the copy service
        // listener won't get called in several situations (e.g., the delete model is imap delete)
        // and we rely on the listener getting called to continue the filter application.
        // This means we're going to end up firing off the delete, and then subsequently 
        // issuing a search for the next filter, which will block until the delete finishes.
        m_curFolder->DeleteMessages(m_searchHitHdrs, m_msgWindow, PR_FALSE, PR_FALSE, nsnull, PR_FALSE /*allow Undo*/ );
        //if we are deleting then we couldn't care less about applying remaining filter actions
        applyMoreActions = PR_FALSE;
        break;
      case nsMsgFilterAction::MoveToFolder:
      case nsMsgFilterAction::CopyToFolder:
      {
        // if moving or copying to a different file, do it.
        nsXPIDLCString uri;
        rv = m_curFolder->GetURI(getter_Copies(uri));

        if ((const char*)actionTargetFolderUri &&
            nsCRT::strcmp(uri, actionTargetFolderUri))
        {
          nsCOMPtr<nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1",&rv);
          nsCOMPtr<nsIRDFResource> res;
          rv = rdf->GetResource(actionTargetFolderUri, getter_AddRefs(res));
          NS_ENSURE_SUCCESS(rv, rv);

          nsCOMPtr<nsIMsgFolder> destIFolder(do_QueryInterface(res, &rv));
          NS_ENSURE_SUCCESS(rv, rv);

          PRBool canFileMessages = PR_TRUE;
          nsCOMPtr<nsIMsgFolder> parentFolder;
          destIFolder->GetParent(getter_AddRefs(parentFolder));
          if (parentFolder)
            destIFolder->GetCanFileMessages(&canFileMessages);
          if (!parentFolder || !canFileMessages)
          {
            m_curFilter->SetEnabled(PR_FALSE);
            destIFolder->ThrowAlertMsg("filterDisabled",m_msgWindow);
            // we need to explicitly save the filter file.
            m_filters->SaveToDefaultFile();
            // In the case of applying multiple filters
            // we might want to remove the filter from the list, but 
            // that's a bit evil since we really don't know that we own
            // the list. Disabling it doesn't do a lot of good since
            // we still apply disabled filters. Currently, we don't
            // have any clients that apply filters to multiple folders,
            // so this might be the edge case of an edge case.
            return RunNextFilter();
          }
          nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
          if (copyService)
            return copyService->CopyMessages(m_curFolder, m_searchHitHdrs, destIFolder, actionType == nsMsgFilterAction::MoveToFolder, this, m_msgWindow, PR_FALSE);
        }
        //we have already moved the hdrs so we can't apply more actions
        if (actionType == nsMsgFilterAction::MoveToFolder)
          applyMoreActions = PR_FALSE;
      }
        
        break;
      case nsMsgFilterAction::MarkRead:
          // crud, no listener support here - we'll probably just need to go on and apply
          // the next filter, and, in the imap case, rely on multiple connection and url
          // queueing to stay out of trouble
          m_curFolder->MarkMessagesRead(m_searchHitHdrs, PR_TRUE);
        break;
      case nsMsgFilterAction::MarkFlagged:
        m_curFolder->MarkMessagesFlagged(m_searchHitHdrs, PR_TRUE);
        break;
      case nsMsgFilterAction::KillThread:
      case nsMsgFilterAction::WatchThread:
        {
          for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
          {
            nsCOMPtr <nsIMsgDBHdr> msgHdr;
            m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
            if (msgHdr)
            {
              nsCOMPtr <nsIMsgThread> msgThread;
              nsMsgKey threadKey;
              m_curFolderDB->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(msgThread));
              if (msgThread)
              {
                msgThread->GetThreadKey(&threadKey);
                if (actionType == nsMsgFilterAction::KillThread)
                  m_curFolderDB->MarkThreadIgnored(msgThread, threadKey, PR_TRUE, nsnull);
                else
                  m_curFolderDB->MarkThreadWatched(msgThread, threadKey, PR_TRUE, nsnull);
              }
            }
          }
        }
        break;
      case nsMsgFilterAction::ChangePriority:
          {
              nsMsgPriorityValue filterPriority;
              filterAction->GetPriority(&filterPriority);
              for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
              {
                nsCOMPtr <nsIMsgDBHdr> msgHdr;
                m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
                if (msgHdr)
                  msgHdr->SetPriority(filterPriority);
              }
          }
        break;
      case nsMsgFilterAction::Label:
        {
            nsMsgLabelValue filterLabel;
            filterAction->GetLabel(&filterLabel);
            m_curFolder->SetLabelForMessages(m_searchHitHdrs, filterLabel);
        }
        break;
      case nsMsgFilterAction::AddTag:
        {
            nsXPIDLCString keyword;
            filterAction->GetStrValue(getter_Copies(keyword));
            m_curFolder->AddKeywordsToMessages(m_searchHitHdrs, keyword.get());
        }
        break;
      case nsMsgFilterAction::JunkScore:
      {
        nsCAutoString junkScoreStr;
        PRInt32 junkScore;
        filterAction->GetJunkScore(&junkScore);
        junkScoreStr.AppendInt(junkScore);
        m_curFolder->SetJunkScoreForMessages(m_searchHitHdrs, junkScoreStr.get());
        break;
      }
      case nsMsgFilterAction::Forward:
        {
          nsXPIDLCString forwardTo;
          filterAction->GetStrValue(getter_Copies(forwardTo));
          nsCOMPtr <nsIMsgIncomingServer> server;
          rv = m_curFolder->GetServer(getter_AddRefs(server));
          NS_ENSURE_SUCCESS(rv, rv);
          if (!forwardTo.IsEmpty())
          {
            nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
            if (compService)
            {
              for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
              {
                nsCOMPtr <nsIMsgDBHdr> msgHdr;
                m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
                if (msgHdr)
                {
                  nsAutoString forwardStr;
                  forwardStr.AssignWithConversion(forwardTo.get());
                  rv = compService->ForwardMessage(forwardStr, msgHdr, m_msgWindow, server);
                }
              }
            }
          }
        }
        break;
      case nsMsgFilterAction::Reply:
        {
          nsXPIDLCString replyTemplateUri;
          filterAction->GetStrValue(getter_Copies(replyTemplateUri));
          nsCOMPtr <nsIMsgIncomingServer> server;
          rv = m_curFolder->GetServer(getter_AddRefs(server));
          NS_ENSURE_SUCCESS(rv, rv);
          if (!replyTemplateUri.IsEmpty())
          {
            nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
            if (compService)
            {
              for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
              {
                nsCOMPtr <nsIMsgDBHdr> msgHdr;
                m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
                if (msgHdr)
                  rv = compService->ReplyWithTemplate(msgHdr, replyTemplateUri, m_msgWindow, server);
              }
            }
          }
        }
        break;
      case nsMsgFilterAction::DeleteFromPop3Server:
        {
          nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_curFolder);
          if (localFolder)
          {
            // This action ignores the deleteMailLeftOnServer preference
            localFolder->MarkMsgsOnPop3Server(m_searchHitHdrs, POP3_FORCE_DEL);

            nsCOMPtr <nsISupportsArray> partialMsgs;
            // Delete the partial headers. They're useless now
            // that the server copy is being deleted.
            for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
            {
              nsCOMPtr <nsIMsgDBHdr> msgHdr;
              m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
              if (msgHdr)
              {
                PRUint32 flags;
                msgHdr->GetFlags(&flags);
                if (flags & MSG_FLAG_PARTIAL)
                {
                  if (!partialMsgs)
                    partialMsgs = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
                  NS_ENSURE_SUCCESS(rv, rv);
                  partialMsgs->AppendElement(msgHdr);
                }
              }
            }
            if (partialMsgs)
              m_curFolder->DeleteMessages(partialMsgs, m_msgWindow, PR_TRUE, PR_FALSE, nsnull, PR_FALSE);
          }
        }
        break;
      case nsMsgFilterAction::FetchBodyFromPop3Server:
        {
          nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_curFolder);
          if (localFolder)
          {
            nsCOMPtr<nsISupportsArray> messages = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
            NS_ENSURE_SUCCESS(rv, rv);
            for (PRUint32 msgIndex = 0; msgIndex < m_searchHits.GetSize(); msgIndex++)
            {
              nsCOMPtr <nsIMsgDBHdr> msgHdr;
              m_searchHitHdrs->QueryElementAt(msgIndex, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(msgHdr));
              if (msgHdr)
              {
                PRUint32 flags = 0;
                msgHdr->GetFlags(&flags);
                if (flags & MSG_FLAG_PARTIAL)
                {
                  nsCOMPtr<nsISupports> iSupports = do_QueryInterface(msgHdr);
                  messages->AppendElement(iSupports);
                }
              }
            }
            PRUint32 msgsToFetch;
            messages->Count(&msgsToFetch);
            if (msgsToFetch > 0)
              m_curFolder->DownloadMessagesForOffline(messages, m_msgWindow);
          }
        }
        break;
      default:
        break;
      }
    }
  }
  return RunNextFilter();
}

Here is the call graph for this function:

Definition at line 845 of file nsMsgFilterService.cpp.

{
  PRBool returnVal = PR_FALSE;
  nsresult rv;
  nsCOMPtr <nsIStringBundle> bundle;
  nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
  if (bundleService && NS_SUCCEEDED(rv))
    bundleService->CreateBundle("chrome://messenger/locale/filter.properties",
                                 getter_AddRefs(bundle));
  if (NS_SUCCEEDED(rv) && bundle)
  {
    nsXPIDLString filterName;
    m_curFilter->GetFilterName(getter_Copies(filterName));
    nsXPIDLString formatString;
    nsXPIDLString confirmText;
    const PRUnichar *formatStrings[] =
    {
      filterName
    };
    rv = bundle->FormatStringFromName(NS_LITERAL_STRING("continueFilterExecution").get(),
                                      formatStrings, 1, getter_Copies(confirmText));
    if (NS_SUCCEEDED(rv))
    {
      rv = DisplayConfirmationPrompt(m_msgWindow, confirmText, &returnVal);
    }
  }
  return returnVal;
}

Here is the call graph for this function:

nsresult nsMsgFilterAfterTheFact::DisplayConfirmationPrompt ( nsIMsgWindow msgWindow,
const PRUnichar confirmString,
PRBool confirmed 
) [protected]

Definition at line 874 of file nsMsgFilterService.cpp.

{
  nsresult rv=NS_OK;
  if (msgWindow)
  {
    nsCOMPtr <nsIDocShell> docShell;
    msgWindow->GetRootDocShell(getter_AddRefs(docShell));
    if (docShell)
    {
      nsCOMPtr<nsIPrompt> dialog(do_GetInterface(docShell));
      if (dialog && confirmString)
        dialog->Confirm(nsnull, confirmString, confirmed);
    }
  }
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Getting the file message message ID.

This method is taylored specifically for nsIMsgCopyService::CopyFileMessage() when saving Drafts/Templates. In order to work with imap server which doesn't support uidplus we have to use search comman to retrieve the key of newly created message. Message ID generated by the compose gurantee its uniqueness. aMessageId -

nsresult nsMsgFilterAfterTheFact::OnEndExecution ( nsresult  executionStatus) [protected]

Definition at line 375 of file nsMsgFilterService.cpp.

{
  if (m_searchSession)
    m_searchSession->UnregisterListener(this);

  if (m_filters)
    (void)m_filters->FlushLogIfNecessary();

  Release(); // release ourselves.
  return executionStatus;
}

Here is the caller graph for this function:

void nsIMsgCopyServiceListener::OnProgress ( in PRUint32  aProgress,
in PRUint32  aProgressMax 
) [inherited]

Notify the observer that progress as occurred for the message copy aProgress - aProgressMax -.

void nsIMsgSearchNotify::onSearchHit ( in nsIMsgDBHdr  header,
in nsIMsgFolder  folder 
) [inherited]

Notify the observer that the message has started to be copied.

This method is called only once, at the beginning of a message copyoperation.

Implemented in CopyListener.

Here is the caller graph for this function:

Notify the observer that the message copied operation has completed.

This method is called regardless of whether the the operation was successful. aStatus - indicate whether the operation was succeeded

void nsIUrlListener::OnStopRunningUrl ( in nsIURI  url,
in nsresult  aExitCode 
) [inherited]

Here is the caller graph for this function:

Definition at line 387 of file nsMsgFilterService.cpp.

{
  nsresult rv;
  if (m_curFilterIndex >= m_numFilters)
    return AdvanceToNextFolder();

  rv = m_filters->GetFilterAt(m_curFilterIndex++, getter_AddRefs(m_curFilter));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr <nsISupportsArray> searchTerms;
  rv = m_curFilter->GetSearchTerms(getter_AddRefs(searchTerms));
  NS_ENSURE_SUCCESS(rv, rv);
  if (m_searchSession)
    m_searchSession->UnregisterListener(this);
  m_searchSession = do_CreateInstance(NS_MSGSEARCHSESSION_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsMsgSearchScopeValue searchScope = nsMsgSearchScope::offlineMail;
  PRUint32 termCount;
  searchTerms->Count(&termCount);
  for (PRUint32 termIndex = 0; termIndex < termCount; termIndex++)
  {
    nsCOMPtr <nsIMsgSearchTerm> term;
    rv = searchTerms->QueryElementAt(termIndex, NS_GET_IID(nsIMsgSearchTerm), getter_AddRefs(term));
    NS_ENSURE_SUCCESS(rv, rv);
    rv = m_searchSession->AppendTerm(term);
    NS_ENSURE_SUCCESS(rv, rv);
  }
  m_searchSession->RegisterListener(this);

  rv = m_searchSession->AddScopeTerm(searchScope, m_curFolder);
  NS_ENSURE_SUCCESS(rv, rv);
  // it's possible that this error handling will need to be rearranged when mscott lands the UI for
  // doing filters based on sender in PAB, because we can't do that for IMAP. I believe appending the
  // search term will fail, or the Search itself will fail synchronously. In that case, we'll
  // have to ignore the filter, I believe. Ultimately, we'd like to re-work the search backend
  // so that it can do this.
  return m_searchSession->Search(m_msgWindow);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Setting newly created message key.

This method is taylored specifically for nsIMsgCopyService::CopyFileMessage() when saveing Drafts/Templates. We need to have a way to inform the client what's the key of the newly created message. aKey -


Member Data Documentation

Definition at line 344 of file nsMsgFilterService.cpp.

Definition at line 345 of file nsMsgFilterService.cpp.

Definition at line 342 of file nsMsgFilterService.cpp.

Definition at line 343 of file nsMsgFilterService.cpp.

Definition at line 346 of file nsMsgFilterService.cpp.

Definition at line 340 of file nsMsgFilterService.cpp.

Definition at line 341 of file nsMsgFilterService.cpp.

Definition at line 339 of file nsMsgFilterService.cpp.

Definition at line 347 of file nsMsgFilterService.cpp.

Definition at line 348 of file nsMsgFilterService.cpp.

Definition at line 350 of file nsMsgFilterService.cpp.

nsMsgKeyArray nsMsgFilterAfterTheFact::m_searchHits [protected]

Definition at line 349 of file nsMsgFilterService.cpp.

Definition at line 351 of file nsMsgFilterService.cpp.


The documentation for this class was generated from the following file: