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