pjs/lib/libmsg/msgprefs.cpp

1596 строки
43 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "msg.h"
#include "errcode.h"
#include "rosetta.h"
#include "msgprefs.h"
#include "msgprnot.h"
#include "imap.h"
#include "prefapi.h"
#include "msgmast.h"
#include "msgfinfo.h"
#include "proto.h" // for XP_FindSomeContext
#include "pmsgfilt.h"
#include "msgimap.h"
#include "imaphost.h"
extern "C"
{
#include "mkreg.h"
}
#include "ptrarray.h"
#ifdef XP_MAC
#include "Memory.h"
#include "Files.h"
#include "ufilemgr.h"
#include "uprefd.h"
#else
extern "C"
{
const char *FE_GetFolderDirectory(MWContext *c);
void NET_SetMailRelayHost(char *);
void NET_SetNewsHost(const char *);
}
#endif
extern "C"
{
extern int MK_MSG_MAIL_DIRECTORY_CHANGED;
extern int MK_MSG_SENT_L10N_NAME;
extern void MIME_ConformToStandard(XP_Bool conform_p);
extern int MK_MSG_UNABLE_TO_SAVE_DRAFT;
extern int MK_MSG_UNABLE_TO_SAVE_TEMPLATE;
}
// Notify listeners that something got changed. updateCode is an int16 instead of
// a MSG_PrefsNotify::NotifyCode because it was deemed a Bad Thing to include all of
// msgprnot.h just to pick up that definition.
void MSG_Prefs::Notify(int16 updateCode)
{
int i;
// if we are changing mail servers, trash cached path to imap databases
// m_IMAPdirectory will be reset by next reload call
if ((updateCode == MSG_PrefsNotify::MailServerType) || (updateCode == MSG_PrefsNotify::PopHost))
FREEIF(m_IMAPdirectory);
// Do the notification in such a way that deleted listeners don't
// foul up the notification for everyone else. (m_notifying affects
// the behavior of RemoveNotify so that it only NULLs deleted listeners.)
m_notifying = TRUE;
for (i = 0; i < m_numnotify ; i++)
{
if (m_notify[i])
m_notify[i]->NotifyPrefsChange((MSG_PrefsNotify::NotifyCode) updateCode);
}
m_notifying = FALSE;
// Clean up after nulled pointers.
for(i=(m_numnotify-1);i >= 0; i--)
{
if (! m_notify[i])
{
if (i == (m_numnotify-1))
// last element is null, keep decrementing the count
m_numnotify--;
else
// replace this null element with the last in the list
m_notify[i] = m_notify[--m_numnotify];
}
}
}
char *headerPrefNames[] =
{
"mail.identity.reply_to",
"mail.default_cc",
"mail.default_fcc",
"mail.imap_sentmail_path",
"news.default_cc",
"news.default_fcc",
"news.imap_sentmail_path",
};
enum headerPrefIndices
{
mail_identity_reply_to=0,
mail_default_cc,
mail_default_fcc, // this is a mess don't change order
mail_imap_sentmail_path,
news_default_cc,
news_default_fcc, // this is a mess don't change order
news_imap_sentmail_path,
num_of_header_prefs
};
void MSG_Prefs::PlatformFileToURLPath(const char *platformFile, char **result)
{
*result = NULL;
char *tmp = XP_PlatformFileToURL(platformFile);
XP_ASSERT(tmp && !strncmp(tmp, "file://", 7));
if (tmp && !strncmp(tmp, "file://", 7))
*result = XP_STRDUP(&(tmp[7]));
#ifdef XP_UNIX
if ( *result && **result == '~' ) {
char buf[1024];
char* home_dir = getenv("HOME");
char* tmp = (*result) + 1;
while ( *tmp == '/' )
tmp++;
/* trim trailing slashes in home_dir */
while ( (tmp = strrchr(home_dir, '/')) && tmp[1] == '\0' )
*tmp = '\0';
PR_snprintf(buf, sizeof(buf), "%s/%s", home_dir ? home_dir : "", tmp);
XP_FREE(*result);
*result = XP_STRDUP(buf);
}
#endif
FREEIF(tmp);
}
static XP_Bool ShouldSavePrefAsBinaryAlias(const char* prefname)
{
#ifdef XP_MAC
// Return TRUE if path names are saved as binary alias prefs (the default).
// Return FALSE for the URL cases, now saved as a string (new in Nova). These are IMAP
// fccs, and all drafts and all templates.
if (XP_STRCMP(prefname, "mail.imap_sentmail_path") == 0)
return FALSE; // URL
else if (XP_STRCMP(prefname, "news.imap_sentmail_path") == 0)
return FALSE; // URL
else if (XP_STRCMP(prefname, "mail.default_drafts") == 0)
return FALSE; // URL
else if (XP_STRCMP(prefname, "mail.default_templates") == 0)
return FALSE; // URL
return TRUE;
#else
return FALSE;
#endif // XP_MAC
}
int MSG_Prefs::GetXPDirPathPref(const char *prefName, XP_Bool /*expectFile*/, char **result)
{
int returnVal = PREF_NOERROR;
char *tmp = NULL;
*result = NULL; // in case we fail
if (ShouldSavePrefAsBinaryAlias(prefName))
{
returnVal = PREF_CopyPathPref(prefName, &tmp);
if (returnVal == PREF_NOERROR)
*result = tmp;
return returnVal;
}
returnVal = PREF_CopyCharPref(prefName, &tmp); // paths are strings elsewhere
if (returnVal == PREF_NOERROR)
{
// Convert pathname to an xp path.
if (XP_STRLEN(tmp) > 0 && NET_URL_Type(tmp) != IMAP_TYPE_URL &&
NET_URL_Type(tmp) != MAILBOX_TYPE_URL)
{
PlatformFileToURLPath(tmp,result);
XP_FREEIF(tmp);
}
else
*result = tmp;
}
return returnVal;
}
int MSG_Prefs::SetXPMailFilePref(const char* /*prefName*/, char *xpPath)
{
int returnVal = PREF_NOERROR;
if (NET_URL_Type(xpPath) != IMAP_TYPE_URL)
{
// ## mwelch 4.0b2 hack! Create the mail file if it doesn't already exist.
// Mail parent folder was created at app startup, so it is
// safe to assume that the parent directory exists.
char *platformPath = WH_FileName(xpPath, xpMailFolder);
XP_File fp = XP_FileOpen(xpPath, xpMailFolder, XP_FILE_APPEND_BIN);
if (fp)
XP_FileClose(fp);
XP_FREEIF(platformPath);
}
return returnVal;
} // MSG_Prefs::SetXPMailFilePref
void MSG_Prefs::SetMailNewsProfileAgeFlag(int32 flag, XP_Bool set /* = TRUE */)
{
// each 'trick' uses this function to register that it is done, but we do not
// want one trick to erase the completion of another.
int32 currentAge = 0;
PREF_GetIntPref("mailnews.profile_age",&currentAge);
if (set)
{
if (!(currentAge & flag))
PREF_SetIntPref("mailnews.profile_age",(currentAge | flag));
}
else
{
if (currentAge & flag)
PREF_SetIntPref("mailnews.profile_age",(currentAge | ~flag));
}
m_dirty = TRUE;
}
int32 MSG_Prefs::GetStartingMailNewsProfileAge()
{
Reload();
return m_startingMailNewsProfileAge;
}
void MSG_Prefs::Reload()
{
if (m_dirty)
{
// Temp vars we need to convey pref values.
int32 intPref;
char *strPref;
int prefError = PREF_NOERROR;
// Load in boolean prefs.
PREF_GetBoolPref("mail.fixed_width_messages", &m_plainText);
PREF_GetBoolPref("mail.auto_quote", &m_autoQuote);
PREF_GetBoolPref("news.show_pretty_names", &m_showPrettyNames);
PREF_GetBoolPref("news.notify.on", &m_newsNotifyOn);
PREF_GetBoolPref("mail.cc_self", &m_mailBccSelf);
PREF_GetBoolPref("news.cc_self", &m_newsBccSelf);
PREF_GetBoolPref("mail.wrap_long_lines", &m_wraplonglines);
HG63256
PREF_GetBoolPref("mail.inline_attachments", &m_noinline);
PREF_GetBoolPref("mail.prompt_purge_threshhold", &m_purgeThreshholdEnabled); //Ask about compacting folders
m_noinline = !m_noinline;
// Load in int/enum prefs.
intPref = (int) MSG_ItalicFont; // make italic if pref call fails
PREF_GetIntPref("mail.quoted_style", &intPref);
m_citationFont = (MSG_FONT) intPref;
intPref = (int) MSG_NormalSize; // make normal size if pref call fails
PREF_GetIntPref("mail.quoted_size", &intPref);
m_citationFontSize = (MSG_CITATION_SIZE) intPref;
intPref = 1;
PREF_GetIntPref("mailnews.nav_crosses_folders", &intPref);
m_navCrossesFolders = intPref;
PREF_GetIntPref("mailnews.profile_age",&m_startingMailNewsProfileAge);
intPref = 1; // default in case we fail
prefError = PREF_GetIntPref("mail.show_headers", &intPref);
switch (intPref)
{
case 0: m_headerstyle = MSG_ShowMicroHeaders; break;
case 1: m_headerstyle = MSG_ShowSomeHeaders; break;
case 2: m_headerstyle = MSG_ShowAllHeaders; break;
default:
XP_ASSERT(FALSE);
break;
}
intPref = 0; // if no pref is set, return 0 - let the backend set the default port
HG87635
// Server preference.
// ### mwelch This used to use mail.use_imap, but we're switching
// to mail.server_type as of 4.0b2.
intPref = 0; // pop by default
prefError = PREF_GetIntPref("mail.server_type", &intPref);
m_mailInputType = intPref;
m_mailServerIsIMAP = (m_mailInputType == 1);
PREF_GetIntPref("mail.purge_threshhold", &m_purgeThreshhold);
// Get string prefs.
if (!m_freezeMailDirectory)
{
// m_localMailDirectory
strPref = m_localMailDirectory;
m_localMailDirectory = NULL;
// Get the m_localMailDirectory pref. Passing in TRUE (expectFile) since the flag
// tells the Mac-specific code to make use of the name (usually "\pMail") in the FSSpec
// as well as the parent directory ID.
GetXPDirPathPref("mail.directory", TRUE, &m_localMailDirectory);
#if defined (XP_MAC)
if (!m_localMailDirectory || !*m_localMailDirectory)
{
Assert_(FALSE); // can this happen? If not, remove this.
char *newDirURL = NULL;
// ### mwelch This is a hack, because the MacFE
// doesn't set the mail root directory by default.
FSSpec mailFolder = CPrefs::GetFolderSpec(CPrefs::MailFolder);
newDirURL = CFileMgr::EncodedPathNameFromFSSpec(mailFolder, true);
m_localMailDirectory = newDirURL;
}
#endif
// It is still possible to have a NULL directory at this
// point in the code. This is because the WinFE sets the default
// mail directory preference after creating the prefs object.
if (m_localMailDirectory)
{
// by arbitrary convention, the directory shouldn't have
// a trailing slash
int len = XP_STRLEN(m_localMailDirectory);
if (len && m_localMailDirectory[len-1] == '/')
m_localMailDirectory[len-1] = '\0';
#if !defined(XP_MAC) && !defined(XP_WIN) && !defined(XP_OS2)
if (!strPref || strcmp(m_localMailDirectory, strPref))
{
// Create the directory if it doesn't exist (Unix only)
XP_StatStruct dirStat;
if (-1 == XP_Stat(m_localMailDirectory, &dirStat, xpMailFolder))
XP_MakeDirectory (m_localMailDirectory, xpMailFolder);
}
#endif
}
if (strPref) XP_FREE(strPref);
}
HG93653
char onlineDir[256];
onlineDir[0] = '\0';
int stringSize = 256;
PREF_GetCharPref("mail.imap.server_sub_directory",
onlineDir, &stringSize);
if ( *onlineDir && (*(onlineDir + XP_STRLEN(onlineDir) - 1) != '/') )
XP_STRCAT(onlineDir, "/");
if ((!m_OnlineImapSubDir) ||
((m_OnlineImapSubDir) &&
XP_STRCMP(onlineDir, m_OnlineImapSubDir)))
{
FREEIF(m_OnlineImapSubDir);
m_OnlineImapSubDir = XP_STRDUP(onlineDir);
//if (XP_STRCMP(m_OnlineImapSubDir,"")) // only set it if it is not empty
// IMAP_SetNamespacesFromPrefs(GetPopHost(), m_OnlineImapSubDir, "", "");
}
PREF_GetBoolPref("mailnews.searchServer", &m_searchServer);
PREF_GetBoolPref("mailnews.searchSubFolders", &m_searchSubFolders);
PREF_GetBoolPref("mailnews.confirm.moveFoldersToTrash", &m_confirmMoveFoldersToTrash);
FREEIF(m_customHeaders);
PREF_CopyCharPref("mailnews.customHeaders",&m_customHeaders);
FREEIF(m_citationColor);
PREF_CopyCharPref("mail.citation_color", &m_citationColor);
FREEIF(m_popHost);
PREF_CopyCharPref("network.hosts.pop_server", &m_popHost);
PREF_GetBoolPref("mail.imap.delete_is_move_to_trash", &m_ImapDeleteMoveToTrash);
// Set the smtp and news (nntp) hosts.
strPref = NULL;
prefError = PREF_CopyCharPref("network.hosts.smtp_server", &strPref);
if (prefError == PREF_NOERROR)
NET_SetMailRelayHost(strPref);
XP_FREEIF(strPref);
// Refresh the username.
strPref = NULL;
prefError = PREF_CopyCharPref("mail.pop_name", &strPref);
if (strPref)
{
NET_SetPopUsername(strPref);
XP_FREE(strPref);
}
MSG_FolderInfo *folderInfo = NULL;
for(int i=0;i<(int) num_of_header_prefs ;i++)
{
strPref = NULL;
// Only look at the path if the "use it" bool flag is set!
// Bug #45449 jrm
XP_Bool doingFccPath = TRUE, wantsFccPath = FALSE;
if (i == mail_default_fcc || i == mail_imap_sentmail_path)
#ifdef XP_MAC
PREF_GetBoolPref("mail.use_fcc", &wantsFccPath);
#else
wantsFccPath = TRUE;
#endif
else if (i == news_default_fcc || i == news_imap_sentmail_path)
#ifdef XP_MAC
PREF_GetBoolPref("news.use_fcc", &wantsFccPath);
#else
wantsFccPath = TRUE;
#endif
else
doingFccPath = FALSE;
if (doingFccPath && wantsFccPath)
{
prefError = GetXPDirPathPref(headerPrefNames[i], TRUE, &strPref);
if ((prefError != PREF_NOERROR) || (!strPref) || (!*strPref) ||
(m_localMailDirectory && !XP_STRCMP(strPref, m_localMailDirectory)))
{
// Take the directory preference and add "Sent" to it.
char *sent = XP_GetString(MK_MSG_SENT_L10N_NAME);
XP_FREEIF(strPref);
if (m_localMailDirectory && *m_localMailDirectory)
strPref = PR_smprintf("%s/%s", m_localMailDirectory, sent);
#ifdef XP_MAC
// Still may need to ensure the file exists.
SetXPMailFilePref(headerPrefNames[i], strPref);
#endif
}
}
else if (!doingFccPath)
PREF_CopyCharPref(headerPrefNames[i], &strPref);
FREEIF(m_defaultHeaders[i]);
m_defaultHeaders[i] = strPref;
}
// Collect all the email addresses which specify the user. We'll need to know them
// when checking the Reply recipients, or doing MDN receipts
if (PREF_NOERROR == PREF_CopyCharPref ("mail.identity.useremail.aliases", &strPref))
{
if (*strPref) // default is empty string. don't create an array for that
{
if (!m_emailAliases)
m_emailAliases = new msg_StringArray (TRUE /*ownsMemory*/);
if (m_emailAliases)
{
m_emailAliases->RemoveAll();
m_emailAliases->ImportTokenList (strPref);
}
}
XP_FREE (strPref);
}
// Collect the email addresses which can't be considered aliases for this user.
// This is intended to keep the email aliases feature from defeating the reply-to
// header in messages
char *replyTo = m_defaultHeaders[mail_identity_reply_to];
if (replyTo && *replyTo)
{
if (!m_emailAliasesNot)
m_emailAliasesNot = new msg_StringArray (TRUE);
if (m_emailAliasesNot)
{
char *addresses = NULL;
int num = 0;
if (0 != (num = MSG_ParseRFC822Addresses (replyTo, NULL, &addresses)))
{
// We're ignoring the name of the reply-to header, since the
// actual address is all we care about for the alias calculation
m_emailAliasesNot->RemoveAll();
for (int i = 0; i < num; i++)
{
m_emailAliasesNot->Add (addresses);
addresses += XP_STRLEN (addresses) + 1;
}
}
}
}
}
m_dirty = FALSE;
}
int PR_CALLBACK MSG_PrefsChangeCallback(const char * prefName, void *data)
{
MSG_Prefs *prefs = (MSG_Prefs *) data;
XP_Bool boolPref;
char *strPref = NULL;
int prefError = PREF_NOERROR;
if (prefs)
prefs->m_dirty = TRUE;
// Depending on the preference being changed,
// notify listeners as to the change.
// Default headers first, since we have easy access to them.
for (int i=0;i<(int) num_of_header_prefs;i++)
{
if (!XP_STRCMP(prefName, headerPrefNames[i]))
{
prefs->Notify(MSG_PrefsNotify::DefaultHeader);
return PREF_NOERROR;
}
}
if (!XP_STRNCMP(prefName, "netw", 4))
{
if (!XP_STRCMP(prefName, "network.hosts.pop_server"))
{
NET_SetPopPassword(NULL); // invalidate pop3 password #54109
IMAP_SetPassword(NULL);
PREF_SetCharPref("mail.pop_password", "");
prefs->Notify(MSG_PrefsNotify::PopHost);
}
else
{
// cause smtp and news host to be set to new values immediately
if (prefs) prefs->Reload();
}
}
else if (!XP_STRNCMP(prefName, "mail", 4))
{
if (!XP_STRCMP(prefName,"mail.fixed_width_messages"))
prefs->Notify(MSG_PrefsNotify::PlaintextFont);
else if (!XP_STRCMP(prefName,"mail.auto_quote"))
prefs->Notify(MSG_PrefsNotify::AutoQuote);
else if (!XP_STRCMP(prefName,"mail.strictly_mime"))
{
XP_Bool useQP = FALSE;
prefError = PREF_GetBoolPref(prefName, &useQP);
if (prefError == PREF_NOERROR)
MIME_ConformToStandard(useQP);
}
else if (!XP_STRCMP(prefName,"mail.server_type"))
{
NET_SetPopPassword(NULL); // invalidate pop3 password #54109
IMAP_SetPassword(NULL);
PREF_SetCharPref("mail.pop_password", "");
prefs->Notify(MSG_PrefsNotify::MailServerType);
}
HG32428
else if (!XP_STRNCMP(prefName, "mail.imap.server.", 17))
if (prefs->m_masterForBiff && prefs->m_masterForBiff->GetIMAPHostTable())
prefs->m_masterForBiff->GetIMAPHostTable()->UpdatePrefs(prefName);
else if (!XP_STRCMP(prefName,"mail.cc_self"))
prefs->Notify(MSG_PrefsNotify::DefaultBCC);
else if (!XP_STRCMP(prefName,"mail.quoted_style"))
prefs->Notify(MSG_PrefsNotify::CitationStyle);
else if (!XP_STRCMP(prefName,"mail.quoted_size"))
prefs->Notify(MSG_PrefsNotify::CitationStyle);
else if (!XP_STRCMP(prefName,"mail.citation_color"))
prefs->Notify(MSG_PrefsNotify::CitationStyle);
else if (!XP_STRCMP(prefName,"mail.directory"))
{
char *dirTemp = NULL;
// The WinFE has the habit of
// setting the default mail.directory preference
// after initializing the mail master. So, we test
// the pref we get from GetXPDirPathPref (which follows
// the logic of PREF_GetCharPref) against what we have,
// if we have a preference at all.
// Get the new directory preference.
MSG_Prefs::GetXPDirPathPref("mail.directory", FALSE, &dirTemp);
// Only put up an alert if we have a previous mail
// directory specified, and if the new directory
// doesn't match the one we already have.
if (prefs && (prefs->m_localMailDirectory) && *(prefs->m_localMailDirectory) && dirTemp && strcmp(dirTemp, prefs->m_localMailDirectory))
{
// ### mwelch Find any context we can
// in order to display the alert. ugh.
#ifndef XP_UNIX // X weirdness is such that their alert has to appear elsewhere
MWContext *ctxt = XP_FindSomeContext();
FE_Alert(ctxt, XP_GetString(MK_MSG_MAIL_DIRECTORY_CHANGED));
#endif
// don't reload directory pref
prefs->m_freezeMailDirectory = TRUE;
}
else if ((prefs) && !(prefs->m_localMailDirectory && *prefs->m_localMailDirectory))
{
// We are a new prefs object and couldn't find a user
// pref when we first loaded. Reload immediately.
prefs->Reload();
}
// Clear out the FCC paths when the mail directory changes
// so we don't keep FCCing into the old directory. We'll
// create new system folders on restart.
PREF_SetCharPref ("mail.default_fcc", "");
PREF_SetCharPref ("news.default_fcc", "");
// Free what got allocated when we got the dir pref.
XP_FREEIF(dirTemp);
}
else if (!XP_STRCMP(prefName,"mail.imap.server_sub_directory"))
prefs->Notify(MSG_PrefsNotify::ImapOnlineDir);
else if (!XP_STRCMP(prefName,"mail.wrap_long_lines"))
prefs->Notify(MSG_PrefsNotify::WrapLongLines);
// Other prefs not covered in original MSG_Prefs object
else if (!XP_STRCMP(prefName,"mail.leave_on_server"))
{
PREF_GetBoolPref(prefName, &boolPref);
NET_LeavePopMailOnServer(boolPref);
}
else if (!XP_STRCMP(prefName, "mail.pop_name"))
{
// Refresh the username.
prefError = PREF_CopyCharPref("mail.pop_name", &strPref);
if (strPref)
{
HG82454
NET_SetPopUsername(strPref);
XP_FREE(strPref);
}
// Act as if the server has changed.
prefs->Notify(MSG_PrefsNotify::PopHost);
}
else if (!XP_STRCMP(prefName, "mail.remember_password"))
{
PREF_GetBoolPref(prefName, &boolPref);
if (!boolPref)
PREF_SetCharPref("mail.pop_password", "");
}
else if (!XP_STRCMP(prefName,"mail.imap.delete_is_move_to_trash"))
prefs->Notify(MSG_PrefsNotify::ChangeIMAPDeleteModel);
}
else // if (!XP_STRNCMP(prefName, "news", 4))
{
if (!XP_STRCMP(prefName, "news.server_change_xaction"))
{
// Now we know that all news server prefs have been tweaked.
// If the default news server isn't in the host table, add it.
// (Thankfully, we just need to add it, and let the MSG_Master
// do the searching.)
MSG_Master *master = prefs->m_masterForBiff;
if (master)
{
char *newsHost = NULL;
int32 port = -1;
XP_Bool xxx = FALSE;
PREF_CopyCharPref("network.hosts.nntp_server", &newsHost);
PREF_GetIntPref("news.server_port", &port);
HG43788
if ((newsHost != NULL) && (port >= 0))
master->AddNewsHost(newsHost, xxx, port);
}
}
else if (!XP_STRCMP(prefName,"news.cc_self"))
prefs->Notify(MSG_PrefsNotify::DefaultBCC);
}
return PREF_NOERROR;
}
MSG_Prefs::MSG_Prefs()
{
m_citationFont = MSG_PlainFont;
m_citationFontSize = MSG_Bigger;
m_plainText = TRUE;
m_mailServerIsIMAP = FALSE;
HG98298
m_ImapDeleteMoveToTrash = TRUE;
m_IMAPdirectory = NULL;
m_headerstyle = MSG_ShowSomeHeaders;
m_masterForBiff = NULL;
m_notifying = FALSE;
// Set up dirty flag.
m_dirty = TRUE;
m_freezeMailDirectory = FALSE;
m_emailAliases = NULL;
m_emailAliasesNot = NULL;
// Set up prefs callback.
PREF_RegisterCallback("mail.", &MSG_PrefsChangeCallback, this);
PREF_RegisterCallback("news.", &MSG_PrefsChangeCallback, this);
PREF_RegisterCallback("mailnews.", &MSG_PrefsChangeCallback, this);
PREF_RegisterCallback("network.hosts.", &MSG_PrefsChangeCallback, this);
// Load pref values from the prefs api.
// (We can rely on the string members being NULL initially
// since we derive from MSG_Zap.)
Reload();
PREF_RegisterCallback ("mail.use_imap_sentmail",
&MSG_UseImapSentmailPrefChanged, this);
PREF_RegisterCallback ("mail.default_fcc", &MSG_FccPrefChanged, this);
PREF_RegisterCallback ("mail.imap_sentmail_path", &MSG_FccPrefChanged,
this);
PREF_RegisterCallback ("news.use_imap_sentmail",
&MSG_UseImapSentmailPrefChanged, this);
PREF_RegisterCallback ("news.default_fcc", &MSG_FccPrefChanged, this);
PREF_RegisterCallback ("news.imap_sentmail_path", &MSG_FccPrefChanged,
this);
PREF_RegisterCallback ("mail.server_type", &MSG_MailServerTypeChanged,
this);
PREF_RegisterCallback ("mail.default_drafts", &MSG_DraftsPrefChanged, this);
PREF_RegisterCallback ("mail.default_templates", &MSG_TemplatesPrefChanged,
this);
// we are only interested in what this prefs value was at startup so initialize it
// here rather than in Reload()
m_startingMailNewsProfileAge = 0;
PREF_GetIntPref("mailnews.profile_age",&m_startingMailNewsProfileAge);
HG92734
}
MSG_Prefs::~MSG_Prefs()
{
XP_ASSERT(m_numnotify == 0);
FREEIF(m_localMailDirectory);
FREEIF(m_citationColor);
FREEIF(m_popHost);
for (int i=0 ; i<sizeof(m_defaultHeaders)/sizeof(char*) ; i++)
FREEIF(m_defaultHeaders[i]);
XP_FREEIF(m_IMAPdirectory);
delete m_emailAliases;
m_emailAliases = NULL;
delete m_emailAliasesNot;
m_emailAliasesNot = NULL;
PREF_UnregisterCallback("mail.", &MSG_PrefsChangeCallback, this);
PREF_UnregisterCallback("news.", &MSG_PrefsChangeCallback, this);
PREF_UnregisterCallback("mailnews.", &MSG_PrefsChangeCallback, this);
PREF_UnregisterCallback("network.hosts.pop_server",
&MSG_PrefsChangeCallback, this);
PREF_UnregisterCallback("mail.use_imap_sentmail",
&MSG_UseImapSentmailPrefChanged, this);
PREF_UnregisterCallback("mail.default_fcc", &MSG_FccPrefChanged, this);
PREF_UnregisterCallback("mail.imap_sentmail_path", &MSG_FccPrefChanged,
this);
PREF_UnregisterCallback("news.use_imap_sentmail",
&MSG_UseImapSentmailPrefChanged, this);
PREF_UnregisterCallback("news.default_fcc", &MSG_FccPrefChanged, this);
PREF_UnregisterCallback("news.imap_sentmail_path", &MSG_FccPrefChanged,
this);
PREF_UnregisterCallback("mail.server_type", &MSG_MailServerTypeChanged,
this);
PREF_UnregisterCallback("mail.default_drafts", &MSG_DraftsPrefChanged,
this);
PREF_UnregisterCallback("mail.default_templates", &MSG_TemplatesPrefChanged,
this);
}
void MSG_Prefs::AddNotify(MSG_PrefsNotify* notify)
{
MSG_PrefsNotify** tmp = m_notify;
m_notify = new MSG_PrefsNotify* [m_numnotify + 1];
for (int i=0 ; i<m_numnotify ; i++) {
XP_ASSERT(tmp[i] != notify);
m_notify[i] = tmp[i];
}
m_notify[m_numnotify++] = notify;
delete [] tmp; // not sure why this wasn't here before.
// Could have used XP_PtrArray...
}
void MSG_Prefs::RemoveNotify(MSG_PrefsNotify* notify)
{
int i = 0;
if (m_notifying)
{
// We're in the process of notifying listeners, so we
// can't shuffle pointers around.
// Just null out the pointer in question, Notify will
// clean up after us.
for (; i<m_numnotify; i++)
{
if (m_notify[i] == notify)
m_notify[i] = NULL;
}
return;
}
// If we're not notifying listeners, just replace the
// dead element with the last in the list, then decrement
// the listener count.
for (; i<m_numnotify ; i++)
{
if (m_notify[i] == notify)
{
m_notify[i] = m_notify[--m_numnotify];
return;
}
}
XP_ASSERT(0);
}
XP_Bool MSG_Prefs::GetSearchServer()
{
Reload();
return m_searchServer;
}
XP_Bool MSG_Prefs::GetSearchSubFolders()
{
Reload();
return m_searchSubFolders;
}
int32 MSG_Prefs::GetNumCustomHeaders()
{
Reload();
// determine number of custom headers in the preference so far....
int count = 0;
if (!m_customHeaders)
return 0;
char * buffer = XP_STRDUP(m_customHeaders);
char * marker = buffer;
while (XP_STRTOK_R(nil, ":, ", &buffer))
count++;
XP_FREEIF(marker);
return count;
}
// caller must use XP_FREE to deallocate the header string this returns.
char * MSG_Prefs::GetNthCustomHeader(int offset)
{
Reload();
char * temp = NULL;
if (offset < 0)
return temp;
if (!m_customHeaders)
return NULL;
char * buffer = XP_STRDUP(m_customHeaders);
char * marker = buffer;
for (int count = 0; count <= offset; count++)
{
temp = XP_STRTOK_R(nil,",: ",&buffer);
if (!temp)
break;
}
// temp now points to the token string
if (temp)
temp = XP_STRDUP(temp); // make a copy of the string // caller must deallocate the space
XP_FREEIF(marker); // free our copy of the buffer...
return temp;
}
#ifdef XP_UNIX
void MSG_Prefs::SetFolderDirectory(const char* d)
{
PREF_SetCharPref("mail.directory", d);
m_dirty = TRUE;
}
#else
void MSG_Prefs::SetFolderDirectory(const char*)
{
}
#endif
const char *MSG_Prefs::GetFolderDirectory()
{
Reload();
return m_localMailDirectory;
}
const char *MSG_Prefs::GetIMAPFolderDirectory()
{
Reload();
if (!m_IMAPdirectory)
{
char *machinePathName = 0;
if (m_popHost)
{
// see if there's a :port in the server name. If so, strip it off when
// creating the server directory.
char *server = XP_STRDUP(m_popHost);
char *port = 0;
if (server)
{
port = XP_STRCHR(server,':');
if (port)
*port = 0;
machinePathName = WH_FileName(server, xpImapServerDirectory);
XP_FREE(server);
}
}
if (machinePathName)
{
char *imapUrl = XP_PlatformFileToURL (machinePathName);
if (imapUrl)
{
m_IMAPdirectory = XP_STRDUP(imapUrl + XP_STRLEN("file://"));
XP_FREE(imapUrl);
}
XP_FREE (machinePathName);
}
}
return m_IMAPdirectory;
}
void MSG_Prefs::GetCitationStyle(MSG_FONT* f, MSG_CITATION_SIZE* s, const char** c)
{
Reload();
if (f) *f = m_citationFont;
if (s) *s = m_citationFontSize;
if (c) *c = m_citationColor;
}
const char* MSG_Prefs::GetPopHost()
{
Reload();
return m_popHost;
}
XP_Bool MSG_Prefs::IMAPMessageDeleteIsMoveToTrash()
{
Reload();
return m_ImapDeleteMoveToTrash;
}
/*
const char *MSG_Prefs::GetOnlineImapSubDir()
{
Reload();
return m_OnlineImapSubDir;
}
*/
XP_Bool MSG_Prefs::GetMailServerIsIMAP4()
{
Reload();
return m_mailServerIsIMAP;
}
HG87637
const char *MSG_Prefs::GetCopyToSentMailFolderPath()
{
return GetDefaultHeaderContents(MSG_FCC_HEADER_MASK);
}
MSG_CommandType MSG_Prefs::GetHeaderStyle()
{
Reload();
return m_headerstyle;
}
XP_Bool MSG_Prefs::GetNoInlineAttachments()
{
Reload();
return m_noinline;
}
XP_Bool MSG_Prefs::GetWrapLongLines()
{
Reload();
return m_wraplonglines;
}
XP_Bool MSG_Prefs::GetAutoQuoteReply()
{
Reload();
return m_autoQuote;
}
const char* MSG_Prefs::GetDefaultHeaderContents(MSG_HEADER_SET header)
{
Reload();
int i = ConvertHeaderSetToSubscript(header);
if (i < 0)
return NULL;
return m_defaultHeaders[i];
}
XP_Bool MSG_Prefs::GetDefaultBccSelf(XP_Bool newsBcc)
{
Reload();
return newsBcc ? m_newsBccSelf : m_mailBccSelf;
}
int32 MSG_Prefs::GetPurgeThreshhold()
{
Reload();
return m_purgeThreshhold;
}
XP_Bool MSG_Prefs::GetPurgeThreshholdEnabled()
{
Reload();
return m_purgeThreshholdEnabled;
}
XP_Bool MSG_Prefs::GetShowPrettyNames()
{
Reload();
return m_showPrettyNames;
}
HG92435
XP_Bool MSG_Prefs::GetNewsNotifyOn()
{
Reload();
return m_newsNotifyOn;
}
void MSG_Prefs::SetNewsNotifyOn(XP_Bool notify)
{
PREF_SetBoolPref("news.notify.on", notify);
}
MSG_NCFValue MSG_Prefs::GetNavCrossesFolders()
{
Reload();
return (MSG_NCFValue) m_navCrossesFolders;
}
void MSG_Prefs::SetNavCrossesFolders(MSG_NCFValue cross)
{
PREF_SetIntPref("mailnews.nav_crosses_folders", (int32) cross);
}
MSG_Master *MSG_Prefs::GetMasterForBiff()
{
Reload();
return m_masterForBiff;
}
void MSG_Prefs::SetMasterForBiff(MSG_Master *mstr)
{
// Since we're dealing with a mail master, this by
// definition is a temporary preference. So, just
// set the member in this case.
m_masterForBiff = mstr;
}
char *MSG_Prefs::MagicFolderName(uint32 flag, int *pStatus)
{
MSG_FolderInfo *folderInfo = NULL;
if (pStatus)
*pStatus = 0;
if (flag == MSG_FOLDER_FLAG_SENTMAIL)
{
if (m_sentName)
return XP_STRDUP(m_sentName);
const char *tmp = GetCopyToSentMailFolderPath();
if (tmp != NULL && m_masterForBiff)
{
folderInfo = m_masterForBiff->GetFolderInfo(tmp, FALSE);
if (folderInfo && folderInfo->GetDepth() == 1)
{
if (NET_URL_Type(tmp) == IMAP_TYPE_URL && folderInfo->GetIMAPHost())
tmp = PR_smprintf("IMAP://%s@%s/%s",
folderInfo->GetIMAPHost()->GetUserName(),
folderInfo->GetName(),
SENT_FOLDER_NAME);
else if (folderInfo->GetMailFolderInfo())
tmp = PR_smprintf("%s/%s",
folderInfo->GetMailFolderInfo()->GetPathname(),
SENT_FOLDER_NAME);
}
}
if (tmp)
m_sentName = XP_STRDUP(tmp);
return (tmp != NULL) ? XP_STRDUP(tmp) : 0;
}
else if (flag == MSG_FOLDER_FLAG_DRAFTS)
{
if (m_draftsName)
return XP_STRDUP(m_draftsName);
char *draftsName = NULL;
PREF_CopyCharPref("mail.default_drafts", &draftsName);
if (draftsName && *draftsName)
{
#ifdef XP_MAC
#pragma warn_possunwant off
#endif // XP_MAC
if (m_masterForBiff &&
(folderInfo = m_masterForBiff->GetFolderInfo(draftsName, FALSE)) &&
folderInfo->GetDepth() == 1)
{
if (NET_URL_Type(draftsName) == IMAP_TYPE_URL &&
folderInfo->GetIMAPHost())
{
char *newDraftsName =
PR_smprintf("IMAP://%s@%s",
folderInfo->GetIMAPHost()->GetUserName(),
folderInfo->GetName());
if (newDraftsName)
{
XP_FREE(draftsName);
draftsName = newDraftsName;
}
}
StrAllocCat(draftsName, "/");
StrAllocCat(draftsName, DRAFTS_FOLDER_NAME);
}
#ifdef XP_MAC
#pragma warn_possunwant reset
#endif // XP_MAC
m_draftsName = XP_STRDUP(draftsName);
return draftsName;
}
// else fall through
}
else if (flag == MSG_FOLDER_FLAG_TEMPLATES)
{
if (m_templatesName)
return XP_STRDUP(m_templatesName);
char *templatesName = NULL;
PREF_CopyCharPref("mail.default_templates", &templatesName);
if (templatesName && *templatesName)
{
#ifdef XP_MAC
#pragma warn_possunwant off
#endif // XP_MAC
if (m_masterForBiff &&
(folderInfo = m_masterForBiff->GetFolderInfo(templatesName, FALSE)) &&
folderInfo->GetDepth() == 1)
{
if (NET_URL_Type(templatesName) == IMAP_TYPE_URL &&
folderInfo->GetIMAPHost())
{
char *newTemplatesName =
PR_smprintf("IMAP://%s@%s",
folderInfo->GetIMAPHost()->GetUserName(),
folderInfo->GetName());
if (newTemplatesName)
{
XP_FREE(templatesName);
templatesName = newTemplatesName;
}
}
StrAllocCat(templatesName, "/");
StrAllocCat(templatesName, TEMPLATES_FOLDER_NAME);
}
#ifdef XP_MAC
#pragma warn_possunwant reset
#endif // XP_MAC
m_templatesName = XP_STRDUP(templatesName);
return templatesName;
}
// else fall through
}
const char *dir = GetFolderDirectory();
char *name;
char *ptr;
XP_ASSERT(dir);
if (!dir) return 0;
name = (char *) XP_ALLOC(XP_STRLEN(dir) + 30);
if (!name) return 0;
XP_STRCPY(name, dir);
ptr = name + XP_STRLEN(name);
if (ptr[-1] != '/')
*ptr++ = '/';
#ifdef XP_MAC
char* escapedName = NET_Escape(
(flag == MSG_FOLDER_FLAG_INBOX ? INBOX_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_TRASH ? TRASH_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_QUEUE ? MSG_GetQueueFolderName() :
flag == MSG_FOLDER_FLAG_DRAFTS ? DRAFTS_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_TEMPLATES ? TEMPLATES_FOLDER_NAME :
"###"),
URL_PATH);
if (!escapedName)
return NULL;
XP_STRCPY(ptr, escapedName);
XP_FREE(escapedName);
#else
XP_STRCPY(ptr,
(flag == MSG_FOLDER_FLAG_INBOX ? INBOX_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_TRASH ? TRASH_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_QUEUE ? MSG_GetQueueFolderName() :
flag == MSG_FOLDER_FLAG_DRAFTS ? DRAFTS_FOLDER_NAME :
flag == MSG_FOLDER_FLAG_TEMPLATES ? TEMPLATES_FOLDER_NAME :
"###"));
#endif
// Better have really found one.
XP_ASSERT(XP_STRCMP(ptr, "###"));
return name;
}
XP_Bool MSG_Prefs::CopyStringIfChanged(char** str, const char* value)
{
if (*str == NULL && value == NULL) return FALSE;
if (*str && value && XP_STRCMP(*str, value) == 0) return FALSE;
if (*str)
delete [] *str;
if (value)
{
*str = new char[XP_STRLEN(value) + 1];
if (*str)
XP_STRCPY(*str, value);
}
else
*str = NULL;
return TRUE;
}
int MSG_Prefs::ConvertHeaderSetToSubscript(MSG_HEADER_SET header)
{
switch (header)
{
case MSG_REPLY_TO_HEADER_MASK:
return 0;
case MSG_BCC_HEADER_MASK:
return 1;
case MSG_FCC_HEADER_MASK:
{
XP_Bool use_imap_sentmail = FALSE;
PREF_GetBoolPref("mail.use_imap_sentmail", &use_imap_sentmail);
if (use_imap_sentmail)
return 3;
else
return 2;
}
case MSG_NEWS_BCC_HEADER_MASK:
return 4;
case MSG_NEWS_FCC_HEADER_MASK:
{
XP_Bool use_imap_sentmail = FALSE;
PREF_GetBoolPref("news.use_imap_sentmail", &use_imap_sentmail);
if (use_imap_sentmail)
return 6;
else
return 5;
}
default:
XP_ASSERT (0);
return -1;
}
}
const char * msg_DefaultFolderName(uint32 flag)
{
switch (flag)
{
case MSG_FOLDER_FLAG_DRAFTS:
return DRAFTS_FOLDER_NAME;
case MSG_FOLDER_FLAG_SENTMAIL:
return SENT_FOLDER_NAME;
case MSG_FOLDER_FLAG_TEMPLATES:
return TEMPLATES_FOLDER_NAME;
default:
XP_ASSERT(0);
return "";
}
}
int msg_FolderPrefChanged(const char *prefName, void *msgPrefsVoid, uint32 flag)
{
char *folderPath = NULL;
MSG_Prefs *msgPrefs = (MSG_Prefs*) msgPrefsVoid;
MSG_Prefs::GetXPDirPathPref(prefName, TRUE, &folderPath);
if (folderPath)
{
MSG_Master *master = msgPrefs->m_masterForBiff;
// clear out calculated drafts,sent, and templates names
XP_FREEIF(msgPrefs->m_draftsName);
XP_FREEIF(msgPrefs->m_sentName);
XP_FREEIF(msgPrefs->m_templatesName);
if (master)
{
// Find all old magic folders and the new magic folder. For sent mail,
// there can be 1 or 2 such folders.
MSG_FolderInfoMail *newFolder = NULL;
typedef MSG_FolderInfo* FInfoPtr;
MSG_FolderInfo *folderList[3];
uint32 numFoldersToCheck
= master->GetFolderTree()->GetFoldersWithFlag(
flag, folderList, sizeof(folderList)/sizeof(FInfoPtr));
if (NET_URL_Type(folderPath) == IMAP_TYPE_URL)
{
char *host = NET_ParseURL(folderPath, GET_HOST_PART);
char *name = NET_ParseURL(folderPath, GET_PATH_PART);
char *owner = NET_ParseURL(folderPath, GET_USERNAME_PART);
if (!name || !*name)
{
StrAllocCopy(name, "/");
StrAllocCat(name, msg_DefaultFolderName(flag));
}
if ((!owner || !*owner) && master->GetIMAPHost(host))
{
StrAllocCopy(owner, master->GetIMAPHost(host)->GetUserName());
}
// name+1 skips the root "/" character
newFolder =
master->FindImapMailFolder(host, name+1, owner, FALSE);
XP_FREEIF(host);
XP_FREEIF(name);
XP_FREEIF(owner);
}
else
{
const char *folderDir = msgPrefs->GetFolderDirectory();
if (!*folderPath)
StrAllocCopy (folderPath, folderDir);
const char *name =
NET_URL_Type(folderPath) == MAILBOX_TYPE_URL ?
folderPath + 8 : folderPath;
if (XP_STRCMP(name, folderDir) == 0)
{
// Hmmm no folder name. Use default name.
StrAllocCat(folderPath, "/");
StrAllocCat(folderPath, msg_DefaultFolderName(flag));
}
newFolder = master->FindMailFolder(folderPath, FALSE /*createIfMissing*/);
}
if (newFolder)
{
XP_Bool newFolderIsSame = FALSE;
MSG_FolderInfo** current = &folderList[0];
for (int i = 0; i < numFoldersToCheck; i++, current++)
{
if (*current == newFolder)
{
newFolderIsSame = TRUE;
break;
}
}
if (!newFolderIsSame)
folderList[numFoldersToCheck++] = newFolder;
}
MSG_FolderInfo** current = &folderList[0];
for (int i = 0; i < numFoldersToCheck; i++, current++)
{
MSG_FolderInfoMail* f = (*current)->GetMailFolderInfo();
f->SetPrefFolderFlag();
// After changing the flag of a folder that's already in the tree,
// you have to call QuickSort to maintain the sort order.
// Possible improvement: sort only once per parent (even if
// the folders are different, they may have the same parent).
MSG_FolderInfo* parent = master->GetFolderTree()->FindParentOf(f);
parent->GetSubFolders()->QuickSort(MSG_FolderInfoMail::CompareFolders);
// Let the front end know that the flags have changed. The icon will
// change.
master->BroadcastFolderChanged(f);
}
}
XP_FREE(folderPath);
}
return 0;
}
int PR_CALLBACK MSG_UseImapSentmailPrefChanged (const char *prefName,
void *msgPrefsVoid)
{
XP_Bool bUseImap = FALSE;
if ( XP_STRCMP(prefName, "mail.use_imap_sentmail") == 0 &&
PREF_NOERROR == PREF_GetBoolPref("mail.use_imap_sentmail", &bUseImap) )
{
if (bUseImap)
return MSG_FccPrefChanged ("mail.imap_sentmail_path", msgPrefsVoid);
else
return MSG_FccPrefChanged ("mail.default_fcc", msgPrefsVoid);
}
else if ( XP_STRCMP(prefName, "news.use_imap_sentmail") == 0 &&
PREF_NOERROR == PREF_GetBoolPref("news.use_imap_sentmail", &bUseImap) )
{
if (bUseImap)
return MSG_FccPrefChanged ("news.imap_sentmail_path", msgPrefsVoid);
else
return MSG_FccPrefChanged ("news.default_fcc", msgPrefsVoid);
}
return 0;
}
int PR_CALLBACK MSG_FccPrefChanged (const char *prefName, void *msgPrefsVoid)
{
return msg_FolderPrefChanged(prefName, msgPrefsVoid,
MSG_FOLDER_FLAG_SENTMAIL);
}
int PR_CALLBACK MSG_DraftsPrefChanged (const char *prefName, void *msgPrefsVoid)
{
return msg_FolderPrefChanged(prefName, msgPrefsVoid,
MSG_FOLDER_FLAG_DRAFTS);
}
int PR_CALLBACK MSG_TemplatesPrefChanged (const char *prefName,
void *msgPrefsVoid)
{
return msg_FolderPrefChanged(prefName, msgPrefsVoid,
MSG_FOLDER_FLAG_TEMPLATES);
}
int PR_CALLBACK MSG_MailServerTypeChanged (const char * /*prefName*/, void *msgPrefsVoid)
{
// Since we can't deal with Body filters in IMAP (in 4.0) we're going
// to loop over all the filters and redirect them to the Subject header
//
// It would be nice to do this with the user's permission.
// Don't do anything if we switched from POP to IMAP, only for IMAP to POP
MSG_Master *master = ((MSG_Prefs*)msgPrefsVoid)->GetMasterForBiff();
int32 intPref = 0; // pop by default
int prefError = PREF_GetIntPref("mail.server_type", &intPref);
if (prefError == PREF_NOERROR && master)
{
int32 profileAge = master->GetPrefs()->GetStartingMailNewsProfileAge();
// Upgrade default IMAP host prefs
if (!(profileAge & MSG_IMAP_DEFAULT_HOST_UPGRADE_FLAG) &&
intPref == 1) // we haven't upgraded the default host yet
{
// make the pop host look like an imap host.
MSG_IMAPHost::UpgradeDefaultServerPrefs(master);
return 0;
}
}
else
return 0;
HG62437
if (master)
master->CloseCachedImapConnections();
// Don't do anything if someone else is looking at the filter list
if (!master || !master->AcquireRulesSemaphore(msgPrefsVoid))
return 0;
// Don't do anything if we can't open the filter list
MSG_FilterList *filterList = NULL;
if (MSG_FilterList::Open (master, filterInbox, &filterList) != FilterError_Success || !filterList)
{
master->ReleaseRulesSemaphore (msgPrefsVoid);
return 0;
}
XP_Bool filterListIsDirty = FALSE;
int32 filterCount = 0;
filterList->GetFilterCount(&filterCount);
for (MSG_FilterIndex filterIndex = 0; filterIndex < filterCount; filterIndex++)
{
MSG_Filter *filter = NULL;
if (filterList->GetFilterAt(filterIndex, &filter) == FilterError_Success && filter != NULL)
{
if (filter->GetType() == filterInboxRule)
{
MSG_Rule *rule = NULL;
if (filter->GetRule(&rule) == FilterError_Success && rule != NULL)
{
MSG_SearchTermArray &terms = rule->GetTermList();
for (int i = 0; i < terms.GetSize(); i++)
{
MSG_SearchTerm *term = terms.GetAt(i);
if (term && term->m_attribute == attribBody)
{
term->m_attribute = attribSubject;
filterListIsDirty = TRUE;
// Body searching can't do begins/ends with. Maybe it should...
if (term->m_operator == opBeginsWith || term->m_operator == opEndsWith)
term->m_operator = opContains;
}
}
}
}
}
}
master->ReleaseRulesSemaphore (msgPrefsVoid);
if (filterListIsDirty)
MSG_CloseFilterList (filterList);
else
MSG_CancelFilterList (filterList);
return 0;
}
msg_StringArray *MSG_Prefs::m_emailAliases = NULL;
msg_StringArray *MSG_Prefs::m_emailAliasesNot = NULL;
/*static*/ XP_Bool MSG_Prefs::IsEmailAddressAnAliasForMe (const char *addr)
{
// Does the address match one of the user's alias expressions (e.g. foo@*.netscape.com)
if (m_emailAliasesNot)
{
// Some addresses can't be considered aliases. Right now, this is just used
// for the Reply-To address, so that if you Reply All, your Reply-To address
// will be included, or if you send yourself an MDN request, you'll get one back
//
// NB: this list is guaranteed to hold only addresses, not names, so we can strcmp
// it without parsing it (here)
for (int i = 0; i < m_emailAliasesNot->GetSize(); i++)
if (!strcasecomp (addr, m_emailAliasesNot->GetAt(i)))
return FALSE;
}
if (m_emailAliases) // master/prefs may not have been initialized yet
{
for (int i = 0; i < m_emailAliases->GetSize(); i++)
{
char *alias = (char*) m_emailAliases->GetAt(i); //Hacky cast: regexp API isn't const
if (VALID_SXP == NET_RegExpValid (alias))
{
// The alias is a regular expression, so send it into the regexp evaluator
if (!NET_RegExpMatch ((char*) addr, alias, FALSE /*case sensitive*/))
return TRUE;
}
else
{
// The alias is not a regular expression, so just use a string compare
if (!strcasecomp (addr, alias))
return TRUE;
}
}
}
return FALSE;
}