tags:

views:

38

answers:

3

hi,

function ip_address_to_number($IPaddress) { 
 if(!$IPaddress) {
  return false;
 } else {
  $ips = split('\.',$IPaddress);
  return($ips[3] + $ips[2]*256 + $ips[1]*65536 + $ips[0]*16777216);
 }
}

that function executes the same code as the php bundled function ip2long. however, when i print these 2 values, i get 2 different returns. why? (im using php 5.2.10 on a wamp environment).

ip2long('200.117.248.17'); //returns -931792879

ip_address_to_number('200.117.248.17'); // returns 3363174417

Applied and continued here: http://stackoverflow.com/questions/3063192/php-showing-my-country-based-on-my-ip-mysql-optimized

+2  A: 

Try this instead:

$ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR']));

sprintf will then write it as an unsigned integer.

webbiedave
+3  A: 
glopes@nebm:~$ php -r "printf('%u', -931792879);"
3363174417

There you go. My guess is that you are on a system with 32-bit ints and your ip_address_to_number is actually returning a float.

You see, with 32-bit ints, your maximum positive integer is (2^31) - 1 = 2 147 483 647, so the integer wraps around.

If you want to mimic the behaviour of the PHP function, do:

function ip_address_to_number($IPaddress) { 
 if(!$IPaddress) {
  return false;
 } else {
  $ips = split('\.',$IPaddress);
  return($ips[3] | $ips[2] << 8 | $ips[1] << 16 | $ips[0] << 24);
 }
}

(by the way, split has been deprecated)

Artefacto
you sir, are my (today's) personal hero. thanks!
andufo
+1  A: 
  $ips[3]                             = 17
+ $ips[2] * 256 = 248 * 256           = 63488
+ $ips[1] * 65536 = 117 * 65536       = 7667712
+ $ips[0] * 16777216 = 200 * 16777216 = 3355443200
                                      = 3363174417

PHP max integer value (32-bit) is 2147483647, which is < 3363174417

Quoting from the ip2long() PHP manual page

Note: Because PHP's integer type is signed, and many IP addresses will result in negative integers, you need to use the "%u" formatter of sprintf() or printf() to get the string representation of the unsigned IP address.

Mark Baker
You are of course correct. The question is, why would he want the unsigned string representation of the IP in base 10. As far as string representations go, '200.117.248.17' is much more readable. With the integer representation, he has a more compact representation (4 bytes) and he can do bitwise operations on the IP. The "negative value" is irrelevant for that.
Artefacto
+1: You'd be surprised how many problems are solved by reading the manual.
R. Bemrose
@Artefacto: No, the question is "Why don't the PHP developers fix this issue and not have `ip2long` return negative values?"
R. Bemrose
@R. Bemrose Because that would not make sense. The only way to do that would be to have ip2long return a float since an integer is not large enough to hold all the values, while a float has 52 bits for the fraction. That would kill all the bitwise operations on IPs, which, by the way, together with storing IPs efficiently, is the purpose of the function.
Artefacto