3

I'm trying to make a web page that gets an email header from user. when a user clicks a button to analyse the page sees the code and finds out source ip addresses from the header of the email. then this web page queries to freegeoip.com with the number of ip addresses that are extracted.

here is the problem. no matter how many ip addresses i got from an email header, my code only runs the ajax function one time, then no requests anymore.

could you help me with this please?

var myLatlngArray;

function iAnalyse()
{
  //document.getElementById("result").innerHTML
  //document.getElementById("headerValue").value;

  var lines = document.getElementById("headerValue").value.split('\n');
  var ipAddrs = [];
  var cnt=0;

  for(i=0; i<lines.length; i++)
  {
  	if(lines[i].startsWith("Received: from"))
  	{
  		ipAddrs[cnt++]=ipAddr=lines[i].substring(lines[i].lastIndexOf("[")+1,lines[i].lastIndexOf("]"));
  	}
  }
  myLatlngArray=new Array(cnt);

  for(j=0;j<cnt;j++)
  	getIPaddress(ipAddrs[j]);

  //alert(ipAddrs.length);
}

//http://stackoverflow.com/questions/646628/how-to-check-if-a-string-startswith-another-string
if (typeof String.prototype.startsWith != 'function') {
  // see below for better implementation!
  String.prototype.startsWith = function (str){
    return this.indexOf(str) == 0;
  };
}

var xHRObject = false;
if (window.XMLHttpRequest)
{
  xHRObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
  xHRObject = new ActiveXObject("Microsoft.XMLHTTP");
}

function getIPaddress(ipAddrs)
{
	xHRObject.open("GET", "http://freegeoip.net/json/"+ipAddrs+"?t=" + Math.random(),true);
	xHRObject.onreadystatechange = getData;
  	xHRObject.send(null);
}

var aList=0;

function getData()
{
  if ((xHRObject.readyState == 4) && (xHRObject.status == 200))
  {
    if (window.XMLHttpRequest)
    {
      alert("abc"); //codes here should be run as many as the number of cnt in iAnalyse function, but it is called only once..
      var jsonObj = JSON.parse(xHRObject.responseText);
      myLatlngArray[aList]=new Array(2);
	    myLatlngArray[aList][0]=jsonObj.latitude;
	    myLatlngArray[aList][1]=jsonObj.longitude;
      aList++;
      xHRObject = new XMLHttpRequest();
      //google.maps.event.addDomListener(window, 'load', initialize());

    }
  }
}
<!DOCTYPE html>
<html>
  <head>
    <title>TEST</title>
    <script src="analyse.js"></script>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
      html, body, #googleMap {
        width:1000px;
        height:500px;
      }
    </style>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
  </head>
  <body>
    <p>IT Security &nbsp;&nbsp;&nbsp;<button onclick="iAnalyse()">Analyse it!</button> </p>
    <textarea id="headerValue" rows="10" cols="140">Past your email header here.</textarea>
    <p><div id="googleMap"></div></p>
  </body>
</html>

You can use the following code for test email header to put in the textarea.

