1*91da8d44SWillForan<?php 2*91da8d44SWillForan 3*91da8d44SWillForan/** 4*91da8d44SWillForan * DokuWiki 32bit shims for IP address functions. 5*91da8d44SWillForan * 6*91da8d44SWillForan * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7*91da8d44SWillForan */ 8*91da8d44SWillForan 9*91da8d44SWillForannamespace dokuwiki; 10*91da8d44SWillForan 11*91da8d44SWillForanclass Ip32 12*91da8d44SWillForan{ 13*91da8d44SWillForan /** 14*91da8d44SWillForan * slow and ugly bitwise_and for 32bit arch 15*91da8d44SWillForan * @param $u64 unsigned 64bit integer as string 16*91da8d44SWillForan * likely from ipv6_upper_lower_32 17*91da8d44SWillForan * @param $pow 0-64 power of 2 for bitmask 18*91da8d44SWillForan */ 19*91da8d44SWillForan public static function bitmask64_32(string $u64, int $pow) : string { 20*91da8d44SWillForan //$u64 = sprintf("%.0f", $u65); 21*91da8d44SWillForan $b32 = '4294967296'; 22*91da8d44SWillForan $bin = sprintf("%032b%032b", 23*91da8d44SWillForan bcdiv($u64, $b32, 0), 24*91da8d44SWillForan bcmod($u64, $b32)); 25*91da8d44SWillForan 26*91da8d44SWillForan $mask = Ip32::make_bitmask_32(64-$pow); 27*91da8d44SWillForan 28*91da8d44SWillForan // most right is lowest bit 29*91da8d44SWillForan $res='0'; 30*91da8d44SWillForan for ($i=0; $i<64; $i++){ 31*91da8d44SWillForan if (bcmul($bin[$i], $mask[$i]) == 1) { 32*91da8d44SWillForan $res = bcadd($res, bcpow(2, 63-$i)); 33*91da8d44SWillForan } 34*91da8d44SWillForan } 35*91da8d44SWillForan return $res; 36*91da8d44SWillForan } 37*91da8d44SWillForan 38*91da8d44SWillForan 39*91da8d44SWillForan /** 40*91da8d44SWillForan * modeling bitshift like ~0 << $pow for 32-bit arch 41*91da8d44SWillForan * @param pow power of 2 for mask 42*91da8d44SWillForan * @return 64-char string of 1 and 0s 43*91da8d44SWillForan * pow=1 44*91da8d44SWillForan * 1111111111111111111111111111111111111111111111111111111111111110 45*91da8d44SWillForan * pow=63 46*91da8d44SWillForan * 1000000000000000000000000000000000000000000000000000000000000000 47*91da8d44SWillForan * pow=64 48*91da8d44SWillForan * 0000000000000000000000000000000000000000000000000000000000000000 49*91da8d44SWillForan */ 50*91da8d44SWillForan private static function make_bitmask_32(int $pow) : string { 51*91da8d44SWillForan $pow = $pow < 0 ? 64 - $pow : $pow; 52*91da8d44SWillForan $mask = sprintf("%064d",0); 53*91da8d44SWillForan for ($i=0; $i<64; $i++) { 54*91da8d44SWillForan if ($i >= $pow) { 55*91da8d44SWillForan $mask[63 - $i] = '1'; 56*91da8d44SWillForan } 57*91da8d44SWillForan } 58*91da8d44SWillForan return $mask; 59*91da8d44SWillForan } 60*91da8d44SWillForan 61*91da8d44SWillForan /** 62*91da8d44SWillForan * conversion of inet_pton ipv6 into 64-bit upper and lower 63*91da8d44SWillForan * bcmath version for 32-bit architecture 64*91da8d44SWillForan * w/o no unpack('J') - unsigned long long (always 64 bit, big endian byte order) 65*91da8d44SWillForan * 66*91da8d44SWillForan * results match unpack('Jupper/Jlower', $binary) 67*91da8d44SWillForan * 68*91da8d44SWillForan * @param string $binary inet_pton's ipv6 16 element binary 69*91da8d44SWillForan * 70*91da8d44SWillForan * @return int[] upper 64 and lower 64 for ipToNumber 71*91da8d44SWillForan */ 72*91da8d44SWillForan public static function ipv6_upper_lower_32(string $binary) { 73*91da8d44SWillForan // unpack into four 32-bit unsigned ints to recombine as 2 64-bit 74*91da8d44SWillForan $b32 = 4294967296; // bcpow(2, 32) 75*91da8d44SWillForan $parts = unpack('N4', $binary); 76*91da8d44SWillForan $upper = bcadd(bcmul($parts[1], $b32), 77*91da8d44SWillForan $parts[2]); 78*91da8d44SWillForan $lower = bcadd(bcmul($parts[3], $b32), 79*91da8d44SWillForan $parts[4]); 80*91da8d44SWillForan return ['upper' => $upper, 'lower' => $lower]; 81*91da8d44SWillForan } 82*91da8d44SWillForan } 83