PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/classes/Utils.class.php

https://github.com/domanicYL/PocketMine-MP
PHP | 492 lines | 411 code | 55 blank | 26 comment | 22 complexity | 93c70938ab587fa38a89a38c44e8c9b2 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /*
  3. -
  4. / \
  5. / \
  6. / PocketMine \
  7. / MP \
  8. |\ @shoghicp /|
  9. |. \ / .|
  10. | .. \ / .. |
  11. | .. | .. |
  12. | .. | .. |
  13. \ | /
  14. \ | /
  15. \ | /
  16. \ | /
  17. This program is free software: you can redistribute it and/or modify
  18. it under the terms of the GNU Lesser General Public License as published by
  19. the Free Software Foundation, either version 3 of the License, or
  20. (at your option) any later version.
  21. */
  22. if(!defined("HEX2BIN")){
  23. @define("HEX2BIN", false);
  24. }
  25. define("BIG_ENDIAN", 0x00);
  26. define("LITTLE_ENDIAN", 0x01);
  27. define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? BIG_ENDIAN:LITTLE_ENDIAN));
  28. abstract class Utils{
  29. public static function getOS(){
  30. $uname = strtoupper(php_uname("s"));
  31. if(strpos($uname, "WIN") !== false){
  32. return "win";
  33. }elseif(strpos($uname, "DARWIN") !== false){
  34. return "mac";
  35. }else{
  36. return "linux";
  37. }
  38. }
  39. public static function hexdump($bin){
  40. $output = "";
  41. $bin = str_split($bin, 16);
  42. foreach($bin as $counter => $line){
  43. $hex = chunk_split(chunk_split(str_pad(bin2hex($line), 32, " ", STR_PAD_RIGHT), 2, " "), 24, " ");
  44. $ascii = preg_replace('#([^\x20-\x7E])#', ".", $line);
  45. $output .= str_pad(dechex($counter << 4), 4, "0", STR_PAD_LEFT). " " . $hex . " " . $ascii . PHP_EOL;
  46. }
  47. return $output;
  48. }
  49. public static function printable($str){
  50. return preg_replace('#([^\x20-\x7E])#', '.', $str);
  51. }
  52. public static function readTriad($str){
  53. list(,$unpacked) = unpack("N", "\x00".$str);
  54. return (int) $unpacked;
  55. }
  56. public static function writeTriad($value){
  57. return substr(pack("N", $value), 1);
  58. }
  59. public static function writeMetadata($data){
  60. $m = "";
  61. foreach($data as $bottom => $d){
  62. $m .= chr(($d["type"] << 5) & (0xE0 | $bottom));
  63. switch($d["type"]){
  64. case 0:
  65. $m .= Utils::writeByte($data["value"]);
  66. break;
  67. case 1:
  68. $m .= Utils::writeLShort($data["value"]);
  69. break;
  70. case 2:
  71. $m .= Utils::writeLInt($data["value"]);
  72. break;
  73. case 3:
  74. $m .= Utils::writeLFloat($data["value"]);
  75. break;
  76. case 4:
  77. $m .= Utils::writeLShort(strlen($data["value"]));
  78. $m .= $data["value"];
  79. break;
  80. case 5:
  81. $m .= Utils::writeLShort($data["value"][0]);
  82. $m .= Utils::writeByte($data["value"][1]);
  83. $m .= Utils::writeLShort($data["value"][2]);
  84. break;
  85. case 6:
  86. for($i=0; $i < 3; ++$i){
  87. $m .= Utils::writeLInt($data["value"][$i]);
  88. }
  89. break;
  90. }
  91. }
  92. $m .= "\x7f";
  93. return $m;
  94. }
  95. public static function readMetadata($value, $types = false){
  96. $offset = 0;
  97. $m = array();
  98. $b = ord($value{$offset});
  99. ++$offset;
  100. while($b !== 127){
  101. $bottom = $b & 0x1F;
  102. $type = $b >> 5;
  103. switch($type){
  104. case 0:
  105. $r = Utils::readByte($value{$offset});
  106. ++$offset;
  107. break;
  108. case 1:
  109. $r = Utils::readLShort(substr($value, $offset, 2));
  110. $offset += 2;
  111. break;
  112. case 2:
  113. $r = Utils::readLInt(substr($value, $offset, 4));
  114. $offset += 4;
  115. break;
  116. case 3:
  117. $r = Utils::readLFloat(substr($value, $offset, 4));
  118. $offset += 4;
  119. break;
  120. case 4:
  121. $len = Utils::readLShort(substr($value, $offset, 2));
  122. $offset += 2;
  123. $r = substr($value, $offset, $len);
  124. $offset += $len;
  125. break;
  126. case 5:
  127. $r = array();
  128. $r[] = Utils::readLShort(substr($value, $offset, 2));
  129. $offset += 2;
  130. $r[] = Utils::readByte($value{$offset});
  131. ++$offset;
  132. $r[] = Utils::readLShort(substr($value, $offset, 2));
  133. $offset += 2;
  134. break;
  135. case 6:
  136. $r = array();
  137. for($i=0; $i < 3; ++$i){
  138. $r[] = Utils::readLInt(substr($value, $offset, 4));
  139. $offset += 4;
  140. }
  141. break;
  142. }
  143. if($types === true){
  144. $m[$bottom] = array($r, $type);
  145. }else{
  146. $m[$bottom] = $r;
  147. }
  148. $b = ord($value{$offset});
  149. ++$offset;
  150. }
  151. return $m;
  152. }
  153. public static function readDataArray($str, $len = 10, &$offset = null){
  154. $data = array();
  155. $offset = 0;
  156. for($i = 1; $i <= $len; ++$i){
  157. $l = Utils::readTriad(substr($str, $offset, 3));
  158. $offset += 3;
  159. $data[] = substr($str, $offset, $l);
  160. $offset += $l;
  161. }
  162. return $data;
  163. }
  164. public static function writeDataArray($data){
  165. $raw = "";
  166. foreach($data as $v){
  167. $raw .= Utils::writeTriad(strlen($v));
  168. $raw .= $v;
  169. }
  170. return $raw;
  171. }
  172. public static function getRandomBytes($length = 16, $secure = true, $raw = true, $startEntropy = "", &$rounds = 0, &$drop = 0){
  173. $output = b"";
  174. $length = abs((int) $length);
  175. $secureValue = "";
  176. $rounds = 0;
  177. $drop = 0;
  178. while(!isset($output{$length - 1})){
  179. //some entropy, but works ^^
  180. $weakEntropy = array(
  181. is_array($startEntropy) ? implode($startEntropy):$startEntropy,
  182. serialize(stat(__FILE__)),
  183. __DIR__,
  184. PHP_OS,
  185. microtime(),
  186. (string) lcg_value(),
  187. serialize($_SERVER),
  188. serialize(get_defined_constants()),
  189. get_current_user(),
  190. serialize(ini_get_all()),
  191. (string) memory_get_usage(),
  192. php_uname(),
  193. phpversion(),
  194. extension_loaded("gmp") ? gmp_strval(gmp_random(4)):microtime(),
  195. zend_version(),
  196. (string) getmypid(),
  197. (string) mt_rand(),
  198. (string) rand(),
  199. function_exists("zend_thread_id") ? ((string) zend_thread_id()):microtime(),
  200. var_export(@get_browser(), true),
  201. function_exists("sys_getloadavg") ? implode(";", sys_getloadavg()):microtime(),
  202. serialize(get_loaded_extensions()),
  203. sys_get_temp_dir(),
  204. (string) disk_free_space("."),
  205. (string) disk_total_space("."),
  206. uniqid(microtime(),true),
  207. );
  208. shuffle($weakEntropy);
  209. $value = hash("sha256", implode($weakEntropy), true);
  210. foreach($weakEntropy as $k => $c){ //mixing entropy values with XOR and hash randomness extractor
  211. $c = (string) $c;
  212. str_shuffle($c); //randomize characters
  213. $value ^= hash("md5", $c . microtime() . $k, true) . hash("md5", microtime() . $k . $c, true);
  214. $value ^= hash("sha256", $c . microtime() . $k, true);
  215. }
  216. unset($weakEntropy);
  217. if($secure === true){
  218. $strongEntropy = array(
  219. is_array($startEntropy) ? $startEntropy[($rounds + $drop) % count($startEntropy)]:$startEntropy, //Get a random index of the startEntropy, or just read it
  220. file_exists("/dev/urandom") ? fread(fopen("/dev/urandom", "rb"), 512):"",
  221. (function_exists("openssl_random_pseudo_bytes") and version_compare(PHP_VERSION, "5.3.4", ">=")) ? openssl_random_pseudo_bytes(512):"",
  222. function_exists("mcrypt_create_iv") ? mcrypt_create_iv(512, MCRYPT_DEV_URANDOM) : "",
  223. $value,
  224. );
  225. shuffle($strongEntropy);
  226. $strongEntropy = implode($strongEntropy);
  227. $value = "";
  228. //Von Neumann randomness extractor, increases entropy
  229. $len = strlen($strongEntropy) * 8;
  230. for($i = 0; $i < $len; $i += 2){
  231. $a = ord($strongEntropy{$i >> 3});
  232. $b = 1 << ($i % 8);
  233. $c = 1 << (($i % 8) + 1);
  234. $b = ($a & $b) === $b ? "1":"0";
  235. $c = ($a & $c) === $c ? "1":"0";
  236. if($b !== $c){
  237. $secureValue .= $b;
  238. if(isset($secureValue{7})){
  239. $value .= chr(bindec($secureValue));
  240. $secureValue = "";
  241. }
  242. ++$drop;
  243. }else{
  244. $drop += 2;
  245. }
  246. }
  247. }
  248. $output .= substr($value, 0, min($length - strlen($output), $length));
  249. unset($value);
  250. ++$rounds;
  251. }
  252. return $raw === false ? bin2hex($output):$output;
  253. }
  254. public static function round($number){
  255. return round($number, 0, PHP_ROUND_HALF_DOWN);
  256. }
  257. public static function distance($pos1, $pos2){
  258. return sqrt(pow($pos1["x"] - $pos2["x"], 2) + pow($pos1["y"] - $pos2["y"], 2) + pow($pos1["z"] - $pos2["z"], 2));
  259. }
  260. public static function angle3D($pos1, $pos2){
  261. $X = $pos1["x"] - $pos2["x"];
  262. $Z = $pos1["z"] - $pos2["z"];
  263. $dXZ = sqrt(pow($X, 2) + pow($Z, 2));
  264. $Y = $pos1["y"] - $pos2["y"];
  265. $hAngle = rad2deg(atan2($Z, $X) - M_PI_2);
  266. $vAngle = rad2deg(-atan2($Y, $dXZ));
  267. return array("yaw" => $hAngle, "pitch" => $vAngle);
  268. }
  269. public static function sha1($input){
  270. $number = new Math_BigInteger(sha1($input, true), -256);
  271. $zero = new Math_BigInteger(0);
  272. return ($zero->compare($number) <= 0 ? "":"-") . ltrim($number->toHex(), "0");
  273. }
  274. public static function microtime(){
  275. return microtime(true);
  276. }
  277. public static function curl_get($page){
  278. $ch = curl_init($page);
  279. curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Minecraft PHP Client 2"));
  280. curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  281. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  282. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  283. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  284. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  285. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  286. $ret = curl_exec($ch);
  287. curl_close($ch);
  288. return $ret;
  289. }
  290. public static function curl_post($page, $args, $timeout = 10){
  291. $ch = curl_init($page);
  292. curl_setopt($ch, CURLOPT_POST, 1);
  293. curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
  294. curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  295. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  296. curl_setopt($ch, CURLOPT_HTTPHEADER, array("User-Agent: Minecraft PHP Client 2"));
  297. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  298. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
  299. $ret = curl_exec($ch);
  300. curl_close($ch);
  301. return $ret;
  302. }
  303. public static function strToHex($str){
  304. return bin2hex($str);
  305. }
  306. public static function hexToStr($hex){
  307. if(HEX2BIN === true){
  308. return hex2bin($hex);
  309. }
  310. return pack("H*" , $hex);
  311. }
  312. public static function readBool($b){
  313. return Utils::readByte($b, false) === 0 ? false:true;
  314. }
  315. public static function writeBool($b){
  316. return Utils::writeByte($b === true ? 1:0);
  317. }
  318. public static function readByte($c, $signed = true){
  319. $b = ord($c{0});
  320. if($signed === true and ($b & 0x80) === 0x80){ //calculate Two's complement
  321. $b = -0x80 + ($b & 0x7f);
  322. }
  323. return $b;
  324. }
  325. public static function writeByte($c){
  326. if($c > 0xff){
  327. return false;
  328. }
  329. if($c < 0 and $c >= -0x80){
  330. $c = 0xff + $c + 1;
  331. }
  332. return chr($c);
  333. }
  334. public static function readShort($str, $signed = true){
  335. list(,$unpacked) = unpack("n", $str);
  336. if($unpacked > 0x7fff and $signed === true){
  337. $unpacked -= 0x10000; // Convert unsigned short to signed short
  338. }
  339. return $unpacked;
  340. }
  341. public static function writeShort($value){
  342. if($value < 0){
  343. $value += 0x10000;
  344. }
  345. return pack("n", $value);
  346. }
  347. public static function readLShort($str, $signed = true){
  348. list(,$unpacked) = unpack("v", $str);
  349. if($unpacked > 0x7fff and $signed === true){
  350. $unpacked -= 0x10000; // Convert unsigned short to signed short
  351. }
  352. return $unpacked;
  353. }
  354. public static function writeLShort($value){
  355. if($value < 0){
  356. $value += 0x10000;
  357. }
  358. return pack("v", $value);
  359. }
  360. public static function readInt($str){
  361. list(,$unpacked) = unpack("N", $str);
  362. if($unpacked >= 2147483648){
  363. $unpacked -= 4294967296;
  364. }
  365. return (int) $unpacked;
  366. }
  367. public static function writeInt($value){
  368. if($value < 0){
  369. $value += 0x100000000;
  370. }
  371. return pack("N", $value);
  372. }
  373. public static function readLInt($str){
  374. list(,$unpacked) = unpack("V", $str);
  375. if($unpacked >= 2147483648){
  376. $unpacked -= 4294967296;
  377. }
  378. return (int) $unpacked;
  379. }
  380. public static function writeLInt($value){
  381. if($value < 0){
  382. $value += 0x100000000;
  383. }
  384. return pack("V", $value);
  385. }
  386. public static function readFloat($str){
  387. list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("f", $str):unpack("f", strrev($str));
  388. return $value;
  389. }
  390. public static function writeFloat($value){
  391. return ENDIANNESS === BIG_ENDIAN ? pack("f", $value):strrev(pack("f", $value));
  392. }
  393. public static function readLFloat($str){
  394. list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("f", strrev($str)):unpack("f", $str);
  395. return $value;
  396. }
  397. public static function writeLFloat($value){
  398. return ENDIANNESS === BIG_ENDIAN ? strrev(pack("f", $value)):pack("f", $value);
  399. }
  400. public static function printFloat($value){
  401. return preg_replace("/(\.\d+?)0+$/", "$1", sprintf("%F", $value));
  402. }
  403. public static function readDouble($str){
  404. list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("d", $str):unpack("d", strrev($str));
  405. return $value;
  406. }
  407. public static function writeDouble($value){
  408. return ENDIANNESS === BIG_ENDIAN ? pack("d", $value):strrev(pack("d", $value));
  409. }
  410. public static function readLDouble($str){
  411. list(,$value) = ENDIANNESS === BIG_ENDIAN ? unpack("d", strrev($str)):unpack("d", $str);
  412. return $value;
  413. }
  414. public static function writeLDouble($value){
  415. return ENDIANNESS === BIG_ENDIAN ? strrev(pack("d", $value)):pack("d", $value);
  416. }
  417. public static function readLong($str){
  418. $long = new Math_BigInteger($str, -256);
  419. return $long->toString();
  420. }
  421. public static function writeLong($value){
  422. $long = new Math_BigInteger($value, -10);
  423. return str_pad($long->toBytes(true), 8, "\x00", STR_PAD_LEFT);
  424. }
  425. public static function readLLong($str){
  426. $long = new Math_BigInteger(strrev($str), -256);
  427. return $long->toString();
  428. }
  429. public static function writeLLong($value){
  430. $long = new Math_BigInteger($value, -10);
  431. return strrev(str_pad($long->toBytes(true), 8, "\x00", STR_PAD_LEFT));
  432. }
  433. }