/libs/upgradephp/upgrade.php
PHP | 676 lines | 407 code | 50 blank | 219 comment | 117 complexity | 4cc4006f9ae5e23b73e69c51b64cd99c MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
- <?php
- /**
- * api: php
- * title: upgrade.php
- * description: Emulates functions from new PHP versions on older interpreters.
- * version: 17
- * license: Public Domain
- * url: http://freshmeat.net/projects/upgradephp
- * type: functions
- * category: library
- * priority: auto
- * load_if: (PHP_VERSION<5.2)
- * sort: -255
- * provides: upgrade-php, api:php5, json
- *
- *
- * By loading this library you get PHP version independence. It provides
- * downwards compatibility to older PHP interpreters by emulating missing
- * functions or constants using IDENTICAL NAMES. So this doesn't slow down
- * script execution on setups where the native functions already exist. It
- * is meant as quick drop-in solution. It spares you from rewriting code or
- * using cumbersome workarounds instead of the more powerful v5 functions.
- *
- * It cannot mirror PHP5s extended OO-semantics and functionality into PHP4
- * however. A few features are added here that weren't part of PHP yet. And
- * some other function collections are separated out into the ext/ directory.
- * It doesn't produce many custom error messages (YAGNI), and instead leaves
- * reporting to invoked functions or for native PHP execution.
- *
- * And further this is PUBLIC DOMAIN (no copyright, no license, no warranty)
- * so therefore compatible to ALL open source licenses. You could rip this
- * paragraph out to republish this instead only under more restrictive terms
- * or your favorite license (GNU LGPL/GPL, BSDL, MPL/CDDL, Artistic/PHPL, ..)
- *
- * Any contribution is appreciated. <milky*users#sf#net>
- *
- */
- use Piwik\SettingsServer;
- /**
- * ------------------------------ 5.2 ---
- * @group 5_2
- * @since 5.2
- *
- * Additions of PHP 5.2.0
- * - some listed here might have appeared earlier or in release candidates
- *
- * @emulated
- * error_get_last
- * preg_last_error
- * lchown
- * lchgrp
- * E_RECOVERABLE_ERROR
- * M_SQRTPI
- * M_LNPI
- * M_EULER
- * M_SQRT3
- *
- * @missing
- * sys_getloadavg
- * inet_ntop
- * inet_pton
- * array_fill_keys
- * array_intersect_key
- * array_intersect_ukey
- * array_diff_key
- * array_diff_ukey
- * array_product
- * pdo_drivers
- * ftp_ssl_connect
- * XmlReader
- * XmlWriter
- * PDO*
- *
- * @unimplementable
- * stream_*
- *
- */
- /**
- * Constants for future 64-bit integer support.
- *
- */
- if (!defined("PHP_INT_SIZE")) { define("PHP_INT_SIZE", 4); }
- if (!defined("PHP_INT_MAX")) { define("PHP_INT_MAX", 2147483647); }
- /*
- These functions emulate the "character type" extension, which is
- present in PHP first since version 4.3 per default. In this variant
- only ASCII and Latin-1 characters are being handled. The first part
- is eventually faster.
- */
- /**
- * Sets the default client character set.
- *
- * @compat
- * Procedural style
- * @bugs
- * PHP documentation says this function exists in PHP 5 >= 5.0.5,
- * but it also depends on the versions of external libraries, e.g.,
- * php_mysqli.dll and libmysql.dll.
- *
- * @param $link mysqli MySQLi connection resource
- * @param $charset string Character set
- * @return bool TRUE on success, FALSE on failure
- */
- if (in_array('mysqli', @get_loaded_extensions()) && !function_exists('mysqli_set_charset')) {
- function mysqli_set_charset($link, $charset)
- {
- return mysqli_query($link, "SET NAMES '$charset'");
- }
- }
- /**
- * parse_ini_file() replacement.
- * Behaves like parse_ini_file($filename, $process_sections);
- *
- * @author Andrew Sohn <asohn (at) aircanopy (dot) net>
- * @author anthon (dot) pang (at) gmail (dot) com
- *
- * @param string $filename
- * @param bool $process_sections (defaults to false)
- * @return array
- */
- if(function_exists('parse_ini_file')) {
- // provide a wrapper
- function _parse_ini_file($filename, $process_sections = false) {
- return file_exists($filename) ? parse_ini_file($filename, $process_sections) : false;
- }
- } else {
- // we can't redefine parse_ini_file() if it has been disabled
- function _parse_ini_file($filename, $process_sections = false)
- {
- if(!file_exists($filename)) {
- return false;
- }
- if(function_exists('file_get_contents')) {
- $ini = file_get_contents($filename);
- } else if(function_exists('file')) {
- if($ini = file($filename)) {
- $ini = implode("\n", $ini);
- }
- } else if(function_exists('fopen') && function_exists('fread')) {
- $handle = fopen($filename, 'r');
- if(!$handle) {
- return false;
- }
- $ini = fread($handle, filesize($filename));
- fclose($handle);
- } else {
- return false;
- }
- if($ini === false) {
- return false;
- }
- if(is_string($ini)) { $ini = explode("\n", str_replace("\r", "\n", $ini)); }
- if (count($ini) == 0) { return array(); }
- $sections = array();
- $values = array();
- $result = array();
- $globals = array();
- $i = 0;
- foreach ($ini as $line) {
- $line = trim($line);
- $line = str_replace("\t", " ", $line);
- // Comments
- if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}
- // Sections
- if ($line{0} == '[') {
- $tmp = explode(']', $line);
- $sections[] = trim(substr($tmp[0], 1));
- $i++;
- continue;
- }
- // Key-value pair
- list($key, $value) = explode('=', $line, 2);
- $key = trim($key);
- $value = trim($value);
- if (strstr($value, ";")) {
- $tmp = explode(';', $value);
- if (count($tmp) == 2) {
- if ((($value{0} != '"') && ($value{0} != "'")) ||
- preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
- preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
- $value = $tmp[0];
- }
- } else {
- if ($value{0} == '"') {
- $value = preg_replace('/^"(.*)".*/', '$1', $value);
- } elseif ($value{0} == "'") {
- $value = preg_replace("/^'(.*)'.*/", '$1', $value);
- } else {
- $value = $tmp[0];
- }
- }
- }
- $value = trim($value);
- $value = trim($value, "'\"");
- if ($i == 0) {
- if (substr($key, -2) == '[]') {
- $globals[substr($key, 0, -2)][] = $value;
- } else {
- $globals[$key] = $value;
- }
- } else {
- if (substr($key, -2) == '[]') {
- $values[$i-1][substr($key, 0, -2)][] = $value;
- } else {
- $values[$i-1][$key] = $value;
- }
- }
- }
- for ($j = 0; $j < $i; $j++) {
- if (isset($values[$j])) {
- if ($process_sections === true) {
- $result[$sections[$j]] = $values[$j];
- } else {
- $result[] = $values[$j];
- }
- } else {
- if ($process_sections === true) {
- $result[$sections[$j]] = array();
- }
- }
- }
- return $result + $globals;
- }
- }
- /**
- * glob() replacement.
- * Behaves like glob($pattern, $flags)
- *
- * @author BigueNique AT yahoo DOT ca
- * @author anthon (dot) pang (at) gmail (dot) com
- *
- * @param string $pattern
- * @param int $flags GLOBL_ONLYDIR, GLOB_MARK, GLOB_NOSORT (other flags not supported; defaults to 0)
- * @return array
- */
- if(function_exists('glob')) {
- // provide a wrapper
- function _glob($pattern, $flags = 0) {
- return glob($pattern, $flags);
- }
- } else if(function_exists('opendir') && function_exists('readdir')) {
- // we can't redefine glob() if it has been disabled
- function _glob($pattern, $flags = 0) {
- $path = dirname($pattern);
- $filePattern = basename($pattern);
- if(is_dir($path) && ($handle = opendir($path)) !== false) {
- $matches = array();
- while(($file = readdir($handle)) !== false) {
- if(($file[0] != '.')
- && fnmatch($filePattern, $file)
- && (!($flags & GLOB_ONLYDIR) || is_dir("$path/$file"))) {
- $matches[] = "$path/$file" . ($flags & GLOB_MARK ? '/' : '');
- }
- }
- closedir($handle);
- if(!($flags & GLOB_NOSORT)) {
- sort($matches);
- }
- return $matches;
- }
- return false;
- }
- } else {
- function _glob($pattern, $flags = 0) {
- return false;
- }
- }
- /**
- * Reads entire file into a string.
- * This function is not 100% compatible with the native function.
- *
- * @see http://php.net/file_get_contents
- * @since PHP 4.3.0
- *
- * @param string $filename Name of the file to read.
- * @return string The read data or false on failure.
- */
- if (!function_exists('file_get_contents'))
- {
- function file_get_contents($filename)
- {
- $fhandle = fopen($filename, "r");
- $fcontents = fread($fhandle, filesize($filename));
- fclose($fhandle);
- return $fcontents;
- }
- }
- /**
- * Safe serialize() and unserialize() replacements
- *
- * @license Public Domain
- *
- * @author anthon (dot) pang (at) gmail (dot) com
- */
- /*
- * Arbitrary limits for safe_unserialize()
- */
- define('MAX_SERIALIZED_INPUT_LENGTH', 4096);
- define('MAX_SERIALIZED_ARRAY_LENGTH', 256);
- define('MAX_SERIALIZED_ARRAY_DEPTH', 3);
- /**
- * Safe serialize() replacement
- * - output a strict subset of PHP's native serialized representation
- * - does not serialize objects
- *
- * @param mixed $value
- * @return string
- * @throw Exception if $value is malformed or contains unsupported types (e.g., resources, objects)
- */
- function _safe_serialize( $value )
- {
- if(is_null($value))
- {
- return 'N;';
- }
- if(is_bool($value))
- {
- return 'b:'.(int)$value.';';
- }
- if(is_int($value))
- {
- return 'i:'.$value.';';
- }
- if(is_float($value))
- {
- return 'd:'.$value.';';
- }
- if(is_string($value))
- {
- return 's:'.strlen($value).':"'.$value.'";';
- }
- if(is_array($value))
- {
- $out = '';
- foreach($value as $k => $v)
- {
- $out .= _safe_serialize($k) . _safe_serialize($v);
- }
-
- return 'a:'.count($value).':{'.$out.'}';
- }
- // safe_serialize cannot serialize resources or objects
- return false;
- }
- /**
- * Wrapper for _safe_serialize() that handles exceptions and multibyte encoding issue
- *
- * @param mixed $value
- * @return string
- */
- function safe_serialize( $value )
- {
- // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
- if (function_exists('mb_internal_encoding') &&
- (((int) ini_get('mbstring.func_overload')) & 2))
- {
- $mbIntEnc = mb_internal_encoding();
- mb_internal_encoding('ASCII');
- }
- $out = _safe_serialize($value);
- if (isset($mbIntEnc))
- {
- mb_internal_encoding($mbIntEnc);
- }
- return $out;
- }
- /**
- * Safe unserialize() replacement
- * - accepts a strict subset of PHP's native serialized representation
- * - does not unserialize objects
- *
- * @param string $str
- * @return mixed
- * @throw Exception if $str is malformed or contains unsupported types (e.g., resources, objects)
- */
- function _safe_unserialize($str)
- {
- if(strlen($str) > MAX_SERIALIZED_INPUT_LENGTH)
- {
- // input exceeds MAX_SERIALIZED_INPUT_LENGTH
- return false;
- }
- if(empty($str) || !is_string($str))
- {
- return false;
- }
- $stack = array();
- $expected = array();
- /*
- * states:
- * 0 - initial state, expecting a single value or array
- * 1 - terminal state
- * 2 - in array, expecting end of array or a key
- * 3 - in array, expecting value or another array
- */
- $state = 0;
- while($state != 1)
- {
- $type = isset($str[0]) ? $str[0] : '';
- if($type == '}')
- {
- $str = substr($str, 1);
- }
- else if($type == 'N' && $str[1] == ';')
- {
- $value = null;
- $str = substr($str, 2);
- }
- else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
- {
- $value = $matches[1] == '1' ? true : false;
- $str = substr($str, 4);
- }
- else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
- {
- $value = (int)$matches[1];
- $str = $matches[2];
- }
- else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
- {
- $value = (float)$matches[1];
- $str = $matches[3];
- }
- else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";')
- {
- $value = substr($matches[2], 0, (int)$matches[1]);
- $str = substr($matches[2], (int)$matches[1] + 2);
- }
- else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches) && $matches[1] < MAX_SERIALIZED_ARRAY_LENGTH)
- {
- $expectedLength = (int)$matches[1];
- $str = $matches[2];
- }
- else
- {
- // object or unknown/malformed type
- return false;
- }
- switch($state)
- {
- case 3: // in array, expecting value or another array
- if($type == 'a')
- {
- if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
- {
- // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
- return false;
- }
- $stack[] = &$list;
- $list[$key] = array();
- $list = &$list[$key];
- $expected[] = $expectedLength;
- $state = 2;
- break;
- }
- if($type != '}')
- {
- $list[$key] = $value;
- $state = 2;
- break;
- }
- // missing array value
- return false;
- case 2: // in array, expecting end of array or a key
- if($type == '}')
- {
- if(count($list) < end($expected))
- {
- // array size less than expected
- return false;
- }
- unset($list);
- $list = &$stack[count($stack)-1];
- array_pop($stack);
- // go to terminal state if we're at the end of the root array
- array_pop($expected);
- if(count($expected) == 0) {
- $state = 1;
- }
- break;
- }
- if($type == 'i' || $type == 's')
- {
- if(count($list) >= MAX_SERIALIZED_ARRAY_LENGTH)
- {
- // array size exceeds MAX_SERIALIZED_ARRAY_LENGTH
- return false;
- }
- if(count($list) >= end($expected))
- {
- // array size exceeds expected length
- return false;
- }
- $key = $value;
- $state = 3;
- break;
- }
- // illegal array index type
- return false;
- case 0: // expecting array or value
- if($type == 'a')
- {
- if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
- {
- // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
- return false;
- }
- $data = array();
- $list = &$data;
- $expected[] = $expectedLength;
- $state = 2;
- break;
- }
- if($type != '}')
- {
- $data = $value;
- $state = 1;
- break;
- }
- // not in array
- return false;
- }
- }
- if(!empty($str))
- {
- // trailing data in input
- return false;
- }
- return $data;
- }
- /**
- * Wrapper for _safe_unserialize() that handles exceptions and multibyte encoding issue
- *
- * @param string $str
- * @return mixed
- */
- function safe_unserialize( $str )
- {
- // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
- if (function_exists('mb_internal_encoding') &&
- (((int) ini_get('mbstring.func_overload')) & 2))
- {
- $mbIntEnc = mb_internal_encoding();
- mb_internal_encoding('ASCII');
- }
- $out = _safe_unserialize($str);
- if (isset($mbIntEnc))
- {
- mb_internal_encoding($mbIntEnc);
- }
- return $out;
- }
- /**
- * readfile() replacement.
- * Behaves similar to readfile($filename);
- *
- * @author anthon (dot) pang (at) gmail (dot) com
- *
- * @param string $filename
- * @param bool $useIncludePath
- * @param resource $context
- * @return int the number of bytes read from the file, or false if an error occurs
- */
- function _readfile($filename, $useIncludePath = false, $context = null)
- {
- $count = @filesize($filename);
- // built-in function has a 2 MB limit when using mmap
- if (function_exists('readfile') && $count <= (2 * 1024 * 1024)) {
- return @readfile($filename, $useIncludePath, $context);
- }
- // when in doubt (or when readfile() function is disabled)
- $handle = @fopen($filename, SettingsServer::isWindows() ? "rb" : "r");
- if ($handle) {
- while(!feof($handle)) {
- echo fread($handle, 8192);
- ob_flush();
- flush();
- }
- fclose($handle);
- return $count;
- }
- return false;
- }
- /**
- * utf8_encode replacement
- *
- * @param string $data
- * @return string
- */
- if (!function_exists('utf8_encode')) {
- function utf8_encode($data) {
- if (function_exists('iconv')) {
- return @iconv('ISO-8859-1', 'UTF-8', $data);
- }
- return $data;
- }
- }
- /**
- * utf8_decode replacement
- *
- * @param string $data
- * @return string
- */
- if (!function_exists('utf8_decode')) {
- function utf8_decode($data) {
- if (function_exists('iconv')) {
- return @iconv('UTF-8', 'ISO-8859-1', $data);
- }
- return $data;
- }
- }
- /**
- * Use strtolower if mb_strtolower doesn't exist (i.e., php not compiled with --enable-mbstring)
- * This is not a functional replacement for mb_strtolower.
- *
- * @param string $input
- * @param string $charset
- */
- if(!function_exists('mb_strtolower')) {
- function mb_strtolower($input, $charset) {
- return strtolower($input);
- }
- }