1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Decoding IPs stored as hex in database

Discussion in 'XenForo Development Discussions' started by vord, Nov 8, 2014.

  1. vord

    vord Member

    Does anyone know how to decode IP addresses stored in the database, specifically IP in the xf_ip table? The format looks like it was changed in 1.3 or 1.4 to 8 digit hex, presumably to cope with IPv6.

    I'm trying to convert the hex into a long IP to use in a country lookup table as part of a custom spam tool which runs externally to xenforo and compares actual country with the country entered as a required field during registration.
     
  2. Mike

    Mike XenForo Developer Staff Member

    They're not actually in hex; they're binary representations of the 4 or 16 byte address. You can use one of the helper functions in XenForo_Helper_Ip to decode it to a human readable version.
     
  3. vord

    vord Member

    Thanks, that's fixed it. The IPs come out of the database in binary. The file \library\XenForo\Helper\Ip.php has a function convertIpBinaryToString() which converts the binary into IP format.
     
  4. AndyB

    AndyB Well-Known Member

    The xf_ip table ip field has data like this "1804603c". What do we need to do with this data before using the convertIpBinaryToString() code?
     
  5. vord

    vord Member

    The database has a DEHEX function so the data comes out in binary format using an ordinary select statement.
     
  6. AndyB

    AndyB Well-Known Member

    Thank you, I got that to work.

    Out of curiosity is there a way to do this in PHP, that is "data comes out in binary format". So for example I input to my script "1804603c" and it's put into the same format as I get when I do a select query with MySQL.
     
  7. vord

    vord Member

    There's another function on the same page as convertIpBinaryToString() it's hex2bin() from memory. That'll convert hex to binary. The function has other stuff inside which I removed for my own use before I realised I didn't need it.
     
  8. AndyB

    AndyB Well-Known Member

    Got it.

    PHP:
    <?php

    $ip 
    '1804603c';

    $ip pack('H*'$ip);

    if (
    strlen($ip) == 4)
    {
        
    // IPv4
        
    $parts = array();
        foreach (
    str_split($ip) AS $char)
        {
            
    $parts[] = ord($char);
        }

        echo 
    implode('.'$parts);
    }
    else if (
    strlen($ip) == 16)
    {
        
    // IPv6
        
    $parts = array();
        
    $chunks str_split($ip);
        for (
    $i 0$i 16$i += 2)
        {
            
    $char1 $chunks[$i];
            
    $char2 $chunks[$i 1];

            
    $part sprintf('%02x%02x'ord($char1), ord($char2));
            if (
    $shorten)
            {
                
    // reduce this to the shortest length possible, but keep 1 zero if needed
                
    $part ltrim($part'0');
                if (!
    strlen($part))
                {
                    
    $part '0';
                }
            }
            
    $parts[] = $part;
        }

        
    $output implode(':'$parts);
        if (
    $shorten)
        {
            
    $output preg_replace('/((^0|:0){2,})(.*)$/'':$3'$output);
            if (
    substr($output, -1) === ':' && (strlen($output) == || substr($output, -21) !== ':'))
            {
                
    $output .= ':';
            }
        }

        echo 
    strtolower($output);
    }
    else if (
    preg_match('/^[0-9]+$/'$ip))
    {
        echo 
    long2ip($ip 0);
    }
    else
    {
        echo 
    'return false';
    }

    ?>
     

Share This Page