xref: /dokuwiki/inc/Ip32.php (revision a060f5a0bcf2bd42191c466160b31778110b4a6f)
191da8d44SWillForan<?php
291da8d44SWillForan
391da8d44SWillForan/**
491da8d44SWillForan * DokuWiki 32bit shims for IP address functions.
591da8d44SWillForan *
691da8d44SWillForan * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
791da8d44SWillForan */
891da8d44SWillForan
991da8d44SWillForannamespace dokuwiki;
1091da8d44SWillForan
1191da8d44SWillForanclass Ip32
1291da8d44SWillForan{
1391da8d44SWillForan    /**
1491da8d44SWillForan     * slow and ugly bitwise_and for 32bit arch
1591da8d44SWillForan     * @param $u64 unsigned 64bit integer as string
16*a060f5a0SWillForan     *            likely from ipv6UpperLowerOn32
1791da8d44SWillForan     * @param $pow 0-64 power of 2 for bitmask
1891da8d44SWillForan     */
19*a060f5a0SWillForan    public static function bitmask64On32(string $u64, int $pow) : string {
2091da8d44SWillForan        //$u64 = sprintf("%.0f", $u65);
2191da8d44SWillForan        $b32 = '4294967296';
2291da8d44SWillForan        $bin = sprintf("%032b%032b",
2391da8d44SWillForan                bcdiv($u64, $b32, 0),
2491da8d44SWillForan                bcmod($u64, $b32));
2591da8d44SWillForan
26*a060f5a0SWillForan        $mask = Ip32::makeBitmaskOn32(64-$pow);
2791da8d44SWillForan
2891da8d44SWillForan        // most right is lowest bit
2991da8d44SWillForan        $res='0';
3091da8d44SWillForan        for ($i=0; $i<64; $i++){
3191da8d44SWillForan            if (bcmul($bin[$i], $mask[$i]) == 1) {
3291da8d44SWillForan                $res = bcadd($res, bcpow(2, 63-$i));
3391da8d44SWillForan            }
3491da8d44SWillForan        }
3591da8d44SWillForan        return $res;
3691da8d44SWillForan    }
3791da8d44SWillForan
3891da8d44SWillForan
3991da8d44SWillForan    /**
4091da8d44SWillForan     * modeling bitshift like  ~0 << $pow for 32-bit arch
4191da8d44SWillForan     * @param pow power of 2 for mask
4291da8d44SWillForan     * @return 64-char string of 1 and 0s
4391da8d44SWillForan     * pow=1
4491da8d44SWillForan     * 1111111111111111111111111111111111111111111111111111111111111110
4591da8d44SWillForan     * pow=63
4691da8d44SWillForan     * 1000000000000000000000000000000000000000000000000000000000000000
4791da8d44SWillForan     * pow=64
4891da8d44SWillForan     * 0000000000000000000000000000000000000000000000000000000000000000
4991da8d44SWillForan     */
50*a060f5a0SWillForan    private static function makeBitmaskOn32(int $pow) : string {
5191da8d44SWillForan        $pow = $pow < 0 ? 64 - $pow : $pow;
5291da8d44SWillForan        $mask = sprintf("%064d",0);
5391da8d44SWillForan        for ($i=0; $i<64; $i++) {
5491da8d44SWillForan            if ($i >= $pow) {
5591da8d44SWillForan                $mask[63 - $i] = '1';
5691da8d44SWillForan            }
5791da8d44SWillForan        }
5891da8d44SWillForan        return $mask;
5991da8d44SWillForan    }
6091da8d44SWillForan
6191da8d44SWillForan    /**
6291da8d44SWillForan     * conversion of inet_pton ipv6 into 64-bit upper and lower
6391da8d44SWillForan     * bcmath version for 32-bit architecture
6491da8d44SWillForan     * w/o no unpack('J') - unsigned long long (always 64 bit, big endian byte order)
6591da8d44SWillForan     *
6691da8d44SWillForan     * results match unpack('Jupper/Jlower', $binary)
6791da8d44SWillForan     *
6891da8d44SWillForan     * @param string $binary inet_pton's ipv6 16 element binary
6991da8d44SWillForan     *
7091da8d44SWillForan     * @return int[] upper 64 and lower 64 for ipToNumber
7191da8d44SWillForan     */
72*a060f5a0SWillForan    public static function ipv6UpperLowerOn32(string $binary) {
7391da8d44SWillForan       // unpack into four 32-bit unsigned ints to recombine as 2 64-bit
7491da8d44SWillForan       $b32 = 4294967296; // bcpow(2, 32)
7591da8d44SWillForan       $parts = unpack('N4', $binary);
7691da8d44SWillForan       $upper = bcadd(bcmul($parts[1], $b32),
7791da8d44SWillForan                      $parts[2]);
7891da8d44SWillForan       $lower = bcadd(bcmul($parts[3], $b32),
7991da8d44SWillForan                      $parts[4]);
8091da8d44SWillForan       return ['upper' => $upper, 'lower' => $lower];
8191da8d44SWillForan    }
8291da8d44SWillForan }
83