Bug 296758 Adding phishing detection to mailnews
p=me r=mnyromyr sr=bienvenu a=asa git-svn-id: svn://10.0.0.236/trunk@177340 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -210,6 +210,8 @@ var DefaultController =
|
||||
case "cmd_markAsJunk":
|
||||
case "cmd_markAsNotJunk":
|
||||
case "cmd_recalculateJunkScore":
|
||||
case "cmd_markAsShowRemote":
|
||||
case "cmd_markAsNotPhish":
|
||||
case "cmd_applyFilters":
|
||||
case "cmd_runJunkControls":
|
||||
case "cmd_deleteJunk":
|
||||
@@ -322,12 +324,16 @@ var DefaultController =
|
||||
case "cmd_markAsFlagged":
|
||||
case "button_file":
|
||||
case "cmd_file":
|
||||
return (GetNumSelectedMessages() > 0 );
|
||||
return (GetNumSelectedMessages() > 0);
|
||||
case "cmd_markAsJunk":
|
||||
case "cmd_markAsNotJunk":
|
||||
case "cmd_recalculateJunkScore":
|
||||
// can't do news on junk yet.
|
||||
return (GetNumSelectedMessages() > 0 && !isNewsURI(GetFirstSelectedMessage()));
|
||||
case "cmd_markAsShowRemote":
|
||||
return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("remoteContentPolicy", kAllowRemoteContent));
|
||||
case "cmd_markAsNotPhish":
|
||||
return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("notAPhishMessage", kNotAPhishMessage));
|
||||
case "cmd_applyFilters":
|
||||
if (gDBView)
|
||||
gDBView.getCommandStatus(nsMsgViewCommandType.applyFilters, enabled, checkStatus);
|
||||
@@ -633,6 +639,12 @@ var DefaultController =
|
||||
case "cmd_recalculateJunkScore":
|
||||
analyzeMessagesForJunk();
|
||||
return;
|
||||
case "cmd_markAsShowRemote":
|
||||
LoadMsgWithRemoteContent();
|
||||
return;
|
||||
case "cmd_markAsNotPhish":
|
||||
MsgIsNotAScam();
|
||||
return;
|
||||
case "cmd_applyFilters":
|
||||
MsgApplyFilters(null);
|
||||
return;
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/messengerdnd.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/accountUtils.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/mail-offline.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/phishingDetector.js"/>
|
||||
<script type="application/x-javascript" src="chrome://communicator/content/contentAreaClick.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsTransferable.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
|
||||
@@ -184,14 +185,14 @@
|
||||
</splitter>
|
||||
|
||||
<vbox id="messagepanebox" flex="2" minheight="100" height="200" minwidth="100" width="200" persist="collapsed height width" class="window-focusborder" focusring="false">
|
||||
<hbox id="junkBar"/>
|
||||
<deck id="msgNotificationBar"/>
|
||||
|
||||
<hbox id="msgHeaderView"/>
|
||||
|
||||
<browser id="messagepane" name="messagepane" height="0" flex="1"
|
||||
context="messagePaneContext" minwidth="1" minheight="1"
|
||||
disablesecurity="true" disablehistory="true" autofind="false"
|
||||
type="content-primary" onclick="messagePaneOnClick(event);"/>
|
||||
type="content-primary" onclick="return messagePaneOnClick(event);"/>
|
||||
</vbox>
|
||||
</box>
|
||||
|
||||
|
||||
@@ -228,16 +228,15 @@ function messagePaneOnClick(event)
|
||||
// if this is stand alone mail (no browser)
|
||||
// or this isn't a simple left click, do nothing, and let the normal code execute
|
||||
if (event.button != 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
||||
{
|
||||
contentAreaClick(event);
|
||||
return;
|
||||
}
|
||||
return contentAreaClick(event);
|
||||
|
||||
// try to determine the href for what you are clicking on.
|
||||
// for example, it might be "" if you aren't left clicking on a link
|
||||
var href = hrefForClickEvent(event);
|
||||
if (!href)
|
||||
return;
|
||||
var ceParams = {event: event, href: "", linkNode: null};
|
||||
hrefAndLinkNodeForClickEvent(ceParams);
|
||||
var href = ceParams.href;
|
||||
if (!href)
|
||||
return true;
|
||||
|
||||
// we know that http://, https://, ftp://, file://, chrome://,
|
||||
// resource://, about:, and gopher:// (as if),
|
||||
@@ -248,7 +247,7 @@ function messagePaneOnClick(event)
|
||||
// and let the normal code handle it
|
||||
var needABrowser = /(^http(s)?:|^ftp:|^file:|^gopher:|^chrome:|^resource:|^about:)/i;
|
||||
if (href.search(needABrowser) == -1)
|
||||
return;
|
||||
return true;
|
||||
|
||||
// however, if the protocol should not be loaded internally, then we should
|
||||
// not put up a new browser window. we should just let the usual processing
|
||||
@@ -258,7 +257,7 @@ function messagePaneOnClick(event)
|
||||
extProtService = extProtService.QueryInterface(Components.interfaces.nsIExternalProtocolService);
|
||||
var scheme = href.substring(0, href.indexOf(":"));
|
||||
if (!extProtService.isExposedProtocol(scheme))
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
catch (ex) {} // ignore errors, and just assume that we can proceed.
|
||||
|
||||
@@ -270,7 +269,11 @@ function messagePaneOnClick(event)
|
||||
// we want to preventDefault, so that in
|
||||
// nsGenericHTMLElement::HandleDOMEventForAnchors(), we don't try to handle the click again
|
||||
event.preventDefault();
|
||||
if (isPhishingURL(ceParams.linkNode, false))
|
||||
return false;
|
||||
|
||||
openTopBrowserWith(href);
|
||||
return true;
|
||||
}
|
||||
|
||||
function AddDataSources()
|
||||
@@ -529,30 +532,32 @@ function StopUrls()
|
||||
msgWindow.StopUrls();
|
||||
}
|
||||
|
||||
function loadStartPage() {
|
||||
try {
|
||||
// collapse the junk bar
|
||||
SetUpJunkBar(null);
|
||||
function loadStartPage()
|
||||
{
|
||||
try
|
||||
{
|
||||
gMessageNotificationBar.clearMsgNotifications();
|
||||
|
||||
var startpageenabled = pref.getBoolPref("mailnews.start_page.enabled");
|
||||
|
||||
if (startpageenabled) {
|
||||
var startpage = pref.getComplexValue("mailnews.start_page.url",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
if (startpage != "") {
|
||||
// first, clear out the charset setting.
|
||||
messenger.setDisplayCharset("");
|
||||
|
||||
GetMessagePaneFrame().location.href = startpage;
|
||||
//dump("start message pane with: " + startpage + "\n");
|
||||
ClearMessageSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
dump("Error loading start page.\n");
|
||||
return;
|
||||
var startpageenabled = pref.getBoolPref("mailnews.start_page.enabled");
|
||||
if (startpageenabled)
|
||||
{
|
||||
var startpage = pref.getComplexValue("mailnews.start_page.url",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
if (startpage)
|
||||
{
|
||||
// first, clear out the charset setting.
|
||||
messenger.setDisplayCharset("");
|
||||
GetMessagePaneFrame().location.href = startpage;
|
||||
//dump("start message pane with: " + startpage + "\n");
|
||||
ClearMessageSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
dump("Error loading start page.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Display AccountCentral page when users clicks on the Account Folder.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
* Jan Varga <varga@ku.sk>
|
||||
* Seth Spitzer <sspitzer@netscape.com>
|
||||
* David Bienvenu <bienvenu@netscape.com>
|
||||
* Ian Neal <bugzilla@arlen.demon.co.uk>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@@ -53,6 +54,22 @@ const kClassicMailLayout = 0;
|
||||
const kWideMailLayout = 1;
|
||||
const kVerticalMailLayout = 2;
|
||||
|
||||
// Per message header flags to keep track of whether the user is allowing remote
|
||||
// content for a particular message.
|
||||
// if you change or add more values to these constants, be sure to modify
|
||||
// the corresponding definitions in nsMsgContentPolicy.cpp
|
||||
const kNoRemoteContentPolicy = 0;
|
||||
const kBlockRemoteContent = 1;
|
||||
const kAllowRemoteContent = 2;
|
||||
|
||||
const kIsAPhishMessage = 0;
|
||||
const kNotAPhishMessage = 1;
|
||||
|
||||
const kMsgNotificationNoStatus = 0;
|
||||
const kMsgNotificationJunkBar = 1;
|
||||
const kMsgNotificationRemoteImages = 2;
|
||||
const kMsgNotificationPhishingBar = 3;
|
||||
|
||||
var gMessengerBundle;
|
||||
var gPromptService;
|
||||
var gOfflinePromptsBundle;
|
||||
@@ -2049,40 +2066,143 @@ function HandleJunkStatusChanged(folder)
|
||||
var loadedMessage = GetLoadedMessage();
|
||||
if (loadedMessage && (!(/type=x-message-display/.test(loadedMessage))) && IsCurrentLoadedFolder(folder))
|
||||
{
|
||||
var messageURI = GetLoadedMessage();
|
||||
// if multiple message are selected
|
||||
// and we change the junk status
|
||||
// we don't want to show the junk bar
|
||||
// (since the message pane is blank)
|
||||
if (messageURI && (GetNumSelectedMessages() == 1))
|
||||
SetUpJunkBar(messenger.messageServiceFromURI(messageURI).messageURIToMsgHdr(messageURI));
|
||||
else
|
||||
SetUpJunkBar(null);
|
||||
// if multiple message are selected and we change the junk status
|
||||
// we don't want to show the junk bar (since the message pane is blank)
|
||||
var msgHdr = null;
|
||||
if (GetNumSelectedMessages() == 1)
|
||||
msgHdr = messenger.messageServiceFromURI(loadedMessage).messageURIToMsgHdr(loadedMessage);
|
||||
gMessageNotificationBar.setJunkMsg(msgHdr);
|
||||
}
|
||||
}
|
||||
|
||||
function SetUpJunkBar(aMsgHdr)
|
||||
var gMessageNotificationBar =
|
||||
{
|
||||
// XXX todo
|
||||
// should this happen on the start, or at the end?
|
||||
// if at the end, we might keep the "this message is junk" up for a while, until a big message is loaded
|
||||
// or do we need to wait until here, to make sure the message is fully analyzed
|
||||
// what about almost hiding it on the start, and then showing here?
|
||||
mBarStatus: 0,
|
||||
// flag bit values for mBarStatus, indexed by kMsgNotificationXXX
|
||||
mBarFlagValues: [
|
||||
0, // kMsgNotificationNoStatus
|
||||
1, // 1 << (kMsgNotificationJunkBar - 1)
|
||||
2, // 1 << (kMsgNotificationRemoteImages - 1)
|
||||
4 // 1 << (kMsgNotificationPhishingBar - 1)
|
||||
],
|
||||
|
||||
var isJunk = false;
|
||||
mMsgNotificationBar: document.getElementById('msgNotificationBar'),
|
||||
|
||||
setJunkMsg: function(aMsgHdr)
|
||||
{
|
||||
var isJunk = false;
|
||||
var isCurrentlyNotJunk = this.mMsgNotificationBar.selectedIndex != kMsgNotificationJunkBar;
|
||||
|
||||
if (aMsgHdr) {
|
||||
var junkScore = aMsgHdr.getStringProperty("junkscore");
|
||||
isJunk = ((junkScore != "") && (junkScore != "0"));
|
||||
if (aMsgHdr)
|
||||
{
|
||||
var junkScore = aMsgHdr.getStringProperty("junkscore");
|
||||
isJunk = ((junkScore != "") && (junkScore != "0"));
|
||||
}
|
||||
|
||||
this.updateMsgNotificationBar (kMsgNotificationJunkBar, isJunk);
|
||||
|
||||
goUpdateCommand('button_junk');
|
||||
},
|
||||
|
||||
setRemoteContentMsg: function(aMsgHdr)
|
||||
{
|
||||
var blockRemote = aMsgHdr &&
|
||||
aMsgHdr.getUint32Property("remoteContentPolicy") == kBlockRemoteContent;
|
||||
this.updateMsgNotificationBar(kMsgNotificationRemoteImages, blockRemote);
|
||||
},
|
||||
|
||||
// aUrl is the nsIURI for the message currently loaded in the message pane
|
||||
setPhishingMsg: function(aUrl)
|
||||
{
|
||||
// if we've explicitly marked this message as not being an email scam, then don't
|
||||
// bother checking it with the phishing detector.
|
||||
var phishingMsg = false;
|
||||
if (!checkMsgHdrPropertyIsNot("notAPhishMessage", kIsAPhishMessage))
|
||||
phishingMsg = isMsgEmailScam(aUrl);
|
||||
this.updateMsgNotificationBar(kMsgNotificationPhishingBar, phishingMsg);
|
||||
},
|
||||
|
||||
clearMsgNotifications: function()
|
||||
{
|
||||
this.updateMsgNotificationBar(kMsgNotificationNoStatus, true);
|
||||
},
|
||||
|
||||
// private method used to set our message notification deck to the correct value...
|
||||
updateMsgNotificationBar: function(aIndex, aSet)
|
||||
{
|
||||
var chunk = this.mBarFlagValues[aIndex];
|
||||
var status = aSet ? this.mBarStatus | chunk : this.mBarStatus & ~chunk;
|
||||
this.mBarStatus = status;
|
||||
|
||||
// the junk message takes precedence over the phishing message
|
||||
// which takes precedence over the remote content message
|
||||
if (status & this.mBarFlagValues[kMsgNotificationJunkBar])
|
||||
aIndex = kMsgNotificationJunkBar;
|
||||
else if (status & this.mBarFlagValues[kMsgNotificationPhishingBar])
|
||||
aIndex = kMsgNotificationPhishingBar;
|
||||
else if (status & this.mBarFlagValues[kMsgNotificationRemoteImages])
|
||||
aIndex = kMsgNotificationRemoteImages;
|
||||
else
|
||||
aIndex = kMsgNotificationNoStatus;
|
||||
|
||||
if (status == kMsgNotificationNoStatus)
|
||||
this.mMsgNotificationBar.setAttribute('collapsed', true);
|
||||
else
|
||||
this.mMsgNotificationBar.removeAttribute('collapsed');
|
||||
|
||||
this.mMsgNotificationBar.selectedIndex = aIndex;
|
||||
}
|
||||
|
||||
var junkBar = document.getElementById("junkBar");
|
||||
if (isJunk)
|
||||
junkBar.removeAttribute("collapsed");
|
||||
else
|
||||
junkBar.setAttribute("collapsed","true");
|
||||
|
||||
goUpdateCommand('button_junk');
|
||||
};
|
||||
|
||||
function LoadMsgWithRemoteContent()
|
||||
{
|
||||
// we want to get the msg hdr for the currently selected message
|
||||
// change the "remoteContentBar" property on it
|
||||
// then reload the message
|
||||
|
||||
setMsgHdrPropertyAndReload("remoteContentPolicy", kAllowRemoteContent);
|
||||
}
|
||||
|
||||
function MsgIsNotAScam()
|
||||
{
|
||||
// we want to get the msg hdr for the currently selected message
|
||||
// change the "isPhishingMsg" property on it
|
||||
// then reload the message
|
||||
|
||||
setMsgHdrPropertyAndReload("notAPhishMessage", kNotAPhishMessage);
|
||||
}
|
||||
|
||||
function setMsgHdrPropertyAndReload(aProperty, aValue)
|
||||
{
|
||||
// we want to get the msg hdr for the currently selected message
|
||||
// change the appropiate property on it then reload the message
|
||||
|
||||
var msgURI = GetLoadedMessage();
|
||||
|
||||
if (msgURI && !(/type=x-message-display/.test(msgURI)))
|
||||
{
|
||||
var msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
|
||||
if (msgHdr)
|
||||
{
|
||||
msgHdr.setUint32Property(aProperty, aValue);
|
||||
MsgReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkMsgHdrPropertyIsNot(aProperty, aValue)
|
||||
{
|
||||
// we want to get the msg hdr for the currently selected message,
|
||||
// get the appropiate property on it and then test against value.
|
||||
|
||||
var msgURI = GetLoadedMessage();
|
||||
|
||||
if (msgURI && !(/type=x-message-display/.test(msgURI)))
|
||||
{
|
||||
var msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
|
||||
return (msgHdr && msgHdr.getUint32Property(aProperty) != aValue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function MarkCurrentMessageAsRead()
|
||||
@@ -2099,6 +2219,11 @@ function ClearPendingReadTimer()
|
||||
}
|
||||
}
|
||||
|
||||
function OnMsgParsed(aUrl)
|
||||
{
|
||||
gMessageNotificationBar.setPhishingMsg(aUrl);
|
||||
}
|
||||
|
||||
function OnMsgLoaded(aUrl)
|
||||
{
|
||||
if (!aUrl)
|
||||
@@ -2117,14 +2242,11 @@ function OnMsgLoaded(aUrl)
|
||||
// SetNextMessageAfterDelete() when the operation completes (bug 243532).
|
||||
gNextMessageViewIndexAfterDelete = -2;
|
||||
|
||||
if (/type=x-message-display/.test(msgURI))
|
||||
SetUpJunkBar(null);
|
||||
else
|
||||
{
|
||||
if (!(/type=x-message-display/.test(msgURI)))
|
||||
msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
|
||||
SetUpJunkBar(msgHdr);
|
||||
}
|
||||
|
||||
|
||||
gMessageNotificationBar.setJunkMsg(msgHdr);
|
||||
|
||||
// we just finished loading a message. set a timer to actually mark the message as read after n seconds
|
||||
// where n can be configured by the user.
|
||||
var markReadOnADelay = gPrefBranch.getBoolPref("mailnews.mark_message_read.delay");
|
||||
@@ -2324,5 +2446,3 @@ function OpenOrFocusWindow(args, windowType, chromeURL)
|
||||
else
|
||||
window.openDialog(chromeURL, "", "chrome,resizable,status,centerscreen,dialog=no", args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -280,6 +280,8 @@
|
||||
<command id="cmd_markAsJunk" oncommand="goDoCommand('cmd_markAsJunk'); event.preventBubble()" disabled="true"/>
|
||||
<command id="cmd_markAsNotJunk" oncommand="goDoCommand('cmd_markAsNotJunk'); event.preventBubble()" disabled="true"/>
|
||||
<command id="cmd_recalculateJunkScore" oncommand="goDoCommand('cmd_recalculateJunkScore');" disabled="true"/>
|
||||
<command id="cmd_markAsShowRemote" oncommand="goDoCommand('cmd_markAsShowRemote'); event.preventBubble()" disabled="true"/>
|
||||
<command id="cmd_markAsNotPhish" oncommand="goDoCommand('cmd_markAsNotPhish'); event.preventBubble()" disabled="true"/>
|
||||
</commandset>
|
||||
|
||||
<commandset id="mailLabelMenuItems"
|
||||
@@ -328,6 +330,10 @@
|
||||
<key id="key_markJunk" key="&markAsJunkCmd.key;" oncommand="goDoCommand('cmd_markAsJunk');"/>
|
||||
<key id="key_markNotJunk" key="&markAsNotJunkCmd.key;" oncommand="goDoCommand('cmd_markAsNotJunk');"
|
||||
modifiers="shift"/>
|
||||
<key id="key_markShowRemote" key="&markAsShowRemoteCmd.key;" oncommand="goDoCommand('cmd_markAsShowRemote');"
|
||||
modifiers="shift"/>
|
||||
<key id="key_markNotPhish" key="&markAsNotPhishCmd.key;" oncommand="goDoCommand('cmd_markAsNotPhish');"
|
||||
modifiers="shift"/>
|
||||
<key id="key_markAllRead" key="&markAllReadCmd.key;" oncommand="goDoCommand('cmd_markAllRead');" modifiers="accel, shift"/>
|
||||
<key id="key_markThreadAsRead" key="&markThreadAsReadCmd.key;" oncommand="goDoCommand('cmd_markThreadAsRead')"/>
|
||||
<key id="key_markReadByDate" key="&markReadByDateCmd.key;" oncommand="goDoCommand('cmd_markReadByDate')"/>
|
||||
@@ -633,6 +639,12 @@
|
||||
<menuitem label="&recalculateJunkScoreCmd.label;"
|
||||
accesskey="&recalculateJunkScoreCmd.accesskey;"
|
||||
command="cmd_recalculateJunkScore"/>
|
||||
<menuitem label="&markAsShowRemoteCmd.label;"
|
||||
accesskey="&markAsShowRemoteCmd.accesskey;"
|
||||
command="cmd_markAsShowRemote"/>
|
||||
<menuitem label="&markAsNotPhishCmd.label;"
|
||||
accesskey="&markAsNotPhishCmd.accesskey;"
|
||||
command="cmd_markAsNotPhish"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
@@ -977,6 +989,12 @@
|
||||
<menuitem label="&recalculateJunkScoreCmd.label;"
|
||||
accesskey="&recalculateJunkScoreCmd.accesskey;"
|
||||
command="cmd_recalculateJunkScore"/>
|
||||
<menuitem label="&markAsShowRemoteCmd.label;"
|
||||
accesskey="&markAsShowRemoteCmd.accesskey;"
|
||||
command="cmd_markAsShowRemote"/>
|
||||
<menuitem label="&markAsNotPhishCmd.label;"
|
||||
accesskey="&markAsNotPhishCmd.accesskey;"
|
||||
command="cmd_markAsNotPhish"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator id="messagePaneContext-sep-labels-2"/>
|
||||
@@ -1610,6 +1628,14 @@
|
||||
<menuitem label="&recalculateJunkScoreCmd.label;"
|
||||
accesskey="&recalculateJunkScoreCmd.accesskey;"
|
||||
command="cmd_recalculateJunkScore"/>
|
||||
<menuitem label="&markAsShowRemoteCmd.label;"
|
||||
key="key_markShowRemote"
|
||||
accesskey="&markAsShowRemoteCmd.accesskey;"
|
||||
command="cmd_markAsShowRemote"/>
|
||||
<menuitem label="&markAsNotPhishCmd.label;"
|
||||
key="key_markNotPhish"
|
||||
accesskey="&markAsNotPhishCmd.accesskey;"
|
||||
command="cmd_markAsNotPhish"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
@@ -1827,13 +1853,34 @@
|
||||
accesskey="&advancedButton.accesskey;"/>
|
||||
</hbox>
|
||||
|
||||
<hbox id="junkBar" collapsed="true" align="center">
|
||||
<image id="junkBarImage"/>
|
||||
<label id="junkBarMessage" value="&junkBarMessage.label;"/>
|
||||
<spacer flex="1"/>
|
||||
<button label="&junkInfoButton.label;" oncommand="MsgJunkMailInfo(false)"/>
|
||||
<button label="&junkBarButton.label;" oncommand="JunkSelectedMessages(false)"/>
|
||||
</hbox>
|
||||
<!-- The msgNotificationBar appears on top of the message and displays
|
||||
information like: junk, contains remote images, or is a suspected phishing URL
|
||||
-->
|
||||
<deck id="msgNotificationBar" selectedIndex="0" collapsed="true">
|
||||
<hbox id="msgNotificationNoStatus"/>
|
||||
|
||||
<hbox id="junkBar" class="msgNotificationBar" align="center">
|
||||
<image id="junkBarImage"/>
|
||||
<description flex="1" class="msgNotificationBarText">&junkBarMessage.label;</description>
|
||||
<spacer flex="1"/>
|
||||
<button label="&junkInfoButton.label;" oncommand="MsgJunkMailInfo(false)"/>
|
||||
<button label="&junkBarButton.label;" oncommand="JunkSelectedMessages(false);"/>
|
||||
</hbox>
|
||||
|
||||
<hbox id="remoteContentBar" class="msgNotificationBar" align="center">
|
||||
<image id="remoteContentImage"/>
|
||||
<description flex="1" class="msgNotificationBarText">&remoteContentMessage.label;</description>
|
||||
<spacer flex="1"/>
|
||||
<button label="&loadRemoteContentButton.label;" oncommand="LoadMsgWithRemoteContent();"/>
|
||||
</hbox>
|
||||
|
||||
<hbox id="phishingBar" class="msgNotificationBar" align="center">
|
||||
<image id="phishingBarImage"/>
|
||||
<description flex="1" class="msgNotificationBarText">&phishingBarMessage.label;</description>
|
||||
<spacer flex="1"/>
|
||||
<button label="&removePhishingBarButton.label;" oncommand="MsgIsNotAScam();"/>
|
||||
</hbox>
|
||||
</deck>
|
||||
|
||||
<statusbar class="chromeclass-status" id="status-bar">
|
||||
<statusbarpanel id="component-bar"/>
|
||||
|
||||
@@ -655,6 +655,8 @@ var MessageWindowController =
|
||||
case "cmd_markAsJunk":
|
||||
case "cmd_markAsNotJunk":
|
||||
case "cmd_recalculateJunkScore":
|
||||
case "cmd_markAsShowRemote":
|
||||
case "cmd_markAsNotPhish":
|
||||
case "cmd_applyFilters":
|
||||
case "cmd_runJunkControls":
|
||||
case "cmd_deleteJunk":
|
||||
@@ -753,6 +755,10 @@ var MessageWindowController =
|
||||
case "button_file":
|
||||
case "cmd_file":
|
||||
return (gCurrentMessageUri != null);
|
||||
case "cmd_markAsShowRemote":
|
||||
return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("remoteContentPolicy", kAllowRemoteContent));
|
||||
case "cmd_markAsNotPhish":
|
||||
return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("notAPhishMessage", kNotAPhishMessage));
|
||||
case "cmd_printSetup":
|
||||
return true;
|
||||
case "cmd_getNewMessages":
|
||||
@@ -921,6 +927,12 @@ var MessageWindowController =
|
||||
case "cmd_recalculateJunkScore":
|
||||
analyzeMessagesForJunk();
|
||||
return;
|
||||
case "cmd_markAsShowRemote":
|
||||
LoadMsgWithRemoteContent();
|
||||
return;
|
||||
case "cmd_markAsNotPhish":
|
||||
MsgIsNotAScam();
|
||||
return;
|
||||
case "cmd_label0":
|
||||
gDBView.doCommand(nsMsgViewCommandType.label0);
|
||||
return;
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/messageWindow.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/accountUtils.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/mailContextMenus.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/phishingDetector.js"/>
|
||||
<script type="application/x-javascript" src="chrome://communicator/content/contentAreaClick.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsTransferable.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
|
||||
@@ -147,7 +148,7 @@
|
||||
ondragdrop="nsDragAndDrop.drop(event, messagepaneObserver);"
|
||||
ondragexit="nsDragAndDrop.dragExit(event, messagepaneObserver);">
|
||||
|
||||
<hbox id="junkBar"/>
|
||||
<deck id="msgNotificationBar"/>
|
||||
|
||||
<hbox id="msgHeaderView"/>
|
||||
|
||||
@@ -155,7 +156,7 @@
|
||||
<browser id="messagepane" context="messagePaneContext"
|
||||
style="height: 0px; min-height: 1px" flex="1" name="messagepane"
|
||||
disablesecurity="true" disablehistory="true" type="content-primary"
|
||||
src="about:blank" onclick="messagePaneOnClick(event);" autofind="false"/>
|
||||
src="about:blank" onclick="return messagePaneOnClick(event);" autofind="false"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/messengerdnd.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/accountUtils.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/mail-offline.js"/>
|
||||
<script type="application/x-javascript" src="chrome://messenger/content/phishingDetector.js"/>
|
||||
<script type="application/x-javascript" src="chrome://communicator/content/contentAreaClick.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsTransferable.js"/>
|
||||
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
|
||||
@@ -182,14 +183,14 @@
|
||||
</splitter>
|
||||
|
||||
<vbox id="messagepanebox" flex="2" minheight="100" height="200" minwidth="100" width="200" persist="collapsed height width" class="window-focusborder" focusring="false">
|
||||
<hbox id="junkBar"/>
|
||||
<deck id="msgNotificationBar"/>
|
||||
|
||||
<hbox id="msgHeaderView"/>
|
||||
|
||||
<browser id="messagepane" name="messagepane" height="0" flex="1"
|
||||
context="messagePaneContext" minwidth="1" minheight="1"
|
||||
disablesecurity="true" disablehistory="true" autofind="false"
|
||||
type="content-primary" onclick="messagePaneOnClick(event);"/>
|
||||
type="content-primary" onclick="return messagePaneOnClick(event);"/>
|
||||
</vbox>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
@@ -293,6 +293,7 @@ var messageHeaderSink = {
|
||||
gBuildAttachmentPopupForCurrentMsg = true;
|
||||
ClearAttachmentList();
|
||||
ClearEditMessageButton();
|
||||
gMessageNotificationBar.clearMsgNotifications();
|
||||
|
||||
for (var index in gMessageListeners)
|
||||
gMessageListeners[index].onStartHeaders();
|
||||
@@ -443,6 +444,7 @@ var messageHeaderSink = {
|
||||
|
||||
onEndMsgDownload: function(url)
|
||||
{
|
||||
OnMsgParsed(url);
|
||||
},
|
||||
|
||||
onEndMsgHeaders: function(url)
|
||||
@@ -452,6 +454,7 @@ var messageHeaderSink = {
|
||||
|
||||
onMsgHasRemoteContent: function(aMsgHdr)
|
||||
{
|
||||
gMessageNotificationBar.setRemoteContentMsg(aMsgHdr);
|
||||
},
|
||||
|
||||
mSecurityInfo : null,
|
||||
|
||||
@@ -1130,11 +1130,10 @@ function ClearMessagePane()
|
||||
gCurrentDisplayedMessage = null;
|
||||
if (GetMessagePaneFrame().location.href != "about:blank")
|
||||
GetMessagePaneFrame().location.href = "about:blank";
|
||||
|
||||
// hide the message header view AND the message pane...
|
||||
HideMessageHeaderPane();
|
||||
|
||||
// hide the junk bar
|
||||
SetUpJunkBar(null);
|
||||
gMessageNotificationBar.clearMsgNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
239
mozilla/mailnews/base/resources/content/phishingDetector.js
Executable file
239
mozilla/mailnews/base/resources/content/phishingDetector.js
Executable file
@@ -0,0 +1,239 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Thunderbird Phishing Dectector
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott MacGregor <mscott@mozilla.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ****** */
|
||||
|
||||
// Dependencies:
|
||||
// gPrefBranch, gBrandBundle, gMessengerBundle should already be defined
|
||||
// gatherTextUnder from utilityOverlay.js
|
||||
|
||||
const kPhishingNotSuspicious = 0;
|
||||
const kPhishingWithIPAddress = 1;
|
||||
const kPhishingWithMismatchedHosts = 2;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// isEmailScam --> examines the message currently loaded in the message pane
|
||||
// and returns true if we think that message is an e-mail scam.
|
||||
// Assumes the message has been completely loaded in the message pane (i.e. OnMsgParsed has fired)
|
||||
// aUrl: nsIURI object for the msg we want to examine...
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
function isMsgEmailScam(aUrl)
|
||||
{
|
||||
var isEmailScam = false;
|
||||
if (!aUrl || !gPrefBranch.getBoolPref("mail.phishing.detection.enabled"))
|
||||
return isEmailScam;
|
||||
|
||||
// Ignore nntp and RSS messages
|
||||
var folder = aUrl.folder;
|
||||
if (folder.server.type == 'nntp' || folder.server.type == 'rss')
|
||||
return isEmailScam;
|
||||
|
||||
// loop through all of the link nodes in the message's DOM, looking for phishing URLs...
|
||||
var msgDocument = document.getElementById('messagepane').contentDocument;
|
||||
|
||||
// examine all anchor tags...
|
||||
var anchorNodes = msgDocument.getElementsByTagName("a");
|
||||
for (var index = 0; index < anchorNodes.length && !isEmailScam; index++)
|
||||
isEmailScam = isPhishingURL(anchorNodes[index], true);
|
||||
|
||||
// if an e-mail contains a non-addressbook form element, then assume the message is
|
||||
// a phishing attack. Legitimate sites should not be using forms inside of e-mail
|
||||
if (!isEmailScam)
|
||||
{
|
||||
var forms = msgDocument.getElementsByTagName("form");
|
||||
for (var i = 0; i < forms.length && !isEmailScam; i++)
|
||||
isEmailScam = forms[i].action.search("addbook") != 0;
|
||||
}
|
||||
|
||||
// we'll add more checks here as our detector matures....
|
||||
return isEmailScam;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// isPhishingURL --> examines the passed in linkNode and returns true if we think
|
||||
// the URL is an email scam.
|
||||
// aLinkNode: the link node to examine
|
||||
// aSilentMode: don't prompt the user to confirm
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function isPhishingURL(aLinkNode, aSilentMode)
|
||||
{
|
||||
if (!gPrefBranch.getBoolPref("mail.phishing.detection.enabled"))
|
||||
return false;
|
||||
|
||||
var phishingType = kPhishingNotSuspicious;
|
||||
var href = aLinkNode.href;
|
||||
if (!href)
|
||||
return false;
|
||||
|
||||
var linkTextURL = {};
|
||||
var unobscuredHostName = {};
|
||||
var isPhishingURL = false;
|
||||
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
|
||||
hrefURL = ioService.newURI(href, null, null);
|
||||
|
||||
// only check for phishing urls if the url is an http or https link.
|
||||
// this prevents us from flagging imap and other internally handled urls
|
||||
if (hrefURL.schemeIs('http') || hrefURL.schemeIs('https'))
|
||||
{
|
||||
unobscuredHostName.value = hrefURL.host;
|
||||
|
||||
if (hostNameIsIPAddress(hrefURL.host, unobscuredHostName))
|
||||
phishingType = kPhishingWithIPAddress;
|
||||
else if (misMatchedHostWithLinkText(aLinkNode, hrefURL, linkTextURL))
|
||||
phishingType = kPhishingWithMismatchedHosts;
|
||||
|
||||
isPhishingURL = phishingType != kPhishingNotSuspicious;
|
||||
|
||||
if (!aSilentMode && isPhishingURL) // allow the user to override the decision
|
||||
isPhishingURL = confirmSuspiciousURL(phishingType, unobscuredHostName.value);
|
||||
}
|
||||
|
||||
return isPhishingURL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// helper methods in support of isPhishingURL
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function misMatchedHostWithLinkText(aLinkNode, aHrefURL, aLinkTextURL)
|
||||
{
|
||||
var linkNodeText = gatherTextUnder(aLinkNode);
|
||||
// only worry about http and https urls
|
||||
if (linkNodeText)
|
||||
{
|
||||
// does the link text look like a http url?
|
||||
if (linkNodeText.search(/(^http:|^https:)/) != -1)
|
||||
{
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
|
||||
linkTextURL = ioService.newURI(linkNodeText, null, null);
|
||||
aLinkTextURL.value = linkTextURL;
|
||||
return aHrefURL.host != linkTextURL.host;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns true if the hostName is an IP address
|
||||
// if the host name is an obscured IP address, returns the unobscured host
|
||||
function hostNameIsIPAddress(aHostName, aUnobscuredHostName)
|
||||
{
|
||||
// TODO: Add Support for IPv6
|
||||
|
||||
var index;
|
||||
|
||||
// scammers frequently obscure the IP address by encoding each component as octal, hex
|
||||
// or in some cases a mix match of each. The IP address could also be represented as a DWORD.
|
||||
|
||||
// break the IP address down into individual components.
|
||||
var ipComponents = aHostName.split(".");
|
||||
|
||||
// if we didn't find at least 4 parts to our IP address it either isn't a numerical IP
|
||||
// or it is encoded as a dword
|
||||
if (ipComponents.length < 4)
|
||||
{
|
||||
// Convert to a binary to test for possible DWORD.
|
||||
var binaryDword = parseInt(aHostName).toString(2);
|
||||
|
||||
if (isNaN(binaryDword))
|
||||
return false;
|
||||
|
||||
// convert the dword into its component IP parts.
|
||||
ipComponents =
|
||||
[
|
||||
(aHostName >> 24) & 255,
|
||||
(aHostName >> 16) & 255,
|
||||
(aHostName >> 8) & 255,
|
||||
(aHostName & 255)
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < ipComponents.length; index++)
|
||||
{
|
||||
// by leaving the radix parameter blank, we can handle IP addresses
|
||||
// where one component is hex, another is octal, etc.
|
||||
ipComponents[index] = parseInt(ipComponents[index]);
|
||||
}
|
||||
}
|
||||
|
||||
// make sure each part of the IP address is in fact a number
|
||||
for (index = 0; index < ipComponents.length; index++)
|
||||
if (isNaN(ipComponents[index])) // if any part of the IP address is not a number, then we can safely return
|
||||
return false;
|
||||
|
||||
// only set aUnobscuredHostName if we are looking at an IPv4 host name
|
||||
var hostName = ipComponents.join(".");
|
||||
if (isIPv4HostName(hostName))
|
||||
{
|
||||
aUnobscuredHostName.value = hostName;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isIPv4HostName(aHostName)
|
||||
{
|
||||
var ipv4HostRegExp = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/); // IPv4
|
||||
// treat 0.0.0.0 as an invalid IP address
|
||||
return ipv4HostRegExp.test(aHostName) && aHostName != '0.0.0.0';
|
||||
}
|
||||
|
||||
// returns true if the user confirms the URL is a scam
|
||||
function confirmSuspiciousURL(aPhishingType, aSuspiciousHostName)
|
||||
{
|
||||
var brandShortName = gBrandBundle.getString("brandShortName");
|
||||
var titleMsg = gMessengerBundle.getString("confirmPhishingTitle");
|
||||
var dialogMsg = null;
|
||||
|
||||
switch (aPhishingType)
|
||||
{
|
||||
case kPhishingWithIPAddress:
|
||||
case kPhishingWithMismatchedHosts:
|
||||
dialogMsg = gMessengerBundle.getFormattedString("confirmPhishingUrl" + aPhishingType, [brandShortName, aSuspiciousHostName], 2);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsIPS = Components.interfaces.nsIPromptService;
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(nsIPS);
|
||||
var buttons = nsIPS.STD_YES_NO_BUTTONS + nsIPS.BUTTON_POS_1_DEFAULT;
|
||||
return promptService.confirmEx(window, titleMsg, dialogMsg, buttons, "", "", "", "", {}); /* the yes button is in position 0 */
|
||||
}
|
||||
@@ -437,6 +437,12 @@
|
||||
<!ENTITY markAsNotJunkCmd.key "j">
|
||||
<!ENTITY recalculateJunkScoreCmd.label "Run Junk Mail Controls">
|
||||
<!ENTITY recalculateJunkScoreCmd.accesskey "C">
|
||||
<!ENTITY markAsShowRemoteCmd.label "Show Remote Content">
|
||||
<!ENTITY markAsShowRemoteCmd.accesskey "e">
|
||||
<!ENTITY markAsShowRemoteCmd.key "r">
|
||||
<!ENTITY markAsNotPhishCmd.label "As Not Scam">
|
||||
<!ENTITY markAsNotPhishCmd.accesskey "S">
|
||||
<!ENTITY markAsNotPhishCmd.key "p">
|
||||
<!ENTITY openMessageWindowCmd.label "Open Message">
|
||||
<!ENTITY openMessageWindowCmd.accesskey "O">
|
||||
<!ENTITY openMessageWindowCmd.key "o">
|
||||
@@ -585,8 +591,15 @@
|
||||
<!ENTITY deleteJunk.label "Delete Mail Marked as Junk in Folder">
|
||||
<!ENTITY deleteJunk.accesskey "e">
|
||||
|
||||
<!-- junk bar -->
|
||||
<!ENTITY junkBarMessage.label "&brandShortName; thinks this message is junk mail">
|
||||
<!-- Junk Bar -->
|
||||
<!ENTITY junkBarMessage.label "&brandShortName; thinks this message is junk.">
|
||||
<!ENTITY junkBarButton.label "This is Not Junk">
|
||||
<!ENTITY junkInfoButton.label "?">
|
||||
|
||||
<!-- Remote Content Bar -->
|
||||
<!ENTITY remoteContentMessage.label "To protect your privacy, &brandShortName; has blocked remote content in this message.">
|
||||
<!ENTITY loadRemoteContentButton.label "Show Remote Content">
|
||||
|
||||
<!-- Phishing Bar -->
|
||||
<!ENTITY phishingBarMessage.label "&brandShortName; thinks this message might be an email scam.">
|
||||
<!ENTITY removePhishingBarButton.label "Not a Scam">
|
||||
|
||||
@@ -365,3 +365,9 @@ alertNoSearchFoldersSelected=You must choose at least one folder to search for t
|
||||
# LOCALIZATION NOTES(????ByteAbbreviation): Do not translate %d below, it is the size of the message/folder
|
||||
kiloByteAbbreviation=%dKB
|
||||
megaByteAbbreviation=%dMB
|
||||
|
||||
# Warnings to alert users about phishing urls
|
||||
confirmPhishingTitle=Email Scam Alert
|
||||
#LOCALIZATION NOTE %1$S is the brand name, %2$S is the host name of the url being visited
|
||||
confirmPhishingUrl1=%1$S thinks this site is suspicious! It may be trying to impersonate the web page you want to visit. Most legitimate sites use names instead of numbers. Are you sure you want to visit %2$S?
|
||||
confirmPhishingUrl2=%1$S thinks this site is suspicious! It may be trying to impersonate the web page you want to visit. Are you sure you want to visit %2$S?
|
||||
|
||||
@@ -143,6 +143,7 @@ messenger.jar:
|
||||
content/messenger/junkMail.xul (base/resources/content/junkMail.xul)
|
||||
content/messenger/junkMail.js (base/resources/content/junkMail.js)
|
||||
* content/messenger/junkMailInfo.xul (base/resources/content/junkMailInfo.xul)
|
||||
content/messenger/phishingDetector.js (base/resources/content/phishingDetector.js)
|
||||
content/messenger/SearchDialog.xul (base/search/resources/content/SearchDialog.xul)
|
||||
content/messenger/ABSearchDialog.xul (base/search/resources/content/ABSearchDialog.xul)
|
||||
content/messenger/SearchDialog.js (base/search/resources/content/SearchDialog.js)
|
||||
|
||||
@@ -518,6 +518,7 @@ pref("news.cancel.confirm",true);
|
||||
pref("news.cancel.alert_on_success",true);
|
||||
pref("mail.SpellCheckBeforeSend",false);
|
||||
pref("mail.spellcheck.inline",true);
|
||||
pref("mail.phishing.detection.enabled", true); // enable / disable phishing detection for link clicks
|
||||
pref("mail.warn_on_send_accel_key", true);
|
||||
pref("mail.enable_autocomplete",true);
|
||||
pref("mailnews.html_domains","");
|
||||
|
||||
@@ -429,6 +429,7 @@ classic.jar:
|
||||
skin/classic/messenger/icons/message-news-new-attach-off.gif (messenger/icons/message-news-new-attach-off.gif)
|
||||
skin/classic/messenger/icons/message-news-new-offl.gif (messenger/icons/message-news-new-offl.gif)
|
||||
skin/classic/messenger/icons/message-news-offl.gif (messenger/icons/message-news-offl.gif)
|
||||
skin/classic/messenger/icons/remote-blocked.png (messenger/icons/remote-blocked.png)
|
||||
skin/classic/messenger/icons/server-local.gif (messenger/icons/server-local.gif)
|
||||
skin/classic/messenger/icons/server-local-new.gif (messenger/icons/server-local-new.gif)
|
||||
skin/classic/messenger/icons/server-mail.gif (messenger/icons/server-mail.gif)
|
||||
|
||||
BIN
mozilla/themes/classic/messenger/icons/remote-blocked.png
Executable file
BIN
mozilla/themes/classic/messenger/icons/remote-blocked.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
@@ -242,21 +242,30 @@
|
||||
-moz-image-region: rect(21px 88px 42px 66px) !important;
|
||||
}
|
||||
|
||||
#junkBarImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/junkBar.gif");
|
||||
/* ::::: message notification bar style rules ::::: */
|
||||
|
||||
.msgNotificationBar {
|
||||
border-bottom: 1px solid;
|
||||
-moz-border-bottom-colors: #000000;
|
||||
-moz-appearance: toolbox;
|
||||
background-color: #C7BC8F;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#junkBarMessage {
|
||||
.msgNotificationBarText {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#junkBar {
|
||||
border-bottom: 1px solid;
|
||||
-moz-border-bottom-colors: #000000;
|
||||
background-color: #C7BC8F;
|
||||
#junkBarImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/junkBar.gif");
|
||||
}
|
||||
|
||||
#junkIcon {
|
||||
margin-left: 0.5ex;
|
||||
list-style-image: url("chrome://messenger/skin/icons/folder-junk.gif");
|
||||
}
|
||||
|
||||
#remoteContentImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/remote-blocked.png");
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@@ -396,6 +396,7 @@ modern.jar:
|
||||
skin/modern/messenger/icons/message-news-offl.gif (messenger/icons/message-news-offl.gif)
|
||||
skin/modern/messenger/icons/readcol-read.gif (messenger/icons/readcol-read.gif)
|
||||
skin/modern/messenger/icons/readcol-unread.gif (messenger/icons/readcol-unread.gif)
|
||||
skin/modern/messenger/icons/remote-blocked.png (messenger/icons/remote-blocked.png)
|
||||
skin/modern/messenger/icons/server-local-new.gif (messenger/icons/server-local-new.gif)
|
||||
skin/modern/messenger/icons/server-local.gif (messenger/icons/server-local.gif)
|
||||
skin/modern/messenger/icons/server-mail-new.gif (messenger/icons/server-mail-new.gif)
|
||||
|
||||
BIN
mozilla/themes/modern/messenger/icons/remote-blocked.png
Executable file
BIN
mozilla/themes/modern/messenger/icons/remote-blocked.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
@@ -254,22 +254,30 @@
|
||||
-moz-image-region: rect(68px 199px 101px 150px) !important;
|
||||
}
|
||||
|
||||
#junkBarImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/junkBar.gif");
|
||||
/* ::::: message notification bar style rules ::::: */
|
||||
|
||||
.msgNotificationBar {
|
||||
border-bottom: 1px solid;
|
||||
-moz-border-bottom-colors: #000000;
|
||||
-moz-appearance: toolbox;
|
||||
background-color: #C7BC8F;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#junkBarMessage {
|
||||
.msgNotificationBarText {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#junkBar {
|
||||
border-bottom: 1px solid;
|
||||
-moz-border-bottom-colors: #000000;
|
||||
background-color: #C7BC8F;
|
||||
#junkBarImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/junkBar.gif");
|
||||
}
|
||||
|
||||
|
||||
#junkIcon {
|
||||
margin-left: 0.3ex;
|
||||
list-style-image: url("chrome://messenger/skin/icons/message-junk-other.gif");
|
||||
}
|
||||
|
||||
#remoteContentImage {
|
||||
list-style-image: url("chrome://messenger/skin/icons/remote-blocked.png");
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@@ -110,10 +110,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
function hrefForClickEvent(event)
|
||||
function hrefAndLinkNodeForClickEvent(aParams)
|
||||
{
|
||||
var event = aParams.event;
|
||||
var target = event.target;
|
||||
var linkNode;
|
||||
var href = aParams.href;
|
||||
var linkNode = aParams.linkNode;
|
||||
|
||||
var isKeyPress = (event.type == "keypress");
|
||||
|
||||
@@ -142,7 +144,7 @@
|
||||
if (linkNode && !linkNode.hasAttribute("href"))
|
||||
linkNode = null;
|
||||
}
|
||||
var href;
|
||||
|
||||
if (linkNode) {
|
||||
href = linkNode.href;
|
||||
} else {
|
||||
@@ -155,11 +157,13 @@
|
||||
}
|
||||
linkNode = linkNode.parentNode;
|
||||
}
|
||||
if (href && href != "") {
|
||||
if (href) {
|
||||
href = makeURLAbsolute(linkNode.baseURI, href);
|
||||
}
|
||||
}
|
||||
return href;
|
||||
|
||||
aParams.href = href;
|
||||
aParams.linkNode = linkNode;
|
||||
}
|
||||
|
||||
// Called whenever the user clicks in the content area,
|
||||
@@ -172,7 +176,9 @@
|
||||
}
|
||||
|
||||
var isKeyPress = (event.type == "keypress");
|
||||
var href = hrefForClickEvent(event);
|
||||
var ceParams = {event: event, href: "", linkNode: null};
|
||||
hrefAndLinkNodeForClickEvent(ceParams);
|
||||
var href = ceParams.href;
|
||||
if (href) {
|
||||
if (isKeyPress) {
|
||||
openNewTabWith(href, true, event.shiftKey);
|
||||
@@ -180,6 +186,10 @@
|
||||
}
|
||||
else {
|
||||
handleLinkClick(event, href, null);
|
||||
// if in mailnews block the link left click if we determine
|
||||
// that this URL is phishy (i.e. a potential email scam)
|
||||
if ("gMessengerBundle" in this && !event.button)
|
||||
return !isPhishingURL(ceParams.linkNode, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -362,11 +372,11 @@
|
||||
} // for
|
||||
}
|
||||
|
||||
function makeURLAbsolute( base, url )
|
||||
function makeURLAbsolute(base, url)
|
||||
{
|
||||
// Construct nsIURL.
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var baseURI = ioService.newURI(base, null, null);
|
||||
|
||||
return ioService.newURI(baseURI.resolve(url), null, null).spec;
|
||||
|
||||
Reference in New Issue
Block a user