Teknik is a suite of services with attractive and functional interfaces. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

upgrade.php 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  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. if(!file_exists($filename)) {
  125. return false;
  126. }
  127. return parse_ini_file($filename, $process_sections);
  128. }
  129. } else {
  130. // we can't redefine parse_ini_file() if it has been disabled
  131. function _parse_ini_file($filename, $process_sections = false)
  132. {
  133. if(!file_exists($filename)) {
  134. return false;
  135. }
  136. if(function_exists('file_get_contents')) {
  137. $ini = file_get_contents($filename);
  138. } else if(function_exists('file')) {
  139. if($ini = file($filename)) {
  140. $ini = implode("\n", $ini);
  141. }
  142. } else if(function_exists('fopen') && function_exists('fread')) {
  143. $handle = fopen($filename, 'r');
  144. if(!$handle) {
  145. return false;
  146. }
  147. $ini = fread($handle, filesize($filename));
  148. fclose($handle);
  149. } else {
  150. return false;
  151. }
  152. if($ini === false) {
  153. return false;
  154. }
  155. if(is_string($ini)) { $ini = explode("\n", str_replace("\r", "\n", $ini)); }
  156. if (count($ini) == 0) { return array(); }
  157. $sections = array();
  158. $values = array();
  159. $result = array();
  160. $globals = array();
  161. $i = 0;
  162. foreach ($ini as $line) {
  163. $line = trim($line);
  164. $line = str_replace("\t", " ", $line);
  165. // Comments
  166. if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}
  167. // Sections
  168. if ($line{0} == '[') {
  169. $tmp = explode(']', $line);
  170. $sections[] = trim(substr($tmp[0], 1));
  171. $i++;
  172. continue;
  173. }
  174. // Key-value pair
  175. list($key, $value) = explode('=', $line, 2);
  176. $key = trim($key);
  177. $value = trim($value);
  178. if (strstr($value, ";")) {
  179. $tmp = explode(';', $value);
  180. if (count($tmp) == 2) {
  181. if ((($value{0} != '"') && ($value{0} != "'")) ||
  182. preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
  183. preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
  184. $value = $tmp[0];
  185. }
  186. } else {
  187. if ($value{0} == '"') {
  188. $value = preg_replace('/^"(.*)".*/', '$1', $value);
  189. } elseif ($value{0} == "'") {
  190. $value = preg_replace("/^'(.*)'.*/", '$1', $value);
  191. } else {
  192. $value = $tmp[0];
  193. }
  194. }
  195. }
  196. $value = trim($value);
  197. $value = trim($value, "'\"");
  198. if ($i == 0) {
  199. if (substr($key, -2) == '[]') {
  200. $globals[substr($key, 0, -2)][] = $value;
  201. } else {
  202. $globals[$key] = $value;
  203. }
  204. } else {
  205. if (substr($key, -2) == '[]') {
  206. $values[$i-1][substr($key, 0, -2)][] = $value;
  207. } else {
  208. $values[$i-1][$key] = $value;
  209. }
  210. }
  211. }
  212. for ($j = 0; $j < $i; $j++) {
  213. if (isset($values[$j])) {
  214. if ($process_sections === true) {
  215. $result[$sections[$j]] = $values[$j];
  216. } else {
  217. $result[] = $values[$j];
  218. }
  219. } else {
  220. if ($process_sections === true) {
  221. $result[$sections[$j]] = array();
  222. }
  223. }
  224. }
  225. return $result + $globals;
  226. }
  227. }
  228. /**
  229. * glob() replacement.
  230. * Behaves like glob($pattern, $flags)
  231. *
  232. * @author BigueNique AT yahoo DOT ca
  233. * @author anthon (dot) pang (at) gmail (dot) com
  234. *
  235. * @param string $pattern
  236. * @param int $flags GLOBL_ONLYDIR, GLOB_MARK, GLOB_NOSORT (other flags not supported; defaults to 0)
  237. * @return array
  238. */
  239. if(function_exists('glob')) {
  240. // provide a wrapper
  241. function _glob($pattern, $flags = 0) {
  242. return glob($pattern, $flags);
  243. }
  244. } else if(function_exists('opendir') && function_exists('readdir')) {
  245. // we can't redefine glob() if it has been disabled
  246. function _glob($pattern, $flags = 0) {
  247. $path = dirname($pattern);
  248. $filePattern = basename($pattern);
  249. if(is_dir($path) && ($handle = opendir($path)) !== false) {
  250. $matches = array();
  251. while(($file = readdir($handle)) !== false) {
  252. if(($file[0] != '.')
  253. && fnmatch($filePattern, $file)
  254. && (!($flags & GLOB_ONLYDIR) || is_dir("$path/$file"))) {
  255. $matches[] = "$path/$file" . ($flags & GLOB_MARK ? '/' : '');
  256. }
  257. }
  258. closedir($handle);
  259. if(!($flags & GLOB_NOSORT)) {
  260. sort($matches);
  261. }
  262. return $matches;
  263. }
  264. return false;
  265. }
  266. } else {
  267. function _glob($pattern, $flags = 0) {
  268. return false;
  269. }
  270. }
  271. /**
  272. * Reads entire file into a string.
  273. * This function is not 100% compatible with the native function.
  274. *
  275. * @see http://php.net/file_get_contents
  276. * @since PHP 4.3.0
  277. *
  278. * @param string $filename Name of the file to read.
  279. * @return string The read data or false on failure.
  280. */
  281. if (!function_exists('file_get_contents'))
  282. {
  283. function file_get_contents($filename)
  284. {
  285. $fhandle = fopen($filename, "r");
  286. $fcontents = fread($fhandle, filesize($filename));
  287. fclose($fhandle);
  288. return $fcontents;
  289. }
  290. }
  291. /**
  292. * Safe serialize() and unserialize() replacements
  293. *
  294. * @license Public Domain
  295. *
  296. * @author anthon (dot) pang (at) gmail (dot) com
  297. */
  298. /*
  299. * Arbitrary limits for safe_unserialize()
  300. */
  301. define('MAX_SERIALIZED_INPUT_LENGTH', 4096);
  302. define('MAX_SERIALIZED_ARRAY_LENGTH', 256);
  303. define('MAX_SERIALIZED_ARRAY_DEPTH', 3);
  304. /**
  305. * Safe serialize() replacement
  306. * - output a strict subset of PHP's native serialized representation
  307. * - does not serialize objects
  308. *
  309. * @param mixed $value
  310. * @return string
  311. * @throw Exception if $value is malformed or contains unsupported types (e.g., resources, objects)
  312. */
  313. function _safe_serialize( $value )
  314. {
  315. if(is_null($value))
  316. {
  317. return 'N;';
  318. }
  319. if(is_bool($value))
  320. {
  321. return 'b:'.(int)$value.';';
  322. }
  323. if(is_int($value))
  324. {
  325. return 'i:'.$value.';';
  326. }
  327. if(is_float($value))
  328. {
  329. return 'd:'.$value.';';
  330. }
  331. if(is_string($value))
  332. {
  333. return 's:'.strlen($value).':"'.$value.'";';
  334. }
  335. if(is_array($value))
  336. {
  337. $out = '';
  338. foreach($value as $k => $v)
  339. {
  340. $out .= _safe_serialize($k) . _safe_serialize($v);
  341. }
  342. return 'a:'.count($value).':{'.$out.'}';
  343. }
  344. // safe_serialize cannot serialize resources or objects
  345. return false;
  346. }
  347. /**
  348. * Wrapper for _safe_serialize() that handles exceptions and multibyte encoding issue
  349. *
  350. * @param mixed $value
  351. * @return string
  352. */
  353. function safe_serialize( $value )
  354. {
  355. // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
  356. if (function_exists('mb_internal_encoding') &&
  357. (((int) ini_get('mbstring.func_overload')) & 2))
  358. {
  359. $mbIntEnc = mb_internal_encoding();
  360. mb_internal_encoding('ASCII');
  361. }
  362. $out = _safe_serialize($value);
  363. if (isset($mbIntEnc))
  364. {
  365. mb_internal_encoding($mbIntEnc);
  366. }
  367. return $out;
  368. }
  369. /**
  370. * Safe unserialize() replacement
  371. * - accepts a strict subset of PHP's native serialized representation
  372. * - does not unserialize objects
  373. *
  374. * @param string $str
  375. * @return mixed
  376. * @throw Exception if $str is malformed or contains unsupported types (e.g., resources, objects)
  377. */
  378. function _safe_unserialize($str)
  379. {
  380. if(strlen($str) > MAX_SERIALIZED_INPUT_LENGTH)
  381. {
  382. // input exceeds MAX_SERIALIZED_INPUT_LENGTH
  383. return false;
  384. }
  385. if(empty($str) || !is_string($str))
  386. {
  387. return false;
  388. }
  389. $stack = array();
  390. $expected = array();
  391. /*
  392. * states:
  393. * 0 - initial state, expecting a single value or array
  394. * 1 - terminal state
  395. * 2 - in array, expecting end of array or a key
  396. * 3 - in array, expecting value or another array
  397. */
  398. $state = 0;
  399. while($state != 1)
  400. {
  401. $type = isset($str[0]) ? $str[0] : '';
  402. if($type == '}')
  403. {
  404. $str = substr($str, 1);
  405. }
  406. else if($type == 'N' && $str[1] == ';')
  407. {
  408. $value = null;
  409. $str = substr($str, 2);
  410. }
  411. else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
  412. {
  413. $value = $matches[1] == '1' ? true : false;
  414. $str = substr($str, 4);
  415. }
  416. else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
  417. {
  418. $value = (int)$matches[1];
  419. $str = $matches[2];
  420. }
  421. else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
  422. {
  423. $value = (float)$matches[1];
  424. $str = $matches[3];
  425. }
  426. else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";')
  427. {
  428. $value = substr($matches[2], 0, (int)$matches[1]);
  429. $str = substr($matches[2], (int)$matches[1] + 2);
  430. }
  431. else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches) && $matches[1] < MAX_SERIALIZED_ARRAY_LENGTH)
  432. {
  433. $expectedLength = (int)$matches[1];
  434. $str = $matches[2];
  435. }
  436. else
  437. {
  438. // object or unknown/malformed type
  439. return false;
  440. }
  441. switch($state)
  442. {
  443. case 3: // in array, expecting value or another array
  444. if($type == 'a')
  445. {
  446. if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
  447. {
  448. // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
  449. return false;
  450. }
  451. $stack[] = &$list;
  452. $list[$key] = array();
  453. $list = &$list[$key];
  454. $expected[] = $expectedLength;
  455. $state = 2;
  456. break;
  457. }
  458. if($type != '}')
  459. {
  460. $list[$key] = $value;
  461. $state = 2;
  462. break;
  463. }
  464. // missing array value
  465. return false;
  466. case 2: // in array, expecting end of array or a key
  467. if($type == '}')
  468. {
  469. if(count($list) < end($expected))
  470. {
  471. // array size less than expected
  472. return false;
  473. }
  474. unset($list);
  475. $list = &$stack[count($stack)-1];
  476. array_pop($stack);
  477. // go to terminal state if we're at the end of the root array
  478. array_pop($expected);
  479. if(count($expected) == 0) {
  480. $state = 1;
  481. }
  482. break;
  483. }
  484. if($type == 'i' || $type == 's')
  485. {
  486. if(count($list) >= MAX_SERIALIZED_ARRAY_LENGTH)
  487. {
  488. // array size exceeds MAX_SERIALIZED_ARRAY_LENGTH
  489. return false;
  490. }
  491. if(count($list) >= end($expected))
  492. {
  493. // array size exceeds expected length
  494. return false;
  495. }
  496. $key = $value;
  497. $state = 3;
  498. break;
  499. }
  500. // illegal array index type
  501. return false;
  502. case 0: // expecting array or value
  503. if($type == 'a')
  504. {
  505. if(count($stack) >= MAX_SERIALIZED_ARRAY_DEPTH)
  506. {
  507. // array nesting exceeds MAX_SERIALIZED_ARRAY_DEPTH
  508. return false;
  509. }
  510. $data = array();
  511. $list = &$data;
  512. $expected[] = $expectedLength;
  513. $state = 2;
  514. break;
  515. }
  516. if($type != '}')
  517. {
  518. $data = $value;
  519. $state = 1;
  520. break;
  521. }
  522. // not in array
  523. return false;
  524. }
  525. }
  526. if(!empty($str))
  527. {
  528. // trailing data in input
  529. return false;
  530. }
  531. return $data;
  532. }
  533. /**
  534. * Wrapper for _safe_unserialize() that handles exceptions and multibyte encoding issue
  535. *
  536. * @param string $str
  537. * @return mixed
  538. */
  539. function safe_unserialize( $str )
  540. {
  541. // ensure we use the byte count for strings even when strlen() is overloaded by mb_strlen()
  542. if (function_exists('mb_internal_encoding') &&
  543. (((int) ini_get('mbstring.func_overload')) & 2))
  544. {
  545. $mbIntEnc = mb_internal_encoding();
  546. mb_internal_encoding('ASCII');
  547. }
  548. $out = _safe_unserialize($str);
  549. if (isset($mbIntEnc))
  550. {
  551. mb_internal_encoding($mbIntEnc);
  552. }
  553. return $out;
  554. }
  555. /**
  556. * readfile() replacement.
  557. * Behaves similar to readfile($filename);
  558. *
  559. * @author anthon (dot) pang (at) gmail (dot) com
  560. *
  561. * @param string $filename
  562. * @param bool $useIncludePath
  563. * @param resource $context
  564. * @return int the number of bytes read from the file, or false if an error occurs
  565. */
  566. function _readfile($filename, $byteStart, $byteEnd, $useIncludePath = false, $context = null)
  567. {
  568. $count = @filesize($filename);
  569. // built-in function has a 2 MB limit when using mmap
  570. if (function_exists('readfile')
  571. && $count <= (2 * 1024 * 1024)
  572. && $byteStart == 0
  573. && $byteEnd == $count
  574. ) {
  575. return @readfile($filename, $useIncludePath, $context);
  576. }
  577. // when in doubt (or when readfile() function is disabled)
  578. $handle = @fopen($filename, SettingsServer::isWindows() ? "rb" : "r");
  579. if ($handle) {
  580. fseek($handle, $byteStart);
  581. for ($pos = $byteStart; $pos < $byteEnd && !feof($handle); $pos = ftell($handle)) {
  582. echo fread($handle, min(8192, $byteEnd - $pos));
  583. ob_flush();
  584. flush();
  585. }
  586. fclose($handle);
  587. return $byteEnd - $byteStart;
  588. }
  589. return false;
  590. }
  591. /**
  592. * utf8_encode replacement
  593. *
  594. * @param string $data
  595. * @return string
  596. */
  597. if (!function_exists('utf8_encode')) {
  598. function utf8_encode($data) {
  599. if (function_exists('iconv')) {
  600. return @iconv('ISO-8859-1', 'UTF-8', $data);
  601. }
  602. return $data;
  603. }
  604. }
  605. /**
  606. * utf8_decode replacement
  607. *
  608. * @param string $data
  609. * @return string
  610. */
  611. if (!function_exists('utf8_decode')) {
  612. function utf8_decode($data) {
  613. if (function_exists('iconv')) {
  614. return @iconv('UTF-8', 'ISO-8859-1', $data);
  615. }
  616. return $data;
  617. }
  618. }
  619. /**
  620. * Use strtolower if mb_strtolower doesn't exist (i.e., php not compiled with --enable-mbstring)
  621. * This is not a functional replacement for mb_strtolower.
  622. *
  623. * @param string $input
  624. * @param string $charset
  625. */
  626. if(!function_exists('mb_strtolower')) {
  627. function mb_strtolower($input, $charset) {
  628. return strtolower($input);
  629. }
  630. }
  631. /**
  632. * On ubuntu in some cases, there is a bug that gzopen does not exist and one must use gzopen64 instead
  633. */
  634. if (!function_exists('gzopen')
  635. && function_exists('gzopen64')) {
  636. function gzopen($filename , $mode = 'r', $use_include_path = 0 )
  637. {
  638. return gzopen64($filename , $mode, $use_include_path);
  639. }
  640. }