diff options
Diffstat (limited to 'mailnews/base/src/nsSpamSettings.cpp')
-rw-r--r-- | mailnews/base/src/nsSpamSettings.cpp | 892 |
1 files changed, 892 insertions, 0 deletions
diff --git a/mailnews/base/src/nsSpamSettings.cpp b/mailnews/base/src/nsSpamSettings.cpp new file mode 100644 index 000000000..e8318b75a --- /dev/null +++ b/mailnews/base/src/nsSpamSettings.cpp @@ -0,0 +1,892 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsSpamSettings.h" +#include "nsIFile.h" +#include "plstr.h" +#include "prmem.h" +#include "nsIMsgHdr.h" +#include "nsNetUtil.h" +#include "nsIMsgFolder.h" +#include "nsMsgUtils.h" +#include "nsMsgFolderFlags.h" +#include "nsImapCore.h" +#include "nsIImapIncomingServer.h" +#include "nsIRDFService.h" +#include "nsIRDFResource.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIStringBundle.h" +#include "nsDateTimeFormatCID.h" +#include "mozilla/Services.h" +#include "mozilla/mailnews/MimeHeaderParser.h" +#include "nsIArray.h" +#include "nsArrayUtils.h" +#include "nsMailDirServiceDefs.h" +#include "nsDirectoryServiceUtils.h" +#include "nsDirectoryServiceDefs.h" +#include "nsISimpleEnumerator.h" +#include "nsIDirectoryEnumerator.h" +#include "nsAbBaseCID.h" +#include "nsIAbManager.h" +#include "nsIMsgAccountManager.h" +#include "nsMsgBaseCID.h" + +using namespace mozilla::mailnews; + +nsSpamSettings::nsSpamSettings() +{ + mLevel = 0; + mMoveOnSpam = false; + mMoveTargetMode = nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT; + mPurge = false; + mPurgeInterval = 14; // 14 days + + mServerFilterTrustFlags = 0; + + mUseWhiteList = false; + mUseServerFilter = false; + + nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mLogFile)); + if (NS_SUCCEEDED(rv)) + mLogFile->Append(NS_LITERAL_STRING("junklog.html")); +} + +nsSpamSettings::~nsSpamSettings() +{ +} + +NS_IMPL_ISUPPORTS(nsSpamSettings, nsISpamSettings, nsIUrlListener) + +NS_IMETHODIMP +nsSpamSettings::GetLevel(int32_t *aLevel) +{ + NS_ENSURE_ARG_POINTER(aLevel); + *aLevel = mLevel; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetLevel(int32_t aLevel) +{ + NS_ASSERTION((aLevel >= 0 && aLevel <= 100), "bad level"); + mLevel = aLevel; + return NS_OK; +} + +NS_IMETHODIMP +nsSpamSettings::GetMoveTargetMode(int32_t *aMoveTargetMode) +{ + NS_ENSURE_ARG_POINTER(aMoveTargetMode); + *aMoveTargetMode = mMoveTargetMode; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetMoveTargetMode(int32_t aMoveTargetMode) +{ + NS_ASSERTION((aMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_FOLDER || aMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT), "bad move target mode"); + mMoveTargetMode = aMoveTargetMode; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::GetManualMark(bool *aManualMark) +{ + NS_ENSURE_ARG_POINTER(aManualMark); + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + return prefBranch->GetBoolPref("mail.spam.manualMark", aManualMark); +} + +NS_IMETHODIMP nsSpamSettings::GetManualMarkMode(int32_t *aManualMarkMode) +{ + NS_ENSURE_ARG_POINTER(aManualMarkMode); + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + return prefBranch->GetIntPref("mail.spam.manualMarkMode", aManualMarkMode); +} + +NS_IMETHODIMP nsSpamSettings::GetLoggingEnabled(bool *aLoggingEnabled) +{ + NS_ENSURE_ARG_POINTER(aLoggingEnabled); + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + return prefBranch->GetBoolPref("mail.spam.logging.enabled", aLoggingEnabled); +} + +NS_IMETHODIMP nsSpamSettings::GetMarkAsReadOnSpam(bool *aMarkAsReadOnSpam) +{ + NS_ENSURE_ARG_POINTER(aMarkAsReadOnSpam); + nsresult rv; + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + return prefBranch->GetBoolPref("mail.spam.markAsReadOnSpam", aMarkAsReadOnSpam); +} + +NS_IMPL_GETSET(nsSpamSettings, MoveOnSpam, bool, mMoveOnSpam) +NS_IMPL_GETSET(nsSpamSettings, Purge, bool, mPurge) +NS_IMPL_GETSET(nsSpamSettings, UseWhiteList, bool, mUseWhiteList) +NS_IMPL_GETSET(nsSpamSettings, UseServerFilter, bool, mUseServerFilter) + +NS_IMETHODIMP nsSpamSettings::GetWhiteListAbURI(char * *aWhiteListAbURI) +{ + NS_ENSURE_ARG_POINTER(aWhiteListAbURI); + *aWhiteListAbURI = ToNewCString(mWhiteListAbURI); + return NS_OK; +} +NS_IMETHODIMP nsSpamSettings::SetWhiteListAbURI(const char * aWhiteListAbURI) +{ + mWhiteListAbURI = aWhiteListAbURI; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::GetActionTargetAccount(char * *aActionTargetAccount) +{ + NS_ENSURE_ARG_POINTER(aActionTargetAccount); + *aActionTargetAccount = ToNewCString(mActionTargetAccount); + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetActionTargetAccount(const char * aActionTargetAccount) +{ + mActionTargetAccount = aActionTargetAccount; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::GetActionTargetFolder(char * *aActionTargetFolder) +{ + NS_ENSURE_ARG_POINTER(aActionTargetFolder); + *aActionTargetFolder = ToNewCString(mActionTargetFolder); + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetActionTargetFolder(const char * aActionTargetFolder) +{ + mActionTargetFolder = aActionTargetFolder; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::GetPurgeInterval(int32_t *aPurgeInterval) +{ + NS_ENSURE_ARG_POINTER(aPurgeInterval); + *aPurgeInterval = mPurgeInterval; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetPurgeInterval(int32_t aPurgeInterval) +{ + NS_ASSERTION(aPurgeInterval >= 0, "bad purge interval"); + mPurgeInterval = aPurgeInterval; + return NS_OK; +} + +NS_IMETHODIMP +nsSpamSettings::SetLogStream(nsIOutputStream *aLogStream) +{ + // if there is a log stream already, close it + if (mLogStream) { + // will flush + nsresult rv = mLogStream->Close(); + NS_ENSURE_SUCCESS(rv,rv); + } + + mLogStream = aLogStream; + return NS_OK; +} + +#define LOG_HEADER "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<style type=\"text/css\">body{font-family:Consolas,\"Lucida Console\",Monaco,\"Courier New\",Courier,monospace;font-size:small}</style>\n</head>\n<body>\n" +#define LOG_HEADER_LEN (strlen(LOG_HEADER)) + +NS_IMETHODIMP +nsSpamSettings::GetLogStream(nsIOutputStream **aLogStream) +{ + NS_ENSURE_ARG_POINTER(aLogStream); + + nsresult rv; + + if (!mLogStream) { + // append to the end of the log file + rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mLogStream), + mLogFile, + PR_CREATE_FILE | PR_WRONLY | PR_APPEND, + 0600); + NS_ENSURE_SUCCESS(rv, rv); + + int64_t fileSize; + rv = mLogFile->GetFileSize(&fileSize); + NS_ENSURE_SUCCESS(rv, rv); + + // write the header at the start + if (fileSize == 0) + { + uint32_t writeCount; + + rv = mLogStream->Write(LOG_HEADER, LOG_HEADER_LEN, &writeCount); + NS_ENSURE_SUCCESS(rv, rv); + NS_ASSERTION(writeCount == LOG_HEADER_LEN, "failed to write out log header"); + } + } + + NS_ADDREF(*aLogStream = mLogStream); + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::Initialize(nsIMsgIncomingServer *aServer) +{ + NS_ENSURE_ARG_POINTER(aServer); + nsresult rv; + int32_t spamLevel; + rv = aServer->GetIntValue("spamLevel", &spamLevel); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetLevel(spamLevel); + NS_ENSURE_SUCCESS(rv, rv); + + bool moveOnSpam; + rv = aServer->GetBoolValue("moveOnSpam", &moveOnSpam); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetMoveOnSpam(moveOnSpam); + NS_ENSURE_SUCCESS(rv, rv); + + int32_t moveTargetMode; + rv = aServer->GetIntValue("moveTargetMode", &moveTargetMode); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetMoveTargetMode(moveTargetMode); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString spamActionTargetAccount; + rv = aServer->GetCharValue("spamActionTargetAccount", spamActionTargetAccount); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetActionTargetAccount(spamActionTargetAccount.get()); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString spamActionTargetFolder; + rv = aServer->GetCharValue("spamActionTargetFolder", spamActionTargetFolder); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetActionTargetFolder(spamActionTargetFolder.get()); + NS_ENSURE_SUCCESS(rv, rv); + + bool useWhiteList; + rv = aServer->GetBoolValue("useWhiteList", &useWhiteList); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetUseWhiteList(useWhiteList); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString whiteListAbURI; + rv = aServer->GetCharValue("whiteListAbURI", whiteListAbURI); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetWhiteListAbURI(whiteListAbURI.get()); + NS_ENSURE_SUCCESS(rv, rv); + + bool purgeSpam; + rv = aServer->GetBoolValue("purgeSpam", &purgeSpam); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetPurge(purgeSpam); + NS_ENSURE_SUCCESS(rv, rv); + + int32_t purgeSpamInterval; + rv = aServer->GetIntValue("purgeSpamInterval", &purgeSpamInterval); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetPurgeInterval(purgeSpamInterval); + NS_ENSURE_SUCCESS(rv, rv); + + bool useServerFilter; + rv = aServer->GetBoolValue("useServerFilter", &useServerFilter); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetUseServerFilter(useServerFilter); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString serverFilterName; + rv = aServer->GetCharValue("serverFilterName", serverFilterName); + if (NS_SUCCEEDED(rv)) + SetServerFilterName(serverFilterName); + int32_t serverFilterTrustFlags = 0; + rv = aServer->GetIntValue("serverFilterTrustFlags", &serverFilterTrustFlags); + NS_ENSURE_SUCCESS(rv, rv); + rv = SetServerFilterTrustFlags(serverFilterTrustFlags); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + if (prefBranch) + prefBranch->GetCharPref("mail.trusteddomains", + getter_Copies(mTrustedMailDomains)); + + mWhiteListDirArray.Clear(); + if (!mWhiteListAbURI.IsEmpty()) + { + nsCOMPtr<nsIAbManager> abManager(do_GetService(NS_ABMANAGER_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsTArray<nsCString> whiteListArray; + ParseString(mWhiteListAbURI, ' ', whiteListArray); + + for (uint32_t index = 0; index < whiteListArray.Length(); index++) + { + nsCOMPtr<nsIAbDirectory> directory; + rv = abManager->GetDirectory(whiteListArray[index], + getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + if (directory) + mWhiteListDirArray.AppendObject(directory); + } + } + + // the next two preferences affect whether we try to whitelist our own + // address or domain. Spammers send emails with spoofed from address matching + // either the email address of the recipient, or the recipient's domain, + // hoping to get whitelisted. + // + // The terms to describe this get wrapped up in chains of negatives. A full + // definition of the boolean inhibitWhiteListingIdentityUser is "Suppress address + // book whitelisting if the sender matches an identity's email address" + + rv = aServer->GetBoolValue("inhibitWhiteListingIdentityUser", + &mInhibitWhiteListingIdentityUser); + NS_ENSURE_SUCCESS(rv, rv); + rv = aServer->GetBoolValue("inhibitWhiteListingIdentityDomain", + &mInhibitWhiteListingIdentityDomain); + NS_ENSURE_SUCCESS(rv, rv); + + // collect lists of identity users if needed + if (mInhibitWhiteListingIdentityDomain || mInhibitWhiteListingIdentityUser) + { + nsCOMPtr<nsIMsgAccountManager> + accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIMsgAccount> account; + rv = accountManager->FindAccountForServer(aServer, getter_AddRefs(account)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString accountKey; + if (account) + account->GetKey(accountKey); + + // Loop through all accounts, adding emails from this account, as well as + // from any accounts that defer to this account. + mEmails.Clear(); + nsCOMPtr<nsIArray> accounts; + rv = accountManager->GetAccounts(getter_AddRefs(accounts)); + NS_ENSURE_SUCCESS(rv, rv); + uint32_t accountCount = 0; + if (account && accounts) // no sense scanning accounts if we've nothing to match + accounts->GetLength(&accountCount); + + for (uint32_t i = 0; i < accountCount; i++) + { + nsCOMPtr<nsIMsgAccount> loopAccount(do_QueryElementAt(accounts, i)); + if (!loopAccount) + continue; + nsAutoCString loopAccountKey; + loopAccount->GetKey(loopAccountKey); + nsCOMPtr<nsIMsgIncomingServer> loopServer; + loopAccount->GetIncomingServer(getter_AddRefs(loopServer)); + nsAutoCString deferredToAccountKey; + if (loopServer) + loopServer->GetCharValue("deferred_to_account", deferredToAccountKey); + + // Add the emails for any account that defers to this one, or for the + // account itself. + if (accountKey.Equals(deferredToAccountKey) || accountKey.Equals(loopAccountKey)) + { + nsCOMPtr<nsIArray> identities; + loopAccount->GetIdentities(getter_AddRefs(identities)); + if (!identities) + continue; + uint32_t identityCount = 0; + identities->GetLength(&identityCount); + for (uint32_t j = 0; j < identityCount; ++j) + { + nsCOMPtr<nsIMsgIdentity> identity(do_QueryElementAt(identities, j, &rv)); + if (NS_FAILED(rv) || !identity) + continue; + nsAutoCString email; + identity->GetEmail(email); + if (!email.IsEmpty()) + mEmails.AppendElement(email); + } + } + } + } + + return UpdateJunkFolderState(); +} + +nsresult nsSpamSettings::UpdateJunkFolderState() +{ + nsresult rv; + + // if the spam folder uri changed on us, we need to unset the junk flag + // on the old spam folder + nsCString newJunkFolderURI; + rv = GetSpamFolderURI(getter_Copies(newJunkFolderURI)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!mCurrentJunkFolderURI.IsEmpty() && !mCurrentJunkFolderURI.Equals(newJunkFolderURI)) + { + nsCOMPtr<nsIMsgFolder> oldJunkFolder; + rv = GetExistingFolder(mCurrentJunkFolderURI, getter_AddRefs(oldJunkFolder)); + if (NS_SUCCEEDED(rv) && oldJunkFolder) + { + // remove the nsMsgFolderFlags::Junk on the old junk folder + // XXX TODO + // JUNK MAIL RELATED + // (in ClearFlag?) we need to make sure that this folder + // is not the junk folder for another account + // the same goes for set flag. have fun with all that. + oldJunkFolder->ClearFlag(nsMsgFolderFlags::Junk); + } + } + + mCurrentJunkFolderURI = newJunkFolderURI; + + // only try to create the junk folder if we are moving junk + // and we have a non-empty uri + if (mMoveOnSpam && !mCurrentJunkFolderURI.IsEmpty()) { + // as the url listener, the spam settings will set the nsMsgFolderFlags::Junk folder flag + // on the junk mail folder, after it is created + rv = GetOrCreateFolder(mCurrentJunkFolderURI, this); + } + + return rv; +} + +NS_IMETHODIMP nsSpamSettings::Clone(nsISpamSettings *aSpamSettings) +{ + NS_ENSURE_ARG_POINTER(aSpamSettings); + + nsresult rv = aSpamSettings->GetUseWhiteList(&mUseWhiteList); + NS_ENSURE_SUCCESS(rv,rv); + + (void)aSpamSettings->GetMoveOnSpam(&mMoveOnSpam); + (void)aSpamSettings->GetPurge(&mPurge); + (void)aSpamSettings->GetUseServerFilter(&mUseServerFilter); + + rv = aSpamSettings->GetPurgeInterval(&mPurgeInterval); + NS_ENSURE_SUCCESS(rv,rv); + + rv = aSpamSettings->GetLevel(&mLevel); + NS_ENSURE_SUCCESS(rv,rv); + + rv = aSpamSettings->GetMoveTargetMode(&mMoveTargetMode); + NS_ENSURE_SUCCESS(rv,rv); + + nsCString actionTargetAccount; + rv = aSpamSettings->GetActionTargetAccount(getter_Copies(actionTargetAccount)); + NS_ENSURE_SUCCESS(rv,rv); + mActionTargetAccount = actionTargetAccount; + + nsCString actionTargetFolder; + rv = aSpamSettings->GetActionTargetFolder(getter_Copies(actionTargetFolder)); + NS_ENSURE_SUCCESS(rv,rv); + mActionTargetFolder = actionTargetFolder; + + nsCString whiteListAbURI; + rv = aSpamSettings->GetWhiteListAbURI(getter_Copies(whiteListAbURI)); + NS_ENSURE_SUCCESS(rv,rv); + mWhiteListAbURI = whiteListAbURI; + + aSpamSettings->GetServerFilterName(mServerFilterName); + aSpamSettings->GetServerFilterTrustFlags(&mServerFilterTrustFlags); + + return rv; +} + +NS_IMETHODIMP nsSpamSettings::GetSpamFolderURI(char **aSpamFolderURI) +{ + NS_ENSURE_ARG_POINTER(aSpamFolderURI); + + if (mMoveTargetMode == nsISpamSettings::MOVE_TARGET_MODE_FOLDER) + return GetActionTargetFolder(aSpamFolderURI); + + // if the mode is nsISpamSettings::MOVE_TARGET_MODE_ACCOUNT + // the spam folder URI = account uri + "/Junk" + nsCString folderURI; + nsresult rv = GetActionTargetAccount(getter_Copies(folderURI)); + NS_ENSURE_SUCCESS(rv,rv); + + // we might be trying to get the old spam folder uri + // in order to clear the flag + // if we didn't have one, bail out. + if (folderURI.IsEmpty()) + return NS_OK; + + nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIRDFResource> folderResource; + rv = rdf->GetResource(folderURI, getter_AddRefs(folderResource)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(folderResource); + if (!folder) + return NS_ERROR_UNEXPECTED; + + nsCOMPtr <nsIMsgIncomingServer> server; + rv = folder->GetServer(getter_AddRefs(server)); + NS_ENSURE_SUCCESS(rv,rv); + + // see nsMsgFolder::SetPrettyName() for where the pretty name is set. + + // Check for an existing junk folder - this will do a case-insensitive + // search by URI - if we find a junk folder, use its URI. + nsCOMPtr<nsIMsgFolder> junkFolder; + folderURI.Append("/Junk"); + if (NS_SUCCEEDED(server->GetMsgFolderFromURI(nullptr, folderURI, + getter_AddRefs(junkFolder))) && + junkFolder) + junkFolder->GetURI(folderURI); + + // XXX todo + // better not to make base depend in imap + // but doing it here, like in nsMsgCopy.cpp + // one day, we'll fix this (and nsMsgCopy.cpp) to use GetMsgFolderFromURI() + nsCOMPtr<nsIImapIncomingServer> imapServer = do_QueryInterface(server); + if (imapServer) { + // Make sure an specific IMAP folder has correct personal namespace + // see bug #197043 + nsCString folderUriWithNamespace; + (void)imapServer->GetUriWithNamespacePrefixIfNecessary(kPersonalNamespace, folderURI, + folderUriWithNamespace); + if (!folderUriWithNamespace.IsEmpty()) + folderURI = folderUriWithNamespace; + } + + *aSpamFolderURI = ToNewCString(folderURI); + if (!*aSpamFolderURI) + return NS_ERROR_OUT_OF_MEMORY; + else + return rv; +} + +NS_IMETHODIMP nsSpamSettings::GetServerFilterName(nsACString &aFilterName) +{ + aFilterName = mServerFilterName; + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::SetServerFilterName(const nsACString &aFilterName) +{ + mServerFilterName = aFilterName; + mServerFilterFile = nullptr; // clear out our stored location value + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::GetServerFilterFile(nsIFile ** aFile) +{ + NS_ENSURE_ARG_POINTER(aFile); + if (!mServerFilterFile) + { + nsresult rv; + nsAutoCString serverFilterFileName; + GetServerFilterName(serverFilterFileName); + serverFilterFileName.Append(".sfd"); + + nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // Walk through the list of isp directories + nsCOMPtr<nsISimpleEnumerator> ispDirectories; + rv = dirSvc->Get(ISP_DIRECTORY_LIST, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(ispDirectories)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + nsCOMPtr<nsIFile> file; + while (NS_SUCCEEDED(ispDirectories->HasMoreElements(&hasMore)) && hasMore) + { + nsCOMPtr<nsISupports> elem; + ispDirectories->GetNext(getter_AddRefs(elem)); + file = do_QueryInterface(elem); + + if (file) + { + // append our desired leaf name then test to see if the file exists. If it does, we've found + // mServerFilterFile. + file->AppendNative(serverFilterFileName); + bool exists; + if (NS_SUCCEEDED(file->Exists(&exists)) && exists) + { + file.swap(mServerFilterFile); + break; + } + } // if file + } // until we find the location of mServerFilterName + } // if we haven't already stored mServerFilterFile + + NS_IF_ADDREF(*aFile = mServerFilterFile); + return NS_OK; +} + + +NS_IMPL_GETSET(nsSpamSettings, ServerFilterTrustFlags, int32_t, mServerFilterTrustFlags) + +#define LOG_ENTRY_START_TAG "<p>\n" +#define LOG_ENTRY_START_TAG_LEN (strlen(LOG_ENTRY_START_TAG)) +#define LOG_ENTRY_END_TAG "</p>\n" +#define LOG_ENTRY_END_TAG_LEN (strlen(LOG_ENTRY_END_TAG)) +// Does this need to be localizable? +#define LOG_ENTRY_TIMESTAMP "[$S] " + +NS_IMETHODIMP nsSpamSettings::LogJunkHit(nsIMsgDBHdr *aMsgHdr, bool aMoveMessage) +{ + bool loggingEnabled; + nsresult rv = GetLoggingEnabled(&loggingEnabled); + NS_ENSURE_SUCCESS(rv,rv); + + if (!loggingEnabled) + return NS_OK; + + PRTime date; + + nsString authorValue; + nsString subjectValue; + nsString dateValue; + + (void)aMsgHdr->GetDate(&date); + PRExplodedTime exploded; + PR_ExplodeTime(date, PR_LocalTimeParameters, &exploded); + + if (!mDateFormatter) + { + mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + if (!mDateFormatter) + { + return NS_ERROR_FAILURE; + } + } + mDateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, + kTimeFormatSeconds, &exploded, + dateValue); + + (void)aMsgHdr->GetMime2DecodedAuthor(authorValue); + (void)aMsgHdr->GetMime2DecodedSubject(subjectValue); + + nsCString buffer; + // this is big enough to hold a log entry. + // do this so we avoid growing and copying as we append to the log. +#ifdef MOZILLA_INTERNAL_API + buffer.SetCapacity(512); +#endif + + nsCOMPtr<nsIStringBundleService> bundleService = + mozilla::services::GetStringBundleService(); + NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED); + + nsCOMPtr<nsIStringBundle> bundle; + rv = bundleService->CreateBundle("chrome://messenger/locale/filter.properties", + getter_AddRefs(bundle)); + NS_ENSURE_SUCCESS(rv, rv); + + const char16_t *junkLogDetectFormatStrings[3] = { authorValue.get(), subjectValue.get(), dateValue.get() }; + nsString junkLogDetectStr; + rv = bundle->FormatStringFromName( + u"junkLogDetectStr", + junkLogDetectFormatStrings, 3, + getter_Copies(junkLogDetectStr)); + NS_ENSURE_SUCCESS(rv, rv); + + buffer += NS_ConvertUTF16toUTF8(junkLogDetectStr); + buffer += "\n"; + + if (aMoveMessage) { + nsCString msgId; + aMsgHdr->GetMessageId(getter_Copies(msgId)); + + nsCString junkFolderURI; + rv = GetSpamFolderURI(getter_Copies(junkFolderURI)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ConvertASCIItoUTF16 msgIdValue(msgId); + NS_ConvertASCIItoUTF16 junkFolderURIValue(junkFolderURI); + + const char16_t *logMoveFormatStrings[2] = { msgIdValue.get(), junkFolderURIValue.get() }; + nsString logMoveStr; + rv = bundle->FormatStringFromName( + u"logMoveStr", + logMoveFormatStrings, 2, + getter_Copies(logMoveStr)); + NS_ENSURE_SUCCESS(rv, rv); + + buffer += NS_ConvertUTF16toUTF8(logMoveStr); + buffer += "\n"; + } + + return LogJunkString(buffer.get()); +} + +NS_IMETHODIMP nsSpamSettings::LogJunkString(const char *string) +{ + bool loggingEnabled; + nsresult rv = GetLoggingEnabled(&loggingEnabled); + NS_ENSURE_SUCCESS(rv,rv); + + if (!loggingEnabled) + return NS_OK; + + nsString dateValue; + PRExplodedTime exploded; + PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &exploded); + + if (!mDateFormatter) + { + mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + if (!mDateFormatter) + { + return NS_ERROR_FAILURE; + } + } + mDateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, + kTimeFormatSeconds, &exploded, + dateValue); + + nsCString timestampString(LOG_ENTRY_TIMESTAMP); + MsgReplaceSubstring(timestampString, "$S", NS_ConvertUTF16toUTF8(dateValue).get()); + + nsCOMPtr <nsIOutputStream> logStream; + rv = GetLogStream(getter_AddRefs(logStream)); + NS_ENSURE_SUCCESS(rv,rv); + + uint32_t writeCount; + + rv = logStream->Write(LOG_ENTRY_START_TAG, LOG_ENTRY_START_TAG_LEN, &writeCount); + NS_ENSURE_SUCCESS(rv,rv); + NS_ASSERTION(writeCount == LOG_ENTRY_START_TAG_LEN, "failed to write out start log tag"); + + rv = logStream->Write(timestampString.get(), timestampString.Length(), &writeCount); + NS_ENSURE_SUCCESS(rv,rv); + NS_ASSERTION(writeCount == timestampString.Length(), "failed to write out timestamp"); + + // HTML-escape the log for security reasons. + // We don't want someone to send us a message with a subject with + // HTML tags, especially <script>. + char *escapedBuffer = MsgEscapeHTML(string); + if (!escapedBuffer) + return NS_ERROR_OUT_OF_MEMORY; + + uint32_t escapedBufferLen = strlen(escapedBuffer); + rv = logStream->Write(escapedBuffer, escapedBufferLen, &writeCount); + PR_Free(escapedBuffer); + NS_ENSURE_SUCCESS(rv,rv); + NS_ASSERTION(writeCount == escapedBufferLen, "failed to write out log hit"); + + rv = logStream->Write(LOG_ENTRY_END_TAG, LOG_ENTRY_END_TAG_LEN, &writeCount); + NS_ENSURE_SUCCESS(rv,rv); + NS_ASSERTION(writeCount == LOG_ENTRY_END_TAG_LEN, "failed to write out end log tag"); + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::OnStartRunningUrl(nsIURI* aURL) +{ + // do nothing + // all the action happens in OnStopRunningUrl() + return NS_OK; +} + +NS_IMETHODIMP nsSpamSettings::OnStopRunningUrl(nsIURI* aURL, nsresult exitCode) +{ + nsCString junkFolderURI; + nsresult rv = GetSpamFolderURI(getter_Copies(junkFolderURI)); + NS_ENSURE_SUCCESS(rv,rv); + + if (junkFolderURI.IsEmpty()) + return NS_ERROR_UNEXPECTED; + + // when we get here, the folder should exist. + nsCOMPtr <nsIMsgFolder> junkFolder; + rv = GetExistingFolder(junkFolderURI, getter_AddRefs(junkFolder)); + NS_ENSURE_SUCCESS(rv,rv); + if (!junkFolder) + return NS_ERROR_UNEXPECTED; + + rv = junkFolder->SetFlag(nsMsgFolderFlags::Junk); + NS_ENSURE_SUCCESS(rv,rv); + return rv; +} + +NS_IMETHODIMP nsSpamSettings::CheckWhiteList(nsIMsgDBHdr *aMsgHdr, bool *aResult) +{ + NS_ENSURE_ARG_POINTER(aMsgHdr); + NS_ENSURE_ARG_POINTER(aResult); + *aResult = false; // default in case of error or no whitelisting + + if (!mUseWhiteList || (!mWhiteListDirArray.Count() && + mTrustedMailDomains.IsEmpty())) + return NS_OK; + + // do per-message processing + + nsCString author; + aMsgHdr->GetAuthor(getter_Copies(author)); + + nsAutoCString authorEmailAddress; + ExtractEmail(EncodedHeader(author), authorEmailAddress); + + if (authorEmailAddress.IsEmpty()) + return NS_OK; + + // should we skip whitelisting for the identity email? + if (mInhibitWhiteListingIdentityUser) + { + for (uint32_t i = 0; i < mEmails.Length(); ++i) + { + if (mEmails[i].Equals(authorEmailAddress, nsCaseInsensitiveCStringComparator())) + return NS_OK; + } + } + + if (!mTrustedMailDomains.IsEmpty() || mInhibitWhiteListingIdentityDomain) + { + nsAutoCString domain; + int32_t atPos = authorEmailAddress.FindChar('@'); + if (atPos >= 0) + domain = Substring(authorEmailAddress, atPos + 1); + if (!domain.IsEmpty()) + { + if (!mTrustedMailDomains.IsEmpty() && + MsgHostDomainIsTrusted(domain, mTrustedMailDomains)) + { + *aResult = true; + return NS_OK; + } + + if (mInhibitWhiteListingIdentityDomain) + { + for (uint32_t i = 0; i < mEmails.Length(); ++i) + { + nsAutoCString identityDomain; + int32_t atPos = mEmails[i].FindChar('@'); + if (atPos >= 0) + { + identityDomain = Substring(mEmails[i], atPos + 1); + if (identityDomain.Equals(domain, nsCaseInsensitiveCStringComparator())) + return NS_OK; // don't whitelist + } + } + } + } + } + + if (mWhiteListDirArray.Count()) + { + nsCOMPtr<nsIAbCard> cardForAddress; + for (int32_t index = 0; + index < mWhiteListDirArray.Count() && !cardForAddress; + index++) + { + mWhiteListDirArray[index]->CardForEmailAddress(authorEmailAddress, + getter_AddRefs(cardForAddress)); + } + if (cardForAddress) + { + *aResult = true; + return NS_OK; + } + } + return NS_OK; // default return is false +} |