<?php
    
if (isset($_GET['source'])) {
        
highlight_file(__FILE__);
        exit;
    }

    
/*** Show form if required parameter is not given ***/

    
if (empty($_GET['ip'])) {
        if (
substr_count($_SERVER['REMOTE_ADDR'], ':') == 0) {
            
$ip $_SERVER['REMOTE_ADDR'];
        }
        else {
            echo 
"(Hello there, I see you are using IPv6. Awesome!)<br>\n"// Not actually possible on server02 but whatever, this code will soon move, hopefluly...
            
$ip '';
        }
        
?>
            IPv4 address:<form><input name=ip value="<?php echo $ip;?>"><input type=submit></form>
            Or try <a href="?link&amp;ip=<?php echo file_get_contents('../../extip.txt'); ?>">this website's IP address</a>.
        <?php
        
exit;
    }

    
/*** Input checking ***/

    
$ip $_GET['ip'];
    if (
preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/'$ip) !== 1) {
        die(
'I need a regularly formatted IP address, please.');
    }

    
$parts explode('.'$ip);
    foreach (
$parts as $part) {
        if (
$part 255) {
            die(
'You know the rules, and so do I.');
        }
    }

    
$ilz = isset($_GET['leadingzeroes']);
    
$leftout = [];

    
/*** Formatters ***/

    
function formathex($n$addzero=false) {
        if (
$addzero) {
            return 
'0x0' dechex($n);
        }
        return 
'0x' dechex($n);
    }
    function 
formatoct($n$addzero=false) {
        if (
$addzero) {
            return 
'00' decoct($n);
        }
        return 
'0' decoct($n);
    }
    function 
formatdec($n$addzero=false) {
        return 
"$n";
    }
    
$formats = ['formatdec''formathex''formatoct'];

    
/*** Our workhorse in all this ***/

    
function recurse($pos=0$f=null$sofar=''$addanotherzero=false) {
        global 
$parts$formats$results$ilz$leftout;

        if (
$f != null) {
            
// If Y==0 in x.x.Y.x, or if Y==0 in x.Y.Y.x, we can leave out the zero
            // Also if Y==0 in Y.Y.Y.x, but that's basically ip2long() which we did above already
            
if ($parts[2] == && ($pos == || ($pos == && $parts[1] == 0)) && !isset($leftout[$pos])) {
                
$leftout[$pos] = true;
                
recurse(3null$sofar);
            }

            if (
$f == 'formatoct' && ! $ilz && $parts[$pos] < 8) {
                
// E.g. 1.9.0.4 would be 01.011.00.04 in octal dotted notation, of which only the 011 is interesting because the rest works in decimal as well, so skip any low numbers
                // Note that we don't do this for hex because 0x1 has an x in it, clearly different from the regular decimal with leading zeroes.
                
return;
            }

            if (
$ilz && $f != 'formatdec') {
                
// You want leading zeroes? You'll get leading zeroes! (Within reason, though, still, unfortunately.)
                
if ( ! $addanotherzero) { // (prevent infinite recursion...)
                    
recurse($pos$f$sofartrue);
                }
            }

            
$sofar .= $f($parts[$pos], $addanotherzero);
            if (
$pos 3) {
                
$sofar .= '.';
            }

            if (
$pos == && $parts[2] > 0) {
                
$last16 $parts[2] * 256 $parts[3];
                foreach (
$formats as $f) {
                    
$results[] = $sofar $f($last16);
                    if (
$addanotherzero) {
                        
$results[] = $sofar $f($last16true);
                    }
                }
            }

            if (
$pos == && ($parts[2] > || $parts[1] > 0)) {
                
$last24 $parts[1] * 65536 $parts[2] * 256 $parts[3];
                foreach (
$formats as $f) {
                    
$results[] = $sofar $f($last24);
                    if (
$addanotherzero) {
                        
$results[] = $sofar $f($last24true);
                    }
                }
            }

            if (
$pos == 3) {
                
$results[] = $sofar;
                return;
            }
        }
        else {
            
$pos--;
        }

        foreach (
$formats as $nextf) {
            
recurse($pos 1$nextf$sofar);
        }
    }

    
/*** And finally, main() ***/

    
$l = (isset($_GET['link']) ? '?link&amp;' '?') . "ip=$ip";
    if ( ! 
$ilz) {
        
$l .= '&amp;leadingzeroes';
        
$inex 'include some';
        
$out 'out';
    }
    else {
        
$inex 'exclude unnecessary';
        
$out ' some';
    }
    echo 
"All possible notations of this IPv4 address (with$out leading zeroes (<a href='$l'>${inex} leading zeroes</a>)):<br>\n<pre>\n";

    
$results = [];

    
// Dotted decimal
    
$results[] = $ip;

    
// Decimal, hex, and octal
    
foreach ($formats as $f) {
        
$long $f(ip2long($ip));
        if (
$long 0) { // 32-bit system...
            
$long += 0x100000000;
        }
        if (
$long == && $f == 'formatoct' && !$ilz) {
            continue;
        }
        
$results[] = $long;
    }

    
// Dotted hex/decimal/octal
    
recurse();

    
/*if ($parts[2] == 0) {
        foreach ($formats as $f) {
            recurse(3, null, $f($parts[0]) . '.' . $f($parts[1]));
        }
        if ($parts[1] == 0) {
            recurse(3, null, $f($parts[0]) . '.');
        }
    }*/

    
if (isset($_GET['link'])) {
        
$maxlen 0;
        foreach (
$results as $result) {
            
$maxlen max($maxlenstrlen($result));
        }
    }

    if (isset(
$_GET['link'])) {
        echo 
'IP' str_repeat(' '$maxlen) . "Clickable link (note that not all browsers are tested; if this bugs, try Firefox)\n";
    }

    foreach (
$results as $n=>$result) {
        if (
$ip == $result && $n 0) {
            continue; 
// We put the regular formatting on top, so skip this one
        
}

        if (isset(
$_GET['link'])) {
            
$link str_repeat(' '$maxlen strlen($result)) . "<a href='http://$result'>http://$result</a>";
        }
        echo 
"$result$link\n";
    }

    echo 
"</pre>\n";
    echo 
count($results) . " versions shown.<br><br>\n\n";
    if (
$ilz) {
        echo 
"Of course, with leading zeroes, one can add an infinite number of zeroes in front of any octal and hexadecimal number. I only added one zero in front of each for demonstration purposes.<br><br>\n";
    }
    
$lz $ilz '&amp;leadingzeroes' '';
    if ( ! isset(
$_GET['link'])) {
        echo 
"Would you like to <a href='?ip=$ip$lz&amp;link'>show hyperlinks for each variant</a>? This is useful if a web server is running on that IP address.<br><br>\n";
    }
    else {
        echo 
"Fun fact: in older versions of Firefox, it would not translate the address, so in your address bar you would see the notation you typed. The web server would also see this in the HTTP Host header, and my server used to have an easter egg for its decimal IP that nobody ever triggered. Alas...<br><br>\n";
        echo 
"Would you prefer to <a href='?ip=$ip$lz'>hide hyperlinks</a>?<br><br>\n";
    }
    echo 
"Do you want to <a href='?ip='>try another IPv4 address</a>, or would you like to view the <a href='?source'>source code</a>?\n";
    echo 
'<br><br><br>';