in mailnews/imap/src/nsImapMailFolder.cpp [604:836]
NS_IMETHODIMP nsImapMailFolder::UpdateFolderWithListener(
nsIMsgWindow* aMsgWindow, nsIUrlListener* aUrlListener) {
nsresult rv;
// If this is the inbox, filters will be applied. Otherwise, we test the
// inherited folder property "applyIncomingFilters" (which defaults to empty).
// If this inherited property has the string value "true", we will apply
// filters even if this is not the inbox folder.
nsCString applyIncomingFilters;
GetInheritedStringProperty("applyIncomingFilters", applyIncomingFilters);
m_applyIncomingFilters = applyIncomingFilters.EqualsLiteral("true");
nsCString folderName;
GetPrettyName(folderName);
MOZ_LOG(FILTERLOGMODULE, LogLevel::Debug,
("(Imap) nsImapMailFolder::UpdateFolderWithListener() on folder '%s'",
folderName.get()));
if (mFlags & nsMsgFolderFlags::Inbox || m_applyIncomingFilters) {
MOZ_LOG(FILTERLOGMODULE, LogLevel::Info,
("(Imap) Preparing filter run on folder '%s'", folderName.get()));
if (!m_filterList) {
rv = GetFilterList(aMsgWindow, getter_AddRefs(m_filterList));
if (NS_FAILED(rv)) {
MOZ_LOG(FILTERLOGMODULE, LogLevel::Error,
("(Imap) Loading of filter list failed"));
}
}
// if there's no msg window, but someone is updating the inbox, we're
// doing something biff-like, and may download headers, so make biff notify.
if (!aMsgWindow && mFlags & nsMsgFolderFlags::Inbox)
SetPerformingBiff(true);
}
if (m_filterList) {
nsCString listId;
m_filterList->GetListId(listId);
MOZ_LOG(FILTERLOGMODULE, LogLevel::Info,
("(Imap) Preparing filter list %s", listId.get()));
nsCOMPtr<nsIMsgIncomingServer> server;
rv = GetServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv, rv);
bool canFileMessagesOnServer = true;
rv = server->GetCanFileMessagesOnServer(&canFileMessagesOnServer);
// the mdn filter is for filing return receipts into the sent folder
// some servers (like AOL mail servers)
// can't file to the sent folder, so we don't add the filter for those
// servers
if (canFileMessagesOnServer) {
rv = server->ConfigureTemporaryFilters(m_filterList);
NS_ENSURE_SUCCESS(rv, rv);
}
// If a body filter is enabled for an offline folder, delay the filter
// application until after message has been downloaded.
m_filterListRequiresBody = false;
if (mFlags & nsMsgFolderFlags::Offline) {
nsCOMPtr<nsIMsgFilterService> filterService =
do_GetService("@mozilla.org/messenger/services/filters;1", &rv);
uint32_t filterCount = 0;
m_filterList->GetFilterCount(&filterCount);
for (uint32_t index = 0; index < filterCount && !m_filterListRequiresBody;
++index) {
nsCOMPtr<nsIMsgFilter> filter;
m_filterList->GetFilterAt(index, getter_AddRefs(filter));
if (!filter) continue;
nsMsgFilterTypeType filterType;
filter->GetFilterType(&filterType);
if (!(filterType & nsMsgFilterType::Incoming)) continue;
bool enabled = false;
filter->GetEnabled(&enabled);
if (!enabled) continue;
nsTArray<RefPtr<nsIMsgSearchTerm>> searchTerms;
filter->GetSearchTerms(searchTerms);
for (nsIMsgSearchTerm* term : searchTerms) {
nsMsgSearchAttribValue attrib;
rv = term->GetAttrib(&attrib);
NS_ENSURE_SUCCESS(rv, rv);
if (attrib == nsMsgSearchAttrib::Body)
m_filterListRequiresBody = true;
else if (attrib == nsMsgSearchAttrib::Custom) {
nsAutoCString customId;
rv = term->GetCustomId(customId);
nsCOMPtr<nsIMsgSearchCustomTerm> customTerm;
if (NS_SUCCEEDED(rv) && filterService)
rv = filterService->GetCustomTerm(customId,
getter_AddRefs(customTerm));
bool needsBody = false;
if (NS_SUCCEEDED(rv) && customTerm)
rv = customTerm->GetNeedsBody(&needsBody);
if (NS_SUCCEEDED(rv) && needsBody) m_filterListRequiresBody = true;
}
if (m_filterListRequiresBody) {
break;
}
}
// Also check if filter actions need the body, as this
// is supported in custom actions.
uint32_t numActions = 0;
filter->GetActionCount(&numActions);
for (uint32_t actionIndex = 0;
actionIndex < numActions && !m_filterListRequiresBody;
actionIndex++) {
nsCOMPtr<nsIMsgRuleAction> action;
rv = filter->GetActionAt(actionIndex, getter_AddRefs(action));
if (NS_FAILED(rv) || !action) continue;
nsCOMPtr<nsIMsgFilterCustomAction> customAction;
rv = action->GetCustomAction(getter_AddRefs(customAction));
if (NS_FAILED(rv) || !customAction) continue;
bool needsBody = false;
customAction->GetNeedsBody(&needsBody);
if (needsBody) m_filterListRequiresBody = true;
}
}
}
MOZ_LOG(FILTERLOGMODULE, LogLevel::Info,
("(Imap) Filters require the message body: %s",
(m_filterListRequiresBody ? "true" : "false")));
}
bool isServer;
rv = GetIsServer(&isServer);
if (NS_SUCCEEDED(rv) && isServer) {
if (!m_haveDiscoveredAllFolders) {
bool hasSubFolders = false;
GetHasSubFolders(&hasSubFolders);
if (!hasSubFolders) {
rv = CreateClientSubfolderInfo(
"Inbox"_ns, kOnlineHierarchySeparatorUnknown, 0, false);
NS_ENSURE_SUCCESS(rv, rv);
}
m_haveDiscoveredAllFolders = true;
}
}
rv = GetDatabase();
if (NS_FAILED(rv)) {
ThrowAlertMsg("errorGettingDB", aMsgWindow);
return rv;
}
bool hasOfflineEvents = false;
GetFlag(nsMsgFolderFlags::OfflineEvents, &hasOfflineEvents);
if (!WeAreOffline()) {
if (hasOfflineEvents) {
// hold a reference to the offline sync object. If ProcessNextOperation
// runs a url, a reference will be added to it. Otherwise, it will get
// destroyed when the refptr goes out of scope.
RefPtr<nsImapOfflineSync> goOnline = new nsImapOfflineSync();
goOnline->Init(aMsgWindow, this, this, false);
if (goOnline) {
// Save the listener, so when we arrive here again later (below)
// imapService->SelectFolder() gets the right listener.
m_urlListener = aUrlListener;
return goOnline->ProcessNextOperation();
}
}
}
// Check it we're password protecting the local store.
if (!PromptForMasterPasswordIfNecessary()) return NS_ERROR_FAILURE;
bool canOpenThisFolder = true;
GetCanOpenFolder(&canOpenThisFolder);
// Don't run select if we can't select the folder...
if (!m_urlRunning && canOpenThisFolder && !isServer) {
nsCOMPtr<nsIImapService> imapService =
do_GetService("@mozilla.org/messenger/imapservice;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Do a discovery in its own url if needed. Do before SELECT url.
nsCOMPtr<nsIImapHostSessionList> hostSession =
do_GetService(kCImapHostSessionList, &rv);
if (NS_SUCCEEDED(rv) && hostSession) {
bool foundMailboxesAlready = false;
nsCString serverKey;
GetServerKey(serverKey);
hostSession->GetHaveWeEverDiscoveredFoldersForHost(serverKey.get(),
foundMailboxesAlready);
if (!foundMailboxesAlready) {
bool discoveryInProgress = false;
// See if discovery in progress and not yet finished.
hostSession->GetDiscoveryForHostInProgress(serverKey.get(),
discoveryInProgress);
if (!discoveryInProgress) {
nsCOMPtr<nsIMsgFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder) {
rv = imapService->DiscoverAllFolders(rootFolder, this, aMsgWindow);
if (NS_SUCCEEDED(rv))
hostSession->SetDiscoveryForHostInProgress(serverKey.get(), true);
}
}
}
}
nsCOMPtr<nsIURI> url;
rv = imapService->SelectFolder(this, m_urlListener, aMsgWindow,
getter_AddRefs(url));
if (NS_SUCCEEDED(rv)) {
m_urlRunning = true;
m_updatingFolder = true;
}
if (url) {
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(url, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mailnewsUrl->RegisterListener(this);
m_urlListener = aUrlListener;
}
// Allow IMAP folder auto-compact to occur when online or offline.
if (aMsgWindow) AutoCompact(aMsgWindow);
if (rv == NS_MSG_ERROR_OFFLINE || rv == NS_BINDING_ABORTED) {
rv = NS_OK;
NotifyFolderEvent(kFolderLoaded);
}
} else {
// Tell the front end that the folder is loaded if we're not going to
// actually run a url.
if (!m_updatingFolder) // if we're already running an update url, we'll let
// that one send the folder loaded
NotifyFolderEvent(kFolderLoaded);
}
return rv;
}