* echo GTUtil::gcd(4, 8); * * // output: * // 4 * * * @static * @param int $a the first integer * @param int $b the second integer * @return int the greatest common divisor of a and b or 0 if both are 0 */ public static function gcd($a, $b) { $a = abs((int) $a); $b = abs((int) $b); while ($a > 0) { $c = $b % $a; $b = $a; $a = $c; } return $b; } /** * Computes the least common multiple (LCM) of two integers. * * Least common multiple is the smallest positive integer that can be divided * by both numbers without a remainder. * * * echo GTUtil::lcm(4, 6); * * // output: * // 12 * * * @static * @throws GTException when the result is too big to fit into {@code int} * @param int $a the first integer * @param int $b the second integer * @return int the least common multiple of a and b, or 0 if either a or b is 0 */ public static function lcm($a, $b) { $a = (int) $a; $b = (int) $b; if ($a == 0 || $b == 0) { return 0; } $a = abs($a) / GTUtil::gcd($a, $b); $b = abs($b); if ($a > PHP_INT_MAX / $b) { throw new GTException("Integer overflow"); } return $a * $b; } /** * Writes data to file. * * Example: * * * GTUtil::write('file.txt', array(1, 2, 3)); * * * @static * @throws GTException * @param string $file file name to write to * @param array $bytes byte array that contains the bytes to write * @return void * * @see read */ public static function write($file, array $bytes) { if (empty($file)) { throw new GTException("parameter file is required"); } if ($bytes == null) { throw new GTException("parameter bytes is required"); } if (!is_array($bytes)) { throw new GTException("parameter bytes must be an array"); } $fp = fopen($file, 'wb+'); if (!$fp) { throw new GTException("Unable to open file {$file} for writing"); } if (!fwrite($fp, GTUtil::fromByteArray($bytes))) { throw new GTException("Unable to write to bytes to file {$file}"); } if (!fclose($fp)) { throw new GTException("Unable to close file after writing {$file}"); } } /** * Touches specified file. * * @static * @throws GTException * @param $file the file to touch * @return void */ public static function touch($file) { if (empty($file)) { throw new GTException("parameter file is required"); } touch($file); } /** * Reads data from file. * * @static * @throws GTException * @param string $file file name to read from * @return array byte array read from $file * * @see write */ public static function read($file) { if (empty($file)) { throw new GTException("parameter file is required"); } if (!is_file($file)) { throw new GTException("file {$file} does not exist"); } if (!is_readable($file)) { throw new GTException("file {$file} is not readable"); } $fp = fopen($file, 'rb'); if (!$fp) { throw new GTException("Unable to open file {$file} for reading"); } $length = filesize($file); if ($length > 0) { $data = fread($fp, $length); } else { $data = ""; } if ($data === false) { throw new GTException("Unable to read from file {$file}"); } fclose($fp); return GTUtil::toByteArray($data); } /** * Wrapper method for OpenSSL asn1parse. * * @static * @param string $file file containing a valid ASN.1 DER object * @return void */ public static function printAsn1($file) { passthru("openssl asn1parse -i -inform DER -in {$file}"); } /** * Decodes an ASN.1 formatted time to unix timestamp. * * @static * @throws GTException * @param string $time ASN.1 formatted time * @param string $timezone timezone to use * @return int php unix timestamp */ public static function decodeTime($time, $timezone = null) { if ($timezone != null) { $old_timezone = date_default_timezone_get(); $new_timezone = date_default_timezone_set($timezone); if ($new_timezone === false) { throw new GTException("Unable to set timezone to {$timezone}"); } } if ($time == null) { throw new GTException("parameter time must not be empty"); } if (strlen($time) != 15) { throw new GTException("parameter time has invalid length"); } $tokens = array( 'year' => substr($time, 0, 4), 'month' => substr($time, 4, 2), 'day' => substr($time, 6, 2), 'hour' => substr($time, 8, 2), 'minute' => substr($time, 10, 2), 'second' => substr($time, 12, 2) ); foreach ($tokens as $name => $value) { if (!ctype_digit($value)) { throw new GTException("Invalid time encoding, {$name} = {$value}"); } } $time = mktime( (int) $tokens['hour'], (int) $tokens['minute'], (int) $tokens['second'], (int) $tokens['month'], (int) $tokens['day'], (int) $tokens['year'] ); if ($timezone != null) { date_default_timezone_set($old_timezone); } return $time; } /** * Formats a PHP unix timestamp in a more human readable format (%Y-%m-%d %H:%M:%S UTC) * * @static * @throws GTException * @param $time php unix timestamp * @param $timezone the timezone to use * @return string formatted datetime */ public static function formatTime($time, $timezone = null) { if ($timezone != null) { $old_timezone = date_default_timezone_get(); $new_timezone = date_default_timezone_set($timezone); if ($new_timezone === false) { throw new GTException("Unable to set timezone to {$timezone}"); } } $formatted = strftime('%Y-%m-%d %H:%M:%S UTC', $time); if ($timezone != null) { date_default_timezone_set($old_timezone); } return $formatted; } /** * Pads $array by prepending $value until the size of $array equals $length. * * @static * @param $array the array to pad * @param $length the length to pad to * @param $value padding value * @return void */ public static function lpad(array &$array, $length, $value) { while (count($array) < $length) { array_unshift($array, $value); } } /** * Pads $array by appending $value until the size of $array equals $length. * * @static * @param $array the array to pad * @param $length the length to pad to * @param $value padding value * @return void */ public static function rpad(array &$array, $length, $value) { while (count($array) < $length) { array_push($array, $value); } } /** * Converts a string into an array of characters. * * * $result = GTUtil::toArray('foo'); * * print_r($result); * * // output: * // Array * // ( * // [0] => f * // [1] => o * // [2] => o * // ) * * * @static * @param string $string the input string * @return array an array built from characters in string */ public static function toArray($string) { $result = array(); if (empty($string)) { return $result; } for ($i = 0; $i < strlen($string); $i++) { array_push($result, $string{$i}); } return $result; } /** * Converts an array of characters into a string * * * echo GTUtil::fromArray(array('f', 'o', 'o')); * * // output: * // foo * * * @static * @param $array the input array * @return string a string built from characters in array */ public static function fromArray(array $array = null) { $result = ""; if (empty($array)) { return $result; } for ($i = 0; $i < count($array); $i++) { $result .= $array[$i]; } return $result; } /** * Converts a string into an array of bytes. * * Each byte in the resulting array will represent the ASCII value of each * character in the input string * * * $result = GTUtil::toByteArray('foo'); * * print_r($result); * * // output: * // Array * // ( * // [0] => 102 * // [1] => 111 * // [2] => 111 * // ) * * * @static * @param $string the input string * @return array an array of bytes representing the characters in string */ public static function toByteArray($string) { $result = array(); if (empty($string)) { return $result; } for ($i = 0; $i < strlen($string); $i++) { array_push($result, ord($string{$i})); } return $result; } /** * Converts a byte array into a string. * * Each character in the string will represent the ASCII code of each * byte in the input array * * * $bytes = array( * ord('f'), * ord('o'), * ord('o') * ); * * echo GTUtil::fromByteArray($bytes); * * // output: * // foo * * * @static * @param $array the input array * @return string a string built from bytes in the array */ public static function fromByteArray(array $array = null) { $result = ""; if (empty($array)) { return $result; } for ($i = 0; $i < count($array); $i++) { $result .= chr($array[$i]); } return $result; } /** * Reads a short (2 bytes) integer from the given byte array. * * @static * @throws GTException * @param array $array the byte array to read from * @param int $position the position in the array to read from * @return int short integer from the given byte array */ public static function readShort(array $array, $position) { if ($position + 2 > count($array) - 1) { throw new GTException("Array index out of bounds"); } $integer = new GTBigInteger( array_slice($array, $position, 2) ); return (int) $integer->getValue(); } /** * Reads an integer (4 bytes) from the given byte array. * * @static * @throws GTException * @param array $array the byte array to read from * @param int $position the position in the array to read from * @return int 4 byte integer from the given byte array */ public static function readInt(array $array, $position) { if ($position + 4 > count($array) - 1) { throw new GTException("Array index out of bounds"); } $integer = new GTBigInteger( array_slice($array, $position, 4) ); return (int) $integer->getValue(); } /** * Reads a GTBigInteger (8 bytes) from the given byte array. * * @static * @throws GTException * @param array $array the byte array to read from * @param int $position the position in the array to read from * @return GTBigInteger 8 byte GTBigInteger from the given byte array */ public static function readLong(array $array, $position) { if ($position + 8 > count($array) - 1) { throw new GTException("Array index out of bounds"); } return new GTBigInteger( array_slice($array, $position, 8) ); } /** * Computes and adds CRC32 to the given byte array. * * @static * @param $bytes input byte array * @return array bytes with added CRC32 checksum */ public static function addCrc32(array $bytes) { $checksum = crc32(GTUtil::fromByteArray($bytes)); $checksum = sprintf("%u", $checksum); // make unsigned, needed for 32 bit PHP $checksum = new GTBigInteger($checksum); $checksum = $checksum->toBytes(); // remove leading 0x0-s while (count($checksum) > 4) { array_shift($checksum); } foreach ($checksum as $byte) { array_push($bytes, $byte); } return $bytes; } /** * Gets OpenSSL version as string. * * @static * @return string OpenSSL version as string, example: 0.9.8 */ public static function getOpensslVersion() { $version = new GTBigInteger(OPENSSL_VERSION_NUMBER); $mask = new GTBigInteger(0xF); $major = $version->shiftRight(28)->bitAnd($mask)->getValue(); $minor = $version->shiftRight(20)->bitAnd($mask)->getValue(); $fix = $version->shiftRight(12)->bitAnd($mask)->getValue(); return "{$major}.{$minor}.{$fix}"; } } ?>