diff options
Diffstat (limited to 'system/core/compat')
-rw-r--r-- | system/core/compat/hash.php | 254 | ||||
-rw-r--r-- | system/core/compat/index.html | 11 | ||||
-rw-r--r-- | system/core/compat/mbstring.php | 149 | ||||
-rw-r--r-- | system/core/compat/password.php | 251 | ||||
-rw-r--r-- | system/core/compat/standard.php | 182 |
5 files changed, 847 insertions, 0 deletions
diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php new file mode 100644 index 000000000..c65203aaf --- /dev/null +++ b/system/core/compat/hash.php @@ -0,0 +1,254 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014 - 2017, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) + * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link https://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * PHP ext/hash compatibility package + * + * @package CodeIgniter + * @subpackage CodeIgniter + * @category Compatibility + * @author Andrey Andreev + * @link https://codeigniter.com/user_guide/ + * @link http://php.net/hash + */ + +// ------------------------------------------------------------------------ + +if (is_php('5.6')) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('hash_equals')) +{ + /** + * hash_equals() + * + * @link http://php.net/hash_equals + * @param string $known_string + * @param string $user_string + * @return bool + */ + function hash_equals($known_string, $user_string) + { + if ( ! is_string($known_string)) + { + trigger_error('hash_equals(): Expected known_string to be a string, '.strtolower(gettype($known_string)).' given', E_USER_WARNING); + return FALSE; + } + elseif ( ! is_string($user_string)) + { + trigger_error('hash_equals(): Expected user_string to be a string, '.strtolower(gettype($user_string)).' given', E_USER_WARNING); + return FALSE; + } + elseif (($length = strlen($known_string)) !== strlen($user_string)) + { + return FALSE; + } + + $diff = 0; + for ($i = 0; $i < $length; $i++) + { + $diff |= ord($known_string[$i]) ^ ord($user_string[$i]); + } + + return ($diff === 0); + } +} + +// ------------------------------------------------------------------------ + +if (is_php('5.5')) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('hash_pbkdf2')) +{ + /** + * hash_pbkdf2() + * + * @link http://php.net/hash_pbkdf2 + * @param string $algo + * @param string $password + * @param string $salt + * @param int $iterations + * @param int $length + * @param bool $raw_output + * @return string + */ + function hash_pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_output = FALSE) + { + if ( ! in_array(strtolower($algo), hash_algos(), TRUE)) + { + trigger_error('hash_pbkdf2(): Unknown hashing algorithm: '.$algo, E_USER_WARNING); + return FALSE; + } + + if (($type = gettype($iterations)) !== 'integer') + { + if ($type === 'object' && method_exists($iterations, '__toString')) + { + $iterations = (string) $iterations; + } + + if (is_string($iterations) && is_numeric($iterations)) + { + $iterations = (int) $iterations; + } + else + { + trigger_error('hash_pbkdf2() expects parameter 4 to be long, '.$type.' given', E_USER_WARNING); + return NULL; + } + } + + if ($iterations < 1) + { + trigger_error('hash_pbkdf2(): Iterations must be a positive integer: '.$iterations, E_USER_WARNING); + return FALSE; + } + + if (($type = gettype($length)) !== 'integer') + { + if ($type === 'object' && method_exists($length, '__toString')) + { + $length = (string) $length; + } + + if (is_string($length) && is_numeric($length)) + { + $length = (int) $length; + } + else + { + trigger_error('hash_pbkdf2() expects parameter 5 to be long, '.$type.' given', E_USER_WARNING); + return NULL; + } + } + + if ($length < 0) + { + trigger_error('hash_pbkdf2(): Length must be greater than or equal to 0: '.$length, E_USER_WARNING); + return FALSE; + } + + $hash_length = defined('MB_OVERLOAD_STRING') + ? mb_strlen(hash($algo, NULL, TRUE), '8bit') + : strlen(hash($algo, NULL, TRUE)); + empty($length) && $length = $hash_length; + + // Pre-hash password inputs longer than the algorithm's block size + // (i.e. prepare HMAC key) to mitigate potential DoS attacks. + static $block_sizes; + empty($block_sizes) && $block_sizes = array( + 'gost' => 32, + 'haval128,3' => 128, + 'haval160,3' => 128, + 'haval192,3' => 128, + 'haval224,3' => 128, + 'haval256,3' => 128, + 'haval128,4' => 128, + 'haval160,4' => 128, + 'haval192,4' => 128, + 'haval224,4' => 128, + 'haval256,4' => 128, + 'haval128,5' => 128, + 'haval160,5' => 128, + 'haval192,5' => 128, + 'haval224,5' => 128, + 'haval256,5' => 128, + 'md2' => 16, + 'md4' => 64, + 'md5' => 64, + 'ripemd128' => 64, + 'ripemd160' => 64, + 'ripemd256' => 64, + 'ripemd320' => 64, + 'salsa10' => 64, + 'salsa20' => 64, + 'sha1' => 64, + 'sha224' => 64, + 'sha256' => 64, + 'sha384' => 128, + 'sha512' => 128, + 'snefru' => 32, + 'snefru256' => 32, + 'tiger128,3' => 64, + 'tiger160,3' => 64, + 'tiger192,3' => 64, + 'tiger128,4' => 64, + 'tiger160,4' => 64, + 'tiger192,4' => 64, + 'whirlpool' => 64 + ); + + if (isset($block_sizes[$algo], $password[$block_sizes[$algo]])) + { + $password = hash($algo, $password, TRUE); + } + + $hash = ''; + // Note: Blocks are NOT 0-indexed + for ($bc = (int) ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++) + { + $key = $derived_key = hash_hmac($algo, $salt.pack('N', $bi), $password, TRUE); + for ($i = 1; $i < $iterations; $i++) + { + $derived_key ^= $key = hash_hmac($algo, $key, $password, TRUE); + } + + $hash .= $derived_key; + } + + // This is not RFC-compatible, but we're aiming for natural PHP compatibility + if ( ! $raw_output) + { + $hash = bin2hex($hash); + } + + return defined('MB_OVERLOAD_STRING') + ? mb_substr($hash, 0, $length, '8bit') + : substr($hash, 0, $length); + } +} diff --git a/system/core/compat/index.html b/system/core/compat/index.html new file mode 100644 index 000000000..b702fbc39 --- /dev/null +++ b/system/core/compat/index.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</html> diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php new file mode 100644 index 000000000..1b2f2c63b --- /dev/null +++ b/system/core/compat/mbstring.php @@ -0,0 +1,149 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014 - 2017, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) + * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link https://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * PHP ext/mbstring compatibility package + * + * @package CodeIgniter + * @subpackage CodeIgniter + * @category Compatibility + * @author Andrey Andreev + * @link https://codeigniter.com/user_guide/ + * @link http://php.net/mbstring + */ + +// ------------------------------------------------------------------------ + +if (MB_ENABLED === TRUE) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('mb_strlen')) +{ + /** + * mb_strlen() + * + * WARNING: This function WILL fall-back to strlen() + * if iconv is not available! + * + * @link http://php.net/mb_strlen + * @param string $str + * @param string $encoding + * @return int + */ + function mb_strlen($str, $encoding = NULL) + { + if (ICONV_ENABLED === TRUE) + { + return iconv_strlen($str, isset($encoding) ? $encoding : config_item('charset')); + } + + log_message('debug', 'Compatibility (mbstring): iconv_strlen() is not available, falling back to strlen().'); + return strlen($str); + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('mb_strpos')) +{ + /** + * mb_strpos() + * + * WARNING: This function WILL fall-back to strpos() + * if iconv is not available! + * + * @link http://php.net/mb_strpos + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $encoding + * @return mixed + */ + function mb_strpos($haystack, $needle, $offset = 0, $encoding = NULL) + { + if (ICONV_ENABLED === TRUE) + { + return iconv_strpos($haystack, $needle, $offset, isset($encoding) ? $encoding : config_item('charset')); + } + + log_message('debug', 'Compatibility (mbstring): iconv_strpos() is not available, falling back to strpos().'); + return strpos($haystack, $needle, $offset); + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('mb_substr')) +{ + /** + * mb_substr() + * + * WARNING: This function WILL fall-back to substr() + * if iconv is not available. + * + * @link http://php.net/mb_substr + * @param string $str + * @param int $start + * @param int $length + * @param string $encoding + * @return string + */ + function mb_substr($str, $start, $length = NULL, $encoding = NULL) + { + if (ICONV_ENABLED === TRUE) + { + isset($encoding) OR $encoding = config_item('charset'); + return iconv_substr( + $str, + $start, + isset($length) ? $length : iconv_strlen($str, $encoding), // NULL doesn't work + $encoding + ); + } + + log_message('debug', 'Compatibility (mbstring): iconv_substr() is not available, falling back to substr().'); + return isset($length) + ? substr($str, $start, $length) + : substr($str, $start); + } +} diff --git a/system/core/compat/password.php b/system/core/compat/password.php new file mode 100644 index 000000000..8176f0088 --- /dev/null +++ b/system/core/compat/password.php @@ -0,0 +1,251 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014 - 2017, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) + * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link https://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * PHP ext/standard/password compatibility package + * + * @package CodeIgniter + * @subpackage CodeIgniter + * @category Compatibility + * @author Andrey Andreev + * @link https://codeigniter.com/user_guide/ + * @link http://php.net/password + */ + +// ------------------------------------------------------------------------ + +if (is_php('5.5') OR ! defined('CRYPT_BLOWFISH') OR CRYPT_BLOWFISH !== 1 OR defined('HHVM_VERSION')) +{ + return; +} + +// ------------------------------------------------------------------------ + +defined('PASSWORD_BCRYPT') OR define('PASSWORD_BCRYPT', 1); +defined('PASSWORD_DEFAULT') OR define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); + +// ------------------------------------------------------------------------ + +if ( ! function_exists('password_get_info')) +{ + /** + * password_get_info() + * + * @link http://php.net/password_get_info + * @param string $hash + * @return array + */ + function password_get_info($hash) + { + return (strlen($hash) < 60 OR sscanf($hash, '$2y$%d', $hash) !== 1) + ? array('algo' => 0, 'algoName' => 'unknown', 'options' => array()) + : array('algo' => 1, 'algoName' => 'bcrypt', 'options' => array('cost' => $hash)); + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('password_hash')) +{ + /** + * password_hash() + * + * @link http://php.net/password_hash + * @param string $password + * @param int $algo + * @param array $options + * @return mixed + */ + function password_hash($password, $algo, array $options = array()) + { + static $func_overload; + isset($func_overload) OR $func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); + + if ($algo !== 1) + { + trigger_error('password_hash(): Unknown hashing algorithm: '.(int) $algo, E_USER_WARNING); + return NULL; + } + + if (isset($options['cost']) && ($options['cost'] < 4 OR $options['cost'] > 31)) + { + trigger_error('password_hash(): Invalid bcrypt cost parameter specified: '.(int) $options['cost'], E_USER_WARNING); + return NULL; + } + + if (isset($options['salt']) && ($saltlen = ($func_overload ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22) + { + trigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING); + return NULL; + } + elseif ( ! isset($options['salt'])) + { + if (function_exists('random_bytes')) + { + try + { + $options['salt'] = random_bytes(16); + } + catch (Exception $e) + { + log_message('error', 'compat/password: Error while trying to use random_bytes(): '.$e->getMessage()); + return FALSE; + } + } + elseif (defined('MCRYPT_DEV_URANDOM')) + { + $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); + } + elseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') OR is_readable($dev = '/dev/urandom'))) + { + if (($fp = fopen($dev, 'rb')) === FALSE) + { + log_message('error', 'compat/password: Unable to open '.$dev.' for reading.'); + return FALSE; + } + + // Try not to waste entropy ... + is_php('5.4') && stream_set_chunk_size($fp, 16); + + $options['salt'] = ''; + for ($read = 0; $read < 16; $read = ($func_overload) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) + { + if (($read = fread($fp, 16 - $read)) === FALSE) + { + log_message('error', 'compat/password: Error while reading from '.$dev.'.'); + return FALSE; + } + $options['salt'] .= $read; + } + + fclose($fp); + } + elseif (function_exists('openssl_random_pseudo_bytes')) + { + $is_secure = NULL; + $options['salt'] = openssl_random_pseudo_bytes(16, $is_secure); + if ($is_secure !== TRUE) + { + log_message('error', 'compat/password: openssl_random_pseudo_bytes() set the $cryto_strong flag to FALSE'); + return FALSE; + } + } + else + { + log_message('error', 'compat/password: No CSPRNG available.'); + return FALSE; + } + + $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); + } + elseif ( ! preg_match('#^[a-zA-Z0-9./]+$#D', $options['salt'])) + { + $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); + } + + isset($options['cost']) OR $options['cost'] = 10; + + return (strlen($password = crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']))) === 60) + ? $password + : FALSE; + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('password_needs_rehash')) +{ + /** + * password_needs_rehash() + * + * @link http://php.net/password_needs_rehash + * @param string $hash + * @param int $algo + * @param array $options + * @return bool + */ + function password_needs_rehash($hash, $algo, array $options = array()) + { + $info = password_get_info($hash); + + if ($algo !== $info['algo']) + { + return TRUE; + } + elseif ($algo === 1) + { + $options['cost'] = isset($options['cost']) ? (int) $options['cost'] : 10; + return ($info['options']['cost'] !== $options['cost']); + } + + // Odd at first glance, but according to a comment in PHP's own unit tests, + // because it is an unknown algorithm - it's valid and therefore doesn't + // need rehashing. + return FALSE; + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('password_verify')) +{ + /** + * password_verify() + * + * @link http://php.net/password_verify + * @param string $password + * @param string $hash + * @return bool + */ + function password_verify($password, $hash) + { + if (strlen($hash) !== 60 OR strlen($password = crypt($password, $hash)) !== 60) + { + return FALSE; + } + + $compare = 0; + for ($i = 0; $i < 60; $i++) + { + $compare |= (ord($password[$i]) ^ ord($hash[$i])); + } + + return ($compare === 0); + } +} diff --git a/system/core/compat/standard.php b/system/core/compat/standard.php new file mode 100644 index 000000000..7db2efb57 --- /dev/null +++ b/system/core/compat/standard.php @@ -0,0 +1,182 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014 - 2017, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/) + * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link https://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * PHP ext/standard compatibility package + * + * @package CodeIgniter + * @subpackage CodeIgniter + * @category Compatibility + * @author Andrey Andreev + * @link https://codeigniter.com/user_guide/ + */ + +// ------------------------------------------------------------------------ + +if (is_php('5.5')) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('array_column')) +{ + /** + * array_column() + * + * @link http://php.net/array_column + * @param array $array + * @param mixed $column_key + * @param mixed $index_key + * @return array + */ + function array_column(array $array, $column_key, $index_key = NULL) + { + if ( ! in_array($type = gettype($column_key), array('integer', 'string', 'NULL'), TRUE)) + { + if ($type === 'double') + { + $column_key = (int) $column_key; + } + elseif ($type === 'object' && method_exists($column_key, '__toString')) + { + $column_key = (string) $column_key; + } + else + { + trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING); + return FALSE; + } + } + + if ( ! in_array($type = gettype($index_key), array('integer', 'string', 'NULL'), TRUE)) + { + if ($type === 'double') + { + $index_key = (int) $index_key; + } + elseif ($type === 'object' && method_exists($index_key, '__toString')) + { + $index_key = (string) $index_key; + } + else + { + trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING); + return FALSE; + } + } + + $result = array(); + foreach ($array as &$a) + { + if ($column_key === NULL) + { + $value = $a; + } + elseif (is_array($a) && array_key_exists($column_key, $a)) + { + $value = $a[$column_key]; + } + else + { + continue; + } + + if ($index_key === NULL OR ! array_key_exists($index_key, $a)) + { + $result[] = $value; + } + else + { + $result[$a[$index_key]] = $value; + } + } + + return $result; + } +} + +// ------------------------------------------------------------------------ + +if (is_php('5.4')) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('hex2bin')) +{ + /** + * hex2bin() + * + * @link http://php.net/hex2bin + * @param string $data + * @return string + */ + function hex2bin($data) + { + if (in_array($type = gettype($data), array('array', 'double', 'object', 'resource'), TRUE)) + { + if ($type === 'object' && method_exists($data, '__toString')) + { + $data = (string) $data; + } + else + { + trigger_error('hex2bin() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING); + return NULL; + } + } + + if (strlen($data) % 2 !== 0) + { + trigger_error('Hexadecimal input string must have an even length', E_USER_WARNING); + return FALSE; + } + elseif ( ! preg_match('/^[0-9a-f]*$/i', $data)) + { + trigger_error('Input string must be hexadecimal string', E_USER_WARNING); + return FALSE; + } + + return pack('H*', $data); + } +} |