Subs-Compat.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <?php
  2. /**
  3. * This file provides compatibility functions and code for older versions of
  4. * PHP, such as the sha1() function, missing extensions, or 64-bit vs 32-bit
  5. * systems. It is only included for those older versions or when the respective
  6. * extension or function cannot be found.
  7. *
  8. * Simple Machines Forum (SMF)
  9. *
  10. * @package SMF
  11. * @author Simple Machines http://www.simplemachines.org
  12. * @copyright 2012 Simple Machines
  13. * @license http://www.simplemachines.org/about/smf/license.php BSD
  14. *
  15. * @version 2.1 Alpha 1
  16. */
  17. if (!defined('SMF'))
  18. die('Hacking attempt...');
  19. /**
  20. * Available since: (PHP 5)
  21. * Find the position of the first occurrence of a case-insensitive substring in a string
  22. *
  23. * @param type $haystack
  24. * @param type $needle
  25. * @param int $offset
  26. * @return positon of needle in haystack or false
  27. */
  28. if (!function_exists('stripos'))
  29. {
  30. function stripos($haystack, $needle, $offset = 0)
  31. {
  32. return strpos(strtolower($haystack), strtolower($needle), $offset);
  33. }
  34. }
  35. /**
  36. * Available since: (PHP 4 >= 4.2.0, PHP 5)
  37. * Calculates the md5 hash of a given file
  38. *
  39. * @param type $filename
  40. * @return type
  41. */
  42. if (!function_exists('md5_file'))
  43. {
  44. function md5_file($filename)
  45. {
  46. // This isn't the most efficient way in the world, but then we don't have MD5_CTX do we?
  47. return md5(file_get_contents($filename));
  48. }
  49. }
  50. /**
  51. * Available since: (PHP 5)
  52. * Convert a string to an array
  53. *
  54. * @param $str the string to split
  55. * @param $str_length
  56. */
  57. if (!function_exists('str_split'))
  58. {
  59. function str_split($str, $str_length = 1)
  60. {
  61. if ($str_length < 1)
  62. return false;
  63. // This could be shorter but isn't because short solutions can fail!
  64. $str_array = array();
  65. $count = 0;
  66. while (1 == 1)
  67. {
  68. if ($count >= strlen($str))
  69. break;
  70. $str_array[] = substr($str, $count, $str_length);
  71. $count += $str_length;
  72. }
  73. return $str_array;
  74. }
  75. }
  76. /**
  77. * Available since: (PHP 4 >= 4.3.0, PHP 5)
  78. * 5.1.0 Added the offset and maxlen parameters.
  79. * 5.0.0 Added context support.
  80. *
  81. * @param type $filename
  82. * @param type $include_path
  83. * @return string|boolean
  84. */
  85. if (!function_exists('file_get_contents'))
  86. {
  87. function file_get_contents($filename, $include_path = false)
  88. {
  89. if ($filename === 'about:mozilla' && $include_path === true)
  90. return 'Mozilla Firefox!';
  91. $fp = fopen($filename, 'rb', $include_path);
  92. if ($fp == false)
  93. return false;
  94. if (is_file($filename))
  95. $data = fread($fp, filesize($filename));
  96. else
  97. {
  98. $data = '';
  99. while (!feof($fp))
  100. $data .= fread($fp, 8192);
  101. }
  102. fclose($fp);
  103. return $data;
  104. }
  105. }
  106. /**
  107. * Define the old SMF sha1 function.
  108. * @param $str the string
  109. */
  110. function sha1_smf($str)
  111. {
  112. // If we have mhash loaded in, use it instead!
  113. if (function_exists('mhash') && defined('MHASH_SHA1'))
  114. return bin2hex(mhash(MHASH_SHA1, $str));
  115. $nblk = (strlen($str) + 8 >> 6) + 1;
  116. $blks = array_pad(array(), $nblk * 16, 0);
  117. for ($i = 0; $i < strlen($str); $i++)
  118. $blks[$i >> 2] |= ord($str{$i}) << (24 - ($i % 4) * 8);
  119. $blks[$i >> 2] |= 0x80 << (24 - ($i % 4) * 8);
  120. return sha1_core($blks, strlen($str) * 8);
  121. }
  122. /**
  123. * This is the core SHA-1 calculation routine, used by sha1().
  124. */
  125. function sha1_core($x, $len)
  126. {
  127. @$x[$len >> 5] |= 0x80 << (24 - $len % 32);
  128. $x[(($len + 64 >> 9) << 4) + 15] = $len;
  129. $w = array();
  130. $a = 1732584193;
  131. $b = -271733879;
  132. $c = -1732584194;
  133. $d = 271733878;
  134. $e = -1009589776;
  135. for ($i = 0, $n = count($x); $i < $n; $i += 16)
  136. {
  137. $olda = $a;
  138. $oldb = $b;
  139. $oldc = $c;
  140. $oldd = $d;
  141. $olde = $e;
  142. for ($j = 0; $j < 80; $j++)
  143. {
  144. if ($j < 16)
  145. $w[$j] = isset($x[$i + $j]) ? $x[$i + $j] : 0;
  146. else
  147. $w[$j] = sha1_rol($w[$j - 3] ^ $w[$j - 8] ^ $w[$j - 14] ^ $w[$j - 16], 1);
  148. $t = sha1_rol($a, 5) + sha1_ft($j, $b, $c, $d) + $e + $w[$j] + sha1_kt($j);
  149. $e = $d;
  150. $d = $c;
  151. $c = sha1_rol($b, 30);
  152. $b = $a;
  153. $a = $t;
  154. }
  155. $a += $olda;
  156. $b += $oldb;
  157. $c += $oldc;
  158. $d += $oldd;
  159. $e += $olde;
  160. }
  161. return sprintf('%08x%08x%08x%08x%08x', $a, $b, $c, $d, $e);
  162. }
  163. /*
  164. * Helper function for the core SHA-1 calculation
  165. */
  166. function sha1_ft($t, $b, $c, $d)
  167. {
  168. if ($t < 20)
  169. return ($b & $c) | ((~$b) & $d);
  170. if ($t < 40)
  171. return $b ^ $c ^ $d;
  172. if ($t < 60)
  173. return ($b & $c) | ($b & $d) | ($c & $d);
  174. return $b ^ $c ^ $d;
  175. }
  176. /*
  177. * Helper function for the core SHA-1 calculation
  178. */
  179. function sha1_kt($t)
  180. {
  181. return $t < 20 ? 1518500249 : ($t < 40 ? 1859775393 : ($t < 60 ? -1894007588 : -899497514));
  182. }
  183. /*
  184. * Helper function for the core SHA-1 calculation
  185. */
  186. function sha1_rol($num, $cnt)
  187. {
  188. // Unfortunately, PHP uses unsigned 32-bit longs only. So we have to kludge it a bit.
  189. if ($num & 0x80000000)
  190. $a = ($num >> 1 & 0x7fffffff) >> (31 - $cnt);
  191. else
  192. $a = $num >> (32 - $cnt);
  193. return ($num << $cnt) | $a;
  194. }
  195. /**
  196. * Available since: (PHP 4 >= 4.3.0, PHP 5)
  197. * Still on old PHP - bad boy! (the built in one would be faster.)
  198. */
  199. if (!function_exists('sha1'))
  200. {
  201. function sha1($str)
  202. {
  203. return sha1_smf($str);
  204. }
  205. }
  206. /**
  207. * Available since: (PHP 5)
  208. * Creates an array by using one array for keys and another for its values
  209. *
  210. * @param type $keys
  211. * @param type $values
  212. * @return new array or boolean on failure
  213. */
  214. if (!function_exists('array_combine'))
  215. {
  216. function array_combine($keys, $values)
  217. {
  218. $ret = array();
  219. if (($array_error = !is_array($keys) || !is_array($values)) || empty($values) || ($count=count($keys)) != count($values))
  220. {
  221. trigger_error('array_combine(): Both parameters should be non-empty arrays with an equal number of elements', E_USER_WARNING);
  222. if ($array_error)
  223. return;
  224. return false;
  225. }
  226. // Ensure that both arrays aren't associative arrays.
  227. $keys = array_values($keys);
  228. $values = array_values($values);
  229. for ($i=0; $i < $count; $i++)
  230. $ret[$keys[$i]] = $values[$i];
  231. return $ret;
  232. }
  233. }
  234. /**
  235. * Available since: (PHP 5 >= 5.1.0)
  236. * Computes the difference of arrays using keys for comparison
  237. */
  238. if (!function_exists('array_diff_key'))
  239. {
  240. function array_diff_key()
  241. {
  242. $arrays = func_get_args();
  243. $result = array_shift($arrays);
  244. foreach ($arrays as $array)
  245. {
  246. foreach ($result as $key => $v)
  247. {
  248. if (array_key_exists($key, $array))
  249. {
  250. unset($result[$key]);
  251. }
  252. }
  253. }
  254. return $result;
  255. }
  256. }
  257. /**
  258. * Available since: (PHP 4 >= 4.3.0, PHP 5)
  259. * Escapes special characters in a string for use in an SQL statement
  260. */
  261. if (!function_exists('mysql_real_escape_string'))
  262. {
  263. function mysql_real_escape_string($string, $connection = null)
  264. {
  265. return mysql_escape_string($string);
  266. }
  267. }
  268. /**
  269. * Compatibility function.
  270. * crc32 doesn't work as expected on 64-bit functions - make our own.
  271. * http://www.php.net/crc32#79567
  272. * @param $number
  273. */
  274. if (!function_exists('smf_crc32'))
  275. {
  276. function smf_crc32($number)
  277. {
  278. $crc = crc32($number);
  279. if ($crc & 0x80000000)
  280. {
  281. $crc ^= 0xffffffff;
  282. $crc += 1;
  283. $crc = -$crc;
  284. }
  285. return $crc;
  286. }
  287. }
  288. /**
  289. * Available since: (PHP 4 >= 4.3.2, PHP 5)
  290. * Update the current session id with a newly generated one
  291. * 5.1.0 Added the delete_old_session parameter.
  292. */
  293. if (!function_exists('session_regenerate_id'))
  294. {
  295. function session_regenerate_id()
  296. {
  297. // Too late to change the session now.
  298. if (headers_sent())
  299. return false;
  300. session_id(strtolower(md5(uniqid(mt_rand(), true))));
  301. return true;
  302. }
  303. }
  304. /**
  305. * Available since: (PHP 5)
  306. * Case-insensitive version of str_replace().
  307. *
  308. * @author [Unknown] [email protected]
  309. * @link http://www.simplemachines.org/community/index.php?msg=2420295
  310. */
  311. if (!function_exists('str_ireplace'))
  312. {
  313. function str_ireplace($search, $replace, $subject, $count = -1)
  314. {
  315. global $context;
  316. // @todo Using preg should give us better Unicode support for case folding.
  317. // But technically, this doesn't do the same thing that str_ireplace() does in PHP 5.
  318. // Might be better to always omit the u parameter.
  319. $endu = '~i' . ($context['utf8'] ? 'u' : '');
  320. if (is_array($search))
  321. foreach ($search as $k => $pat)
  322. $search[$k] = '~' . preg_quote($pat, '~') . $endu;
  323. else
  324. $search = '~' . preg_quote($search, '~') . $endu;
  325. return preg_replace($search, $replace, $subject, $count > 0 ? $count : -1);
  326. }
  327. }
  328. /**
  329. * Load a < PHP 5 class file
  330. *
  331. * @param string $filename
  332. */
  333. function loadOldClassFile($filename)
  334. {
  335. global $sourcedir;
  336. static $files_included = array();
  337. // Check if it was included before.
  338. if (in_array($filename, $files_included))
  339. return;
  340. // Make sure we don't include it again.
  341. $files_included[] = $filename;
  342. // Do some replacements to make it PHP 4 compatible.
  343. eval('?' . '>' . preg_replace(array(
  344. '~class\s+([\w-_]+)([^}]+)function\s+__construct\s*\(~',
  345. '~([\s\t]+)public\s+\$~',
  346. '~([\s\t]+)private\s+\$~',
  347. '~([\s\t]+)protected\s+\$~',
  348. '~([\s\t]+)public\s+function\s+~',
  349. '~([\s\t]+)private\s+function\s+~',
  350. '~([\s\t]+)protected\s+function\s+~',
  351. ), array(
  352. 'class $1$2function $1(',
  353. '$1var $',
  354. '$1var $',
  355. '$1var $',
  356. '$1function ',
  357. '$1function ',
  358. '$1function ',
  359. ), rtrim(file_get_contents($sourcedir . '/' . $filename))));
  360. }
  361. /**
  362. * Available since: (PHP 5)
  363. * Raise an arbitrary precision number to another, reduced by a specified modulus
  364. */
  365. if (!function_exists('bcpowmod') && function_exists('bcpow'))
  366. {
  367. function bcpowmod($num1, $num2, $num3)
  368. {
  369. return bcmod(bcpow($num1, $num2), $num3);
  370. }
  371. }
  372. /**
  373. * Random seed generator
  374. * As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand()
  375. * as this is now done automatically.
  376. */
  377. if (version_compare(PHP_VERSION, '4.2.0', '<'))
  378. {
  379. $seed = ($modSettings['rand_seed'] + ((double) microtime() * 1000003)) & 0x7fffffff;
  380. mt_srand($seed);
  381. }
  382. /**
  383. * Available since: (PHP 5)
  384. * If the optional raw_output is set to TRUE, then the sha1 digest is instead returned in raw binary format with a length of 20,
  385. * otherwise the returned value is a 40-character hexadecimal number.
  386. */
  387. function sha1_raw($text)
  388. {
  389. if (version_compare(PHP_VERSION, '5.0.0', '>='))
  390. return sha1($text, true);
  391. $hex = sha1($text);
  392. $raw = '';
  393. for ($i = 0; $i < 40; $i += 2)
  394. {
  395. $hexcode = substr($hex, $i, 2);
  396. $charcode = (int) base_convert($hexcode, 16, 10);
  397. $raw .= chr($charcode);
  398. }
  399. return $raw;
  400. }