soum
soum

Reputation: 1159

Match IP with a range stored in an array

I am returning an IP and then comparing it from a range.

I am just looking at the US IP and if it falls in a range I am displaying a messge. I am getting the IP correctly but when I am trying to match it with the range I am getting a syntax error of unexpected range. How should I resolve this?

here is how my code looks like

$.getJSON("http://jsonip.com", function (data) {
    var x = data.ip;
    $('body').html(x);

    var usRange = [3.0.0.0, 222.229.21.255];
    if (x >= usRange[0] && x <= usRange[1]) {
        alert('US');
    } else alert('outside US');
});

Here is my fiddle

Upvotes: 1

Views: 5062

Answers (2)

SaltedBlowfish
SaltedBlowfish

Reputation: 105

I decided to rewrite my answer here for the sake of a better method. The first method actually converts the IP addresses to integers using bit shifting and then compares the integer values. I've left the second answer as an option but I prefer the first.

Neither of these functions will validate your IP addresses!

Method 1: Bit Shifting

/**
 * Checks if an IP address is within range of 2 other IP addresses
 * @param  {String}  ip         IP to validate
 * @param  {String}  lowerBound The lower bound of the range
 * @param  {String}  upperBound The upper bound of the range
 * @return {Boolean}            True or false
 */
function isWithinRange(ip, lowerBound, upperBound) {

  // Put all IPs into one array for iterating and split all into their own 
  // array of segments
  var ips = [ip.split('.'), lowerBound.split('.'), upperBound.split('.')];

  // Convert all IPs to ints
  for(var i = 0; i < ips.length; i++) {

    // Typecast all segments of all ips to ints
    for(var j = 0; j < ips[i].length; j++) {
      ips[i][j] = parseInt(ips[i][j]);
    }

    // Bit shift each segment to make it easier to compare
    ips[i] = 
      (ips[i][0] << 24) + 
      (ips[i][1] << 16) + 
      (ips[i][2] << 8) + 
      (ips[i][3]);
  }

  // Do comparisons
  if(ips[0] >= ips[1] && ips[0] <= ips[2]) return true;

  return false;
}

Method 2: Plain 'Ol Logic Mess

/**
 * Checks if an IP address is within range of 2 other IP addresses
 * @param  {String}  ip         IP to validate
 * @param  {String}  lowerBound The lower bound of the range
 * @param  {String}  upperBound The upper bound of the range
 * @return {Boolean}            True or false
 */
function isWithinRange(ip, lowerBound, upperBound) {

  // Save us some processing time if the IP equals either the lower bound or 
  // upper bound
  if (ip === lowerBound || ip === upperBound) return true;

  // Split IPs into arrays for iterations below. Use same variables since 
  // we won't need them as strings anymore and because someone will complain 
  // about wasting memory.
  ip = ip.split('.');
  lowerBound = lowerBound.split('.');
  upperBound = upperBound.split('.');

  // A nice, classic for loop iterating over each segment in the IP address
  for (var i = 0; i < 4; i++) {

    // We need those segments to be converted to ints or our comparisons 
    // will not work!
    ip[i] = parseInt(ip[i]);
    lowerBound[i] = parseInt(lowerBound[i]);
    upperBound[i] = parseInt(upperBound[i]);

    // If this is our first iteration, just make sure the first segment 
    // falls within or equal to the range values
    if (i === 0) {
      if (ip[i] < lowerBound[i] || ip[i] > upperBound[i]) {
        return false;
      }
    }

    // If the last segment was equal to the corresponding lower bound 
    // segment, make sure that the current segment is greater
    if (ip[i - 1] === lowerBound[i - 1]) {
      if (ip[i] < lowerBound[i]) return false;
    }

    // If the last segment was equal to the corresponding upper bound 
    // segment, make sure that the current segment is less than
    if (ip[i - 1] === upperBound[i - 1]) {
      if (ip[i] > upperBound[i]) return false;
    }
  }

  return true;
}

Upvotes: 3

Praveen
Praveen

Reputation: 56509

What the error means, you can't assign number with 4 decimal dots.

var usRange = [3.0.0.0, 222.229.21.255]; //Not possible

FYI: The IP address returned from the json is string, not a number.

So you approach won't work. Here check my approach,

1) Split the ip address based on . returned by $.getJSON

var x = data.ip.split('.');  // returns ["122", "164", "17", "211"]

2) Instead of using usRange array just do it with simple comparison operations.

3) You cannot compare strings with numbers, so convert those strings to numbers like

+x[0] //convert "122" to 122

Finally,

$.getJSON("http://jsonip.com", function (data) {
    var x = data.ip.split('.');
    if (+x[0] >= 3 && +x[0] <= 222) {
        if (+x[1] >= 0 && +x[1] <= 229) {
            if (+x[2] >= 0 && +x[2] <= 21) {
                if (+x[3] >= 0 && +x[3] <= 255) {
                    alert("Within range");
                }
            }
        }
    } else {
        alert("Is not within range");
    }
});

JSFiddle

Upvotes: 3

Related Questions