Bug 756821 - Port |Bug 305089: Don't mark as scam any mail composed by user (Drafts, Templates, Sent, Outbox folders)| and non-IPv6 parts of |Bug 362434: Add IPv6 support to phishingDetector.js| r=neil a=Callek
authorIan Neal <iann_cvs@blueyonder.co.uk>
Sun, 20 May 2012 16:40:00 -0400
changeset 11323 f7430f8d47df75d8aec53b5e541f8c88e287e7ac
parent 11322 132d65201b8d0f35917a28fa50c651a152c7cbf3
child 11324 b26e8f8161e27ec3c7726e39e739dbfb4980ec0a
push id498
push userCallek@gmail.com
push dateMon, 21 May 2012 05:25:57 +0000
treeherdercomm-beta@cd00c74eef12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersneil, Callek
bugs756821, 305089, 362434
Bug 756821 - Port |Bug 305089: Don't mark as scam any mail composed by user (Drafts, Templates, Sent, Outbox folders)| and non-IPv6 parts of |Bug 362434: Add IPv6 support to phishingDetector.js| r=neil a=Callek
suite/mailnews/phishingDetector.js
--- a/suite/mailnews/phishingDetector.js
+++ b/suite/mailnews/phishingDetector.js
@@ -51,24 +51,36 @@ const kPhishingWithMismatchedHosts = 2;
 // 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
-  // nsIMsgMailNewsUrl.folder can throw an error, especially if we are opening
-  // a .eml message.
   try {
-    var serverType = aUrl.folder.server.type;
-    if (serverType == 'nntp' || serverType == 'rss')
+    // nsIMsgMailNewsUrl.folder can throw an NS_ERROR_FAILURE, especially if
+    // we are opening an .eml file.
+    var folder = aUrl.folder;
+
+    // Ignore NNTP and RSS messages.
+    if (folder.server.type == 'nntp' || folder.server.type == 'rss')
       return isEmailScam;
-  } catch (ex) {}
+
+    // Also ignore messages in Sent/Drafts/Templates/Outbox.
+    const nsMsgFolderFlags = Components.interfaces.nsMsgFolderFlags;
+    let outgoingFlags = nsMsgFolderFlags.SentMail | nsMsgFolderFlags.Drafts |
+                        nsMsgFolderFlags.Templates | nsMsgFolderFlags.Queue;
+    if (folder.isSpecialFolder(outgoingFlags, true))
+      return isEmailScam;
+
+  } catch (ex) {
+    if (ex.result != Components.results.NS_ERROR_FAILURE)
+      throw ex;
+  }
 
   // loop through all of the link nodes in the message's DOM, looking for phishing URLs...
   var msgDocument = document.getElementById('messagepane').contentDocument;
   var index;
 
   // examine all links...
   var linkNodes = msgDocument.links;
   for (index = 0; index < linkNodes.length && !isEmailScam; index++)
@@ -101,36 +113,34 @@ function isPhishingURL(aLinkNode, aSilen
     return false;
 
   var phishingType = kPhishingNotSuspicious;
   var href = aHref || aLinkNode.href;
   if (!href)
     return false;
 
   var linkTextURL = {};
-  var unobscuredHostName = {};
   var isPhishingURL = false;
 
   var hrefURL = Services.io.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) && !isLocalIPAddress(unobscuredHostName))
+    var ipAddress = hostNameIsIPAddress(hrefURL.host);
+    if (ipAddress && !isLocalIPAddress(ipAddress))
       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);
+      isPhishingURL = confirmSuspiciousURL(phishingType, hrefURL.host);
   }
 
   return isPhishingURL;
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // helper methods in support of isPhishingURL
 //////////////////////////////////////////////////////////////////////////////
@@ -154,19 +164,18 @@ function misMatchedHostWithLinkText(aLin
        // compare hosts, but ignore possible www. prefix
        return !(aHrefURL.host.replace(/^www\./, "") == aLinkTextURL.value.host.replace(/^www\./, ""));
      }
   }
 
   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)
+// returns the unobscured host (if there is one), otherwise null
+function hostNameIsIPAddress(aHostName)
 {
   // 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.
 
@@ -175,17 +184,17 @@ function hostNameIsIPAddress(aHostName, 
 
   // 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;
+      return null;
 
     // convert the dword into its component IP parts.
     ipComponents =
     [
       (aHostName >> 24) & 255,
       (aHostName >> 16) & 255,
       (aHostName >>  8) & 255,
       (aHostName & 255)
@@ -199,27 +208,21 @@ function hostNameIsIPAddress(aHostName, 
       // 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;
+      return null;
 
-  // only set aUnobscuredHostName if we are looking at an IPv4 host name
+  // only return unobscured host name if we are looking at an IPv4 host name
   var hostName = ipComponents.join(".");
-  if (isIPv4HostName(hostName))
-  {
-    aUnobscuredHostName.value = hostName;
-    return true;
-  }
-
-  return false;
+  return isIPv4HostName(hostName) ? hostName : null;
 }
 
 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';
 }
@@ -244,15 +247,15 @@ function confirmSuspiciousURL(aPhishingT
   var buttons = Services.prompt.STD_YES_NO_BUTTONS +
                 Services.prompt.BUTTON_POS_1_DEFAULT;
   return Services.prompt.confirmEx(window, titleMsg, dialogMsg, buttons, "", "", "", "", {}); /* the yes button is in position 0 */
 }
 
 // returns true if the IP address is a local address.
 function isLocalIPAddress(unobscuredHostName)
 {
-  var ipComponents = unobscuredHostName.value.split(".");
+  var ipComponents = unobscuredHostName.split(".");
 
   return ipComponents[0] == 10 ||
          (ipComponents[0] == 192 && ipComponents[1] == 168) ||
          (ipComponents[0] == 169 && ipComponents[1] == 254) ||
          (ipComponents[0] == 172 && ipComponents[1] >= 16 && ipComponents[1] < 32);
 }