`Delivered-To: [email protected]
Received: by 10.216.7.2 with SMTP id 2csp890396weo;
        Sat, 13 Sep 2014 10:51:53 -0700 (PDT)
X-Received: by 10.236.230.70 with SMTP id i66mr19664921yhq.26.1410630711344;
        Sat, 13 Sep 2014 10:51:51 -0700 (PDT)
Return-Path: <[email protected]>
Received: from iflip4 ([108.166.68.249])
        by mx.google.com with ESMTPS id 24si1044060yhd.26.2014.09.13.10.51.49
        for <multiple recipients>
        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Sat, 13 Sep 2014 10:51:51 -0700 (PDT)
Received-SPF: permerror (google.com: permanent error in processing during lookup of [email protected]) client-ip=108.166.68.249;
Authentication-Results: mx.google.com;
       spf=permerror (google.com: permanent error in processing during lookup of [email protected]) [email protected];
       dmarc=fail (p=NONE dis=NONE) header.from=ebay.com.au
Message-Id: <54148437.a401ec0a.35e9.ffffe2e6SMTPIN_ADDED_MISSING@mx.google.com>
Received: from [194.1.180.85] (port=12990 helo=User)
  by iflip4 with esmtpa (Exim 4.82)
  (envelope-from <[email protected]>)
  id 1XRT9o-0006MC-PP; Tue, 09 Sep 2014 21:41:02 +0000
From: "PayPal"<[email protected]>
`
5
  • Does getData() get called each time, then it fails the checks there? Else, is getIPaddress called each time - i.e. are you throwing out the expected number of GETs? When you iterate the ipAddrs[] array, you might wish to stagger your http requests by way of setTimeout perhaps? Commented Sep 26, 2014 at 14:55
  • 2
    You are canceling the previous ajax request each time you call getIPaddress as the it hasn't had time to process so it cancels the previous one and starts the new one Commented Sep 26, 2014 at 14:58
  • As @PatrickEvans said, you are cancelling the previous ajax request on every getIPaddress call. You should instantiate a new XHR on every call and use closures to provide access to the XHR object from the callback function. Commented Sep 26, 2014 at 15:19
  • You're destroying your own requests. I can't remember the native addition, but jQuery has an async parameter to it's ajax requests if sync requests are required [api.jquery.com/jquery.ajax]. Commented Sep 26, 2014 at 15:22
  • This is too much code, please pare it down. Also, please do not waste space with ActiveX logic which is needed only for IE6. Commented Sep 26, 2014 at 15:49

2 Answers 2

1

If you have more than one AJAX task on your website, you should create ONE standard function for creating the XMLHttpRequest object, and call this for each AJAX task.

http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp

Try something like this:

function createXhr(){
  var xHRObject = false;
  if (window.XMLHttpRequest) {
    xHRObject = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    xHRObject = new ActiveXObject("Microsoft.XMLHTTP");
  }
  return xHrObject;
}

and then you can:

function getIPaddress(ipAddrs) {
  var xHRObject = createXhr();
  ...
}

and:

function getData(event){
  var xHrObject = event.target;
  ...
}

If you are concerned about CORS, you might want to try something like this:

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {
    // XHR for Chrome/Firefox/Opera/Safari.
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != "undefined") {
    // XDomainRequest for IE 9 and earlier.
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    // CORS not supported.
    xhr = null;
  }
  return xhr;
}

source: http://docs.webplatform.org/wiki/apis/xhr/XMLHttpRequest

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah that looks more like how to make any trivial thing work in IE :) nice one
1

Your code had a few problems, the closure actually wasn't one. But you actually had a single xhr request you used for all your requests, that doesn't work out. You need to create a new instance of the XMLHttpRequest for every request. That should solve it :)

By moving the response handler function in the scope of your request function you can access the original xhr request through the closure generated.

(btw I'm not sure if I normalized the XMLHttpRequest Interface correctly for microsofts "thing", it's basically just a guess.)

var myLatlngArray;

function iAnalyse(){
  var lines = document.getElementById("headerValue").value.split('\n');
  var ipAddrs = [];
  var cnt=0;

  for(i=0; i<lines.length; i++){
    if(lines[i].startsWith("Received: from")){
        ipAddrs[cnt++]=ipAddr=lines[i].substring(lines[i].lastIndexOf("[")+1,lines[i].lastIndexOf("]"));
    }
  }
  myLatlngArray=new Array(cnt);
  for(j=0;j<cnt;j++){
    getIPaddress(ipAddrs[j]);
  }
}
if (typeof String.prototype.startsWith != 'function') {
  String.prototype.startsWith = function (str){
    return this.indexOf(str) == 0;
  };
}
window.XMLHttpRequest=XMLHttpRequest||function(){
  return ActiveXObject&&ActiveXObject("Microsoft.XMLHTTP")
};


function getIPaddress(ipAddrs){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "http://freegeoip.net/json/"+ipAddrs+"?t=" + Math.random(),true);
  xhr.onreadystatechange = getData;
  xhr.send(null);

  function getData(){
    if(xhr.readyState == xhr.DONE && xhr.status == 200){
      var jsonObj = JSON.parse(xhr.responseText);
      myLatlngArray[aList]=new Array(2);
      myLatlngArray[aList][0]=jsonObj.latitude;
      myLatlngArray[aList][1]=jsonObj.longitude;
      aList++;
    }
  }
}

var aList=0;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.