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