PageRenderTime 34ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/upgradephp/upgrade.php

https://github.com/CodeYellowBV/piwik
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
  1. <?php
  2. /**
  3. * api: php
  4. * title: upgrade.php
  5. * description: Emulates functions from new PHP versions on older interpreters.
  6. * version: 17
  7. * license: Public Domain
  8. * url: http://freshmeat.net/projects/upgradephp
  9. * type: functions
  10. * category: library
  11. * priority: auto
  12. * load_if: (PHP_VERSION<5.2)
  13. * sort: -255
  14. * provides: upgrade-php, api:php5, json
  15. *
  16. *
  17. * By loading this library you get PHP version independence. It provides
  18. * downwards compatibility to older PHP interpreters by emulating missing
  19. * functions or constants using IDENTICAL NAMES. So this doesn't slow down
  20. * script execution on setups where the native functions already exist. It
  21. * is meant as quick drop-in solution. It spares you from rewriting code or
  22. * using cumbersome workarounds instead of the more powerful v5 functions.
  23. *
  24. * It cannot mirror PHP5s extended OO-semantics and functionality into PHP4
  25. * however. A few features are added here that weren't part of PHP yet. And
  26. * some other function collections are separated out into the ext/ directory.
  27. * It doesn't produce many custom error messages (YAGNI), and instead leaves
  28. * reporting to invoked functions or for native PHP execution.
  29. *
  30. * And further this is PUBLIC DOMAIN (no copyright, no license, no warranty)
  31. * so therefore compatible to ALL open source licenses. You could rip this
  32. * paragraph out to republish this instead only under more restrictive terms
  33. * or your favorite license (GNU LGPL/GPL, BSDL, MPL/CDDL, Artistic/PHPL, ..)
  34. *
  35. * Any contribution is appreciated. <milky*users#sf#net>
  36. *
  37. */
  38. use Piwik\SettingsServer;
  39. /**
  40. * ------------------------------ 5.2 ---
  41. * @group 5_2
  42. * @since 5.2
  43. *
  44. * Additions of PHP 5.2.0
  45. * - some listed here might have appeared earlier or in release candidates
  46. *
  47. * @emulated
  48. * error_get_last
  49. * preg_last_error
  50. * lchown
  51. * lchgrp
  52. * E_RECOVERABLE_ERROR
  53. * M_SQRTPI
  54. * M_LNPI
  55. * M_EULER
  56. * M_SQRT3
  57. *
  58. * @missing
  59. * sys_getloadavg
  60. * inet_ntop
  61. * inet_pton
  62. * array_fill_keys
  63. * array_intersect_key
  64. * array_intersect_ukey
  65. * array_diff_key
  66. * array_diff_ukey
  67. * array_product
  68. * pdo_drivers
  69. * ftp_ssl_connect
  70. * XmlReader
  71. * XmlWriter
  72. * PDO*
  73. *
  74. * @unimplementable
  75. * stream_*
  76. *
  77. */
  78. /**
  79. * Constants for future 64-bit integer support.
  80. *
  81. */
  82. if (!defined("PHP_INT_SIZE")) { define("PHP_INT_SIZE", 4); }
  83. if (!defined("PHP_INT_MAX")) { define("PHP_INT_MAX", 2147483647); }
  84. /*
  85. These functions emulate the "character type" extension, which is
  86. present in PHP first since version 4.3 per default. In this variant
  87. only ASCII and Latin-1 characters are being handled. The first part
  88. is eventually faster.
  89. */
  90. /**
  91. * Sets the default client character set.
  92. *
  93. * @compat
  94. * Procedural style
  95. * @bugs
  96. * PHP documentation says this function exists in PHP 5 >= 5.0.5,
  97. * but it also depends on the versions of external libraries, e.g.,
  98. * php_mysqli.dll and libmysql.dll.
  99. *
  100. * @param $link mysqli MySQLi connection resource
  101. * @param $charset string Character set
  102. * @return bool TRUE on success, FALSE on failure
  103. */
  104. if (in_array('mysqli', @get_loaded_extensions()) && !function_exists('mysqli_set_charset')) {
  105. function mysqli_set_charset($link, $charset)
  106. {
  107. return mysqli_query($link, "SET NAMES '$charset'");
  108. }
  109. }
  110. /**
  111. * parse_ini_file() replacement.
  112. * Behaves like parse_ini_file($filename, $process_sections);
  113. *
  114. * @author Andrew Sohn <asohn (at) aircanopy (dot) net>
  115. * @author anthon (dot) pang (at) gmail (dot) com
  116. *
  117. * @param string $filename
  118. * @param bool $process_sections (defaults to false)
  119. * @return array
  120. */
  121. if(function_exists('parse_ini_file')) {
  122. // provide a wrapper
  123. function _parse_ini_file($filename, $process_sections = false) {
  124. return file_exists($filename) ? parse_ini_file($filename, $process_sections) : false;
  125. }
  126. } else {
  127. // we can't redefine parse_ini_file() if it has been disabled
  128. function _parse_ini_file($filename, $process_sections = false)
  129. {
  130. if(!file_exists($filename)) {
  131. return false;
  132. }
  133. if(function_exists('file_get_contents')) {
  134. $ini = file_get_contents($filename);
  135. } else if(function_exists('file')) {
  136. if($ini = file($filename)) {
  137. $ini = implode("\n", $ini);
  138. }
  139. } else if(function_exists('fopen') && function_exists('fread')) {
  140. $handle = fopen($filename, 'r');
  141. if(!$handle) {
  142. return false;
  143. }
  144. $ini = fread($handle, filesize($filename));
  145. fclose($handle);
  146. } else {
  147. return false;
  148. }
  149. if($ini === false) {
  150. return false;
  151. }
  152. if(is_string($ini)) { $ini = explode("\n", str_replace("\r", "\n", $ini)); }
  153. if (count($ini) == 0) { return array(); }
  154. $sections = array();
  155. $values = array();
  156. $result = array();
  157. $globals = array();
  158. $i = 0;
  159. foreach ($ini as $line) {
  160. $line = trim($line);
  161. $line = str_replace("\t", " ", $line);
  162. // Comments
  163. if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}
  164. // Sections
  165. if ($line{0} == '[') {
  166. $tmp = explode(']', $line);
  167. $sections[] = trim(substr($tmp[0], 1));
  168. $i++;
  169. continue;
  170. }
  171. // Key-value pair
  172. list($key, $value) = explode('=', $line, 2);
  173. $key = trim($key);
  174. $value = trim($value);
  175. if (strstr($value, ";")) {
  176. $tmp = explode(';', $value);
  177. if (count($tmp) == 2) {
  178. if ((($value{0} != '"') && ($value{0} != "'")) ||
  179. preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
  180. preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
  181. $value = $tmp[0];
  182. }
  183. } else {
  184. if ($value{0} == '"') {
  185. $value = preg_replace('/^"(.*)".*/', '$1', $value);
  186. } elseif ($value{0} == "'") {
  187. $value = preg_replace("/^'(.*)'.*/", '$1', $value);
  188. } else {
  189. $value = $tmp[0];
  190. }
  191. }
  192. }
  193. $value = trim($value);
  194. $value = trim($value, "'\"");
  195. if ($i == 0) {
  196. if (substr($key, -2) == '[]') {
  197. $globals[substr($key, 0, -2)][] = $value;
  198. } else {
  199. $globals[$key] = $value;
  200. }
  201. } else {
  202. if (substr($key, -2) == '[]') {
  203. $values[$i-1][substr($key, 0, -2)][] = $value;
  204. } else {
  205. $values[$i-1][$key] = $value;
  206. }
  207. }
  208. }
  209. for ($j = 0; $j < $i; $j++) {
  210. if (isset($values[$j])) {
  211. if ($process_sections === true) {
  212. $result[$sections[$j]] = $values[$j];
  213. } else {
  214. $result[] = $values[$j];
  215. }
  216. } else {
  217. if ($process_sections === true) {
  218. $result[$sections[$j]] = array();
  219. }
  220. }
  221. }
  222. return $result + $globals;
  223. }
  224. }
  225. /**
  226. * glob() replacement.
  227. * Behaves like glob($pattern, $flags)
  228. *
  229. * @author BigueNique AT yahoo DOT ca
  230. * @author anthon (dot) pang (at) gmail (dot) com
  231. *
  232. * @param string $pattern
  233. * @param int $flags GLOBL_ONLYDIR, GLOB_MARK, GLOB_NOSORT (other flags not supported; defaults to 0)
  234. * @return array
  235. */
  236. if(function_exists('glob')) {
  237. // provide a wrapper
  238. function _glob($pattern, $flags = 0) {
  239. return glob($pattern, $flags);
  240. }
  241. } else if(function_exists('opendir') && function_exists('readdir')) {
  242. // we can't redefine glob() if it has been disabled
  243. function _glob($pattern, $flags = 0) {
  244. $path = dirname($pattern);
  245. $filePattern = basename($pattern);
  246. if(is_dir($path) && ($handle = opendir($path)) !== false) {
  247. $matches = array();
  248. while(($file = readdir($handle)) !== false) {
  249. if(($file[0] != '.')
  250. && fnmatch($filePattern, $file)
  251. && (!($flags & GLOB_ONLYDIR) || is_dir("$path/$file"))) {
  252. $matches[] = "$path/$file" . ($flags & GLOB_MARK ? '/' : '');
  253. }
  254. }
  255. closedir($handle);
  256. if(!($flags & GLOB_NOSORT)) {
  257. sort($matches);
  258. }
  259. return $matches;
  260. }
  261. return false;
  262. }
  263. } else {
  264. function _glob($pattern, $flags = 0) {
  265. return false;
  266. }
  267. }
  268. /**
  269. * Reads entire file into a string.
  270. * This function is not 100% compatible with the native function.
  271. *
  272. * @see http://php.net/file_get_contents
  273. * @since PHP 4.3.0
  274. *
  275. * @param string $filename Name of the file to read.
  276. * @return string The read data or false on failure.
  277. */
  278. if (!function_exists('file_get_contents'))
  279. {
  280. function file_get_contents($filename)
  281. {
  282. $fhandle = fopen($filename, "r");
  283. $fcontents = fread($fhandle, filesize($filename));
  284. fclose($fhandle);
  285. return $fcontents;
  286. }
  287. }
  288. /**
  289. * Safe serialize() and unserialize() replacements
  290. *
  291. * @license Public Domain
  292. *
  293. * @author anthon (dot) pang (at) gmail (dot) com
  294. */
  295. /*
  296. * Arbitrary limits for safe_unserialize()
  297. */
  298. define('MAX_SERIALIZED_INPUT_LENGTH', 4096);
  299. define('MAX_SERIALIZED_ARRAY_LENGTH', 256);
  300. define('MAX_SERIALIZED_ARRAY_DEPTH', 3);
  301. /**
  302. * Safe serialize() replacement
  303. * - output a strict subset of PHP's native serialized representation
  304. * - does not serialize objects
  305. *
  306. * @param mixed $value
  307. * @return string
  308. * @throw Exception if $value is malformed or contains unsupported types (e.g., resources, objects)
  309. */
  310. function _safe_serialize( $value )
  311. {
  312. if(is_null($value))
  313. {
  314. return 'N;';
  315. }
  316. if(is_bool($value))
  317. {
  318. return 'b:'.(int)$value.';';
  319. }
  320. if(is_int($value))
  321. {
  322. return 'i:'.$value.';';
  323. }
  324. if(is_float($value))
  325. {
  326. return 'd:'.$value.';';
  327. }
  328. if(is_string($value))
  329. {
  330. return 's:'.strlen($value).':"'.$value.'";';
  331. }
  332. if(is_array($value))
  333. {
  334. $out = '';
  335. foreach($value as $k => $v)
  336. {
  337. $out .= _safe_serialize($k) . _safe_serialize($v);
  338. }
  339. return 'a:'.count($value).':{'.$out.'}';
  340. }
  341. // safe_serialize cannot serialize resources or objects
  342. return false;
  343. }
  344. /**
  345. * Wrapper for _safe_serialize() that handles exceptions and multibyte encoding issue
  346. *
  347. * @param mixed $value
  348. * @return string
  349. */
  350. function safe_serialize( $value )
  351. {
  352. // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
  353. if (function_exists('mb_internal_encoding') &&
  354. (((int) ini_get('mbstring.func_overload')) & 2))
  355. {
  356. $mbIntEnc = mb_internal_encoding();
  357. mb_internal_encoding('ASCII');
  358. }
  359. $out = _safe_serialize($value);
  360. if (isset($mbIntEnc))
  361. {
  362. mb_internal_encoding($mbIntEnc);
  363. }
  364. return $out;
  365. }
  366. /**
  367. * Safe unserialize() replacement
  368. * - accepts a strict subset of PHP's native serialized representation
  369. * - does not unserialize objects
  370. *
  371. * @param string $str
  372. * @return mixed
  373. * @throw Exception if $str is malformed or contains unsupported types (e.g., resources, objects)
  374. */
  375. function _safe_unserialize($str)
  376. {
  377. if(strlen($str) > MAX_SERIALIZED_INPUT_LENGTH)
  378. {
  379. // input exceeds MAX_SERIALIZED_INPUT_LENGTH
  380. return false;
  381. }
  382. if(empty($str) || !is_string($str))
  383. {
  384. return false;
  385. }
  386. $stack = array();
  387. $expected = array();
  388. /*
  389. * states:
  390. * 0 - initial state, expecting a single value or array
  391. * 1 - terminal state
  392. * 2 - in array, expecting end of array or a key
  393. * 3 - in array, expecting value or another array
  394. */
  395. $state = 0;
  396. while($state != 1)
  397. {
  398. $type = isset($str[0]) ? $str[0] : '';
  399. if($type == '}')
  400. {
  401. $str = substr($str, 1);
  402. }
  403. else if($type == 'N' && $str[1] == ';')
  404. {
  405. $value = null;
  406. $str = substr($str, 2);
  407. }
  408. else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
  409. {
  410. $value = $matches[1] == '1' ? true : false;
  411. $str = substr($str, 4);
  412. }
  413. else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
  414. {
  415. $value = (int)$matches[1];
  416. $str = $matches[2];
  417. }
  418. else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
  419. {
  420. $value = (float)$matches[1];
  421. $str = $matches[3];
  422. }
  423. else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";')
  424. {
  425. $value = substr($matches[2], 0, (int)$matches[1]);
  426. $str = substr($matches[2], (int)$matches[1] + 2);
  427. }
  428. else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches) && $matches[1] < MAX_SERIALIZED_ARRAY_LENGTH)
  429. {
  430. $expectedLength = (int)$matches[1];
  431. $str = $matches[2];
  432. }
  433. else
  434. {
  435. // object or unknown/malformed type
  436. return false;
  437. }
  438. switch($state)
  439. {
  440. case 3: // in array, expecting value or another array
  441. if($type == 'a')
  442. {
  443. if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
  444. {
  445. // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
  446. return false;
  447. }
  448. $stack[] = &$list;
  449. $list[$key] = array();
  450. $list = &$list[$key];
  451. $expected[] = $expectedLength;
  452. $state = 2;
  453. break;
  454. }
  455. if($type != '}')
  456. {
  457. $list[$key] = $value;
  458. $state = 2;
  459. break;
  460. }
  461. // missing array value
  462. return false;
  463. case 2: // in array, expecting end of array or a key
  464. if($type == '}')
  465. {
  466. if(count($list) < end($expected))
  467. {
  468. // array size less than expected
  469. return false;
  470. }
  471. unset($list);
  472. $list = &$stack[count($stack)-1];
  473. array_pop($stack);
  474. // go to terminal state if we're at the end of the root array
  475. array_pop($expected);
  476. if(count($expected) == 0) {
  477. $state = 1;
  478. }
  479. break;
  480. }
  481. if($type == 'i' || $type == 's')
  482. {
  483. if(count($list) >= MAX_SERIALIZED_ARRAY_LENGTH)
  484. {
  485. // array size exceeds MAX_SERIALIZED_ARRAY_LENGTH
  486. return false;
  487. }
  488. if(count($list) >= end($expected))
  489. {
  490. // array size exceeds expected length
  491. return false;
  492. }
  493. $key = $value;
  494. $state = 3;
  495. break;
  496. }
  497. // illegal array index type
  498. return false;
  499. case 0: // expecting array or value
  500. if($type == 'a')
  501. {
  502. if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
  503. {
  504. // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
  505. return false;
  506. }
  507. $data = array();
  508. $list = &$data;
  509. $expected[] = $expectedLength;
  510. $state = 2;
  511. break;
  512. }
  513. if($type != '}')
  514. {
  515. $data = $value;
  516. $state = 1;
  517. break;
  518. }
  519. // not in array
  520. return false;
  521. }
  522. }
  523. if(!empty($str))
  524. {
  525. // trailing data in input
  526. return false;
  527. }
  528. return $data;
  529. }
  530. /**
  531. * Wrapper for _safe_unserialize() that handles exceptions and multibyte encoding issue
  532. *
  533. * @param string $str
  534. * @return mixed
  535. */
  536. function safe_unserialize( $str )
  537. {
  538. // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
  539. if (function_exists('mb_internal_encoding') &&
  540. (((int) ini_get('mbstring.func_overload')) & 2))
  541. {
  542. $mbIntEnc = mb_internal_encoding();
  543. mb_internal_encoding('ASCII');
  544. }
  545. $out = _safe_unserialize($str);
  546. if (isset($mbIntEnc))
  547. {
  548. mb_internal_encoding($mbIntEnc);
  549. }
  550. return $out;
  551. }
  552. /**
  553. * readfile() replacement.
  554. * Behaves similar to readfile($filename);
  555. *
  556. * @author anthon (dot) pang (at) gmail (dot) com
  557. *
  558. * @param string $filename
  559. * @param bool $useIncludePath
  560. * @param resource $context
  561. * @return int the number of bytes read from the file, or false if an error occurs
  562. */
  563. function _readfile($filename, $useIncludePath = false, $context = null)
  564. {
  565. $count = @filesize($filename);
  566. // built-in function has a 2 MB limit when using mmap
  567. if (function_exists('readfile') && $count <= (2 * 1024 * 1024)) {
  568. return @readfile($filename, $useIncludePath, $context);
  569. }
  570. // when in doubt (or when readfile() function is disabled)
  571. $handle = @fopen($filename, SettingsServer::isWindows() ? "rb" : "r");
  572. if ($handle) {
  573. while(!feof($handle)) {
  574. echo fread($handle, 8192);
  575. ob_flush();
  576. flush();
  577. }
  578. fclose($handle);
  579. return $count;
  580. }
  581. return false;
  582. }
  583. /**
  584. * utf8_encode replacement
  585. *
  586. * @param string $data
  587. * @return string
  588. */
  589. if (!function_exists('utf8_encode')) {
  590. function utf8_encode($data) {
  591. if (function_exists('iconv')) {
  592. return @iconv('ISO-8859-1', 'UTF-8', $data);
  593. }
  594. return $data;
  595. }
  596. }
  597. /**
  598. * utf8_decode replacement
  599. *
  600. * @param string $data
  601. * @return string
  602. */
  603. if (!function_exists('utf8_decode')) {
  604. function utf8_decode($data) {
  605. if (function_exists('iconv')) {
  606. return @iconv('UTF-8', 'ISO-8859-1', $data);
  607. }
  608. return $data;
  609. }
  610. }
  611. /**
  612. * Use strtolower if mb_strtolower doesn't exist (i.e., php not compiled with --enable-mbstring)
  613. * This is not a functional replacement for mb_strtolower.
  614. *
  615. * @param string $input
  616. * @param string $charset
  617. */
  618. if(!function_exists('mb_strtolower')) {
  619. function mb_strtolower($input, $charset) {
  620. return strtolower($input);
  621. }
  622. }