* 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}";
}
}
?>