PageRenderTime 73ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 2ms

/includes/functions.php

http://github.com/MightyGorgon/icy_phoenix
PHP | 6703 lines | 5117 code | 716 blank | 870 comment | 877 complexity | 47d2b88399eefdc07ffa8394687c33bf MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. *
  4. * @package Icy Phoenix
  5. * @version $Id$
  6. * @copyright (c) 2008 Icy Phoenix
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10. /**
  11. *
  12. * @Icy Phoenix is based on phpBB
  13. * @copyright (c) 2008 phpBB Group
  14. *
  15. */
  16. if (!defined('IN_ICYPHOENIX'))
  17. {
  18. die('Hacking attempt');
  19. }
  20. if (!defined('STRIP'))
  21. {
  22. // If we are on PHP >= 6.0.0 we do not need some code
  23. if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
  24. {
  25. define('STRIP', false);
  26. }
  27. else
  28. {
  29. define('STRIP', (@get_magic_quotes_gpc()) ? true : false);
  30. }
  31. }
  32. /*
  33. * Append $SID to a url. Borrowed from phplib and modified. This is an extra routine utilised by the session code and acts as a wrapper around every single URL and form action.
  34. * If you replace the session code you must include this routine, even if it's empty.
  35. */
  36. function append_sid($url, $non_html_amp = false, $char_conversion = false, $params = false, $session_id = false)
  37. {
  38. global $SID, $_SID, $_EXTRA_URL, $phpbb_hook;
  39. $_SID = (empty($_SID) && !empty($SID) || (!empty($SID) && ($SID != ('sid=' . $_SID)))) ? str_replace('sid=', '', $SID) : $_SID;
  40. $is_amp = empty($non_html_amp) ? true : false;
  41. $amp_delim = !empty($is_amp) ? '&amp;' : '&';
  42. $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
  43. if (empty($params))
  44. {
  45. $amp_delim = (!empty($char_conversion) ? '%26' : $amp_delim);
  46. $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
  47. if (!empty($SID) && !preg_match('#sid=#', $url))
  48. {
  49. $url .= $url_delim . $SID;
  50. }
  51. return $url;
  52. }
  53. // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately.
  54. // They could mimick most of what is within this function
  55. if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
  56. {
  57. if ($phpbb_hook->hook_return(__FUNCTION__))
  58. {
  59. return $phpbb_hook->hook_return_result(__FUNCTION__);
  60. }
  61. }
  62. $params_is_array = is_array($params);
  63. // Get anchor
  64. $anchor = '';
  65. if (strpos($url, '#') !== false)
  66. {
  67. list($url, $anchor) = explode('#', $url, 2);
  68. $anchor = '#' . $anchor;
  69. }
  70. elseif (!$params_is_array && strpos($params, '#') !== false)
  71. {
  72. list($params, $anchor) = explode('#', $params, 2);
  73. $anchor = '#' . $anchor;
  74. }
  75. // Handle really simple cases quickly
  76. if (($_SID == '') && ($session_id === false) && empty($_EXTRA_URL) && !$params_is_array && !$anchor)
  77. {
  78. if ($params === false)
  79. {
  80. return $url;
  81. }
  82. return $url . (($params !== false) ? $url_delim . $params : '');
  83. }
  84. // Assign sid if session id is not specified
  85. if ($session_id === false)
  86. {
  87. $session_id = $_SID;
  88. }
  89. // Appending custom url parameter?
  90. $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
  91. // Use the short variant if possible ;)
  92. if ($params === false)
  93. {
  94. // Append session id
  95. if (!$session_id)
  96. {
  97. return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor;
  98. }
  99. else
  100. {
  101. return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor;
  102. }
  103. }
  104. // Build string if parameters are specified as array
  105. if (is_array($params))
  106. {
  107. $output = array();
  108. foreach ($params as $key => $item)
  109. {
  110. if ($item === NULL)
  111. {
  112. continue;
  113. }
  114. if ($key == '#')
  115. {
  116. $anchor = '#' . $item;
  117. continue;
  118. }
  119. $output[] = $key . '=' . $item;
  120. }
  121. $params = implode($amp_delim, $output);
  122. }
  123. // Append session id and parameters (even if they are empty)
  124. // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
  125. return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor;
  126. }
  127. /**
  128. * Re-Apply session id after page reloads
  129. */
  130. function reapply_sid($url)
  131. {
  132. // Remove previously added sid
  133. if (strpos($url, 'sid=') !== false)
  134. {
  135. $phpEx = PHP_EXT;
  136. // All kind of links
  137. $url = preg_replace('/(\?)?(&amp;|&)?sid=[a-z0-9]+/', '', $url);
  138. // if the sid was the first param, make the old second as first ones
  139. $url = preg_replace("/$phpEx(&amp;|&)+?/", "$phpEx?", $url);
  140. }
  141. return append_sid($url);
  142. }
  143. /**
  144. * Build an URL with params
  145. */
  146. function ip_build_url($url, $params = false, $html_amp = false)
  147. {
  148. $amp_delim = !empty($html_amp) ? '&amp;' : '&';
  149. $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
  150. if (!empty($params) && is_array($params))
  151. {
  152. foreach ($params as $param)
  153. {
  154. $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
  155. if (!empty($param))
  156. {
  157. $url .= $url_delim . $param;
  158. }
  159. }
  160. }
  161. return $url;
  162. }
  163. /*
  164. * extract_current_page
  165. * function backported from phpBB3 - Olympus
  166. * @param string $root_path current root path (IP_ROOT_PATH)
  167. */
  168. function extract_current_page($root_path)
  169. {
  170. $page_array = array();
  171. // First of all, get the request uri...
  172. $script_name = (!empty($_SERVER['SCRIPT_NAME'])) ? $_SERVER['SCRIPT_NAME'] : getenv('SCRIPT_NAME');
  173. $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING'));
  174. // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support...
  175. if (!$script_name)
  176. {
  177. $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI');
  178. $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name;
  179. $page_array['failover'] = 1;
  180. }
  181. // Replace backslashes and doubled slashes (could happen on some proxy setups)
  182. $script_name = str_replace(array('\\', '//'), '/', $script_name);
  183. // Now, remove the sid and let us get a clean query string...
  184. $use_args = array();
  185. // Since some browser do not encode correctly we need to do this with some "special" characters...
  186. // " -> %22, ' => %27, < -> %3C, > -> %3E
  187. $find = array('"', "'", '<', '>');
  188. $replace = array('%22', '%27', '%3C', '%3E');
  189. foreach ($args as $key => $argument)
  190. {
  191. if (strpos($argument, 'sid=') === 0)
  192. {
  193. continue;
  194. }
  195. $use_args[] = str_replace($find, $replace, $argument);
  196. }
  197. unset($args);
  198. // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2
  199. // The current query string
  200. $query_string = trim(implode('&', $use_args));
  201. // basenamed page name (for example: index.php)
  202. $page_name = (substr($script_name, -1, 1) == '/') ? '' : basename($script_name);
  203. $page_name = urlencode(htmlspecialchars($page_name));
  204. // current directory within the phpBB root (for example: adm)
  205. $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
  206. $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
  207. $intersection = array_intersect_assoc($root_dirs, $page_dirs);
  208. $root_dirs = array_diff_assoc($root_dirs, $intersection);
  209. $page_dirs = array_diff_assoc($page_dirs, $intersection);
  210. $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
  211. if ($page_dir && substr($page_dir, -1, 1) == '/')
  212. {
  213. $page_dir = substr($page_dir, 0, -1);
  214. }
  215. $page_full = $page_name . (($query_string) ? '?' . $query_string : '');
  216. // Current page from Icy Phoenix root (for example: adm/index.php?i=10&b=2)
  217. $page = (($page_dir) ? $page_dir . '/' : '') . $page_full;
  218. // The script path from the webroot to the current directory (for example: /ip/adm/) : always prefixed with / and ends in /
  219. $script_path = trim(str_replace('\\', '/', dirname($script_name)));
  220. // The script path from the webroot to the Icy Phoenix root (for example: /ip/)
  221. $script_dirs = explode('/', $script_path);
  222. array_splice($script_dirs, -sizeof($page_dirs));
  223. $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : '');
  224. // We are on the base level (Icy Phoenix root == webroot), lets adjust the variables a bit...
  225. if (!$root_script_path)
  226. {
  227. $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path;
  228. }
  229. $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
  230. $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';
  231. $post_forum_url = (defined('POST_FORUM_URL') ? POST_FORUM_URL : 'f');
  232. $post_topic_url = (defined('POST_TOPIC_URL') ? POST_TOPIC_URL : 't');
  233. $page_array += array(
  234. 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)),
  235. 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)),
  236. 'page_dir' => $page_dir,
  237. 'page_name' => $page_name,
  238. 'page' => $page,
  239. 'query_string' => $query_string,
  240. 'forum' => (isset($_REQUEST[$post_forum_url]) && $_REQUEST[$post_forum_url] > 0) ? (int) $_REQUEST[$post_forum_url] : 0,
  241. 'topic' => (isset($_REQUEST[$post_topic_url]) && $_REQUEST[$post_topic_url] > 0) ? (int) $_REQUEST[$post_topic_url] : 0,
  242. 'page_full' => $page_full,
  243. );
  244. return $page_array;
  245. }
  246. /**
  247. * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present.
  248. * function backported from phpBB3 - Olympus
  249. */
  250. function extract_current_hostname()
  251. {
  252. global $config;
  253. // Get hostname
  254. $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'));
  255. // Should be a lowercase string
  256. $host = (string) strtolower($host);
  257. // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid
  258. if ((isset($config['cookie_domain']) && ($host === $config['cookie_domain'])) || (isset($config['server_name']) && ($host === $config['server_name'])))
  259. {
  260. return $host;
  261. }
  262. // Is the host actually a IP? If so, we use the IP... (IPv4)
  263. if (long2ip(ip2long($host)) === $host)
  264. {
  265. return $host;
  266. }
  267. // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned
  268. $host = @parse_url('http://' . $host);
  269. $host = (!empty($host['host'])) ? $host['host'] : '';
  270. // Remove any portions not removed by parse_url (#)
  271. $host = str_replace('#', '', $host);
  272. // If, by any means, the host is now empty, we will use a "best approach" way to guess one
  273. if (empty($host))
  274. {
  275. if (!empty($config['server_name']))
  276. {
  277. $host = $config['server_name'];
  278. }
  279. elseif (!empty($config['cookie_domain']))
  280. {
  281. $host = (strpos($config['cookie_domain'], '.') === 0) ? substr($config['cookie_domain'], 1) : $config['cookie_domain'];
  282. }
  283. else
  284. {
  285. // Set to OS hostname or localhost
  286. $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost';
  287. }
  288. }
  289. // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set)
  290. return $host;
  291. }
  292. /**
  293. * Set variable, used by {@link request_var the request_var function}
  294. * function backported from phpBB3 - Olympus
  295. * @access private
  296. */
  297. function set_var(&$result, $var, $type, $multibyte = false)
  298. {
  299. settype($var, $type);
  300. $result = $var;
  301. if ($type == 'string')
  302. {
  303. // normalize UTF-8 data
  304. if ($multibyte)
  305. {
  306. $result = utf8_normalize_nfc($result);
  307. }
  308. $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result), ENT_COMPAT, 'UTF-8'));
  309. if (!empty($result))
  310. {
  311. // Make sure multibyte characters are wellformed
  312. if ($multibyte)
  313. {
  314. if (!preg_match('/^./u', $result))
  315. {
  316. $result = '';
  317. }
  318. }
  319. else
  320. {
  321. // no multibyte, allow only ASCII (0-127)
  322. $result = preg_replace('/[\x80-\xFF]/', '?', $result);
  323. }
  324. }
  325. $result = (STRIP) ? stripslashes($result) : $result;
  326. }
  327. }
  328. /**
  329. * Get passed variable
  330. * function backported from phpBB3 - Olympus
  331. */
  332. function request_var($var_name, $default, $multibyte = false, $cookie = false)
  333. {
  334. if (!$cookie && isset($_COOKIE[$var_name]))
  335. {
  336. if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
  337. {
  338. return (is_array($default)) ? array() : $default;
  339. }
  340. $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
  341. }
  342. $super_global = ($cookie) ? '_COOKIE' : '_REQUEST';
  343. if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default))
  344. {
  345. return (is_array($default)) ? array() : $default;
  346. }
  347. $var = $GLOBALS[$super_global][$var_name];
  348. if (!is_array($default))
  349. {
  350. $type = gettype($default);
  351. }
  352. else
  353. {
  354. list($key_type, $type) = each($default);
  355. $type = gettype($type);
  356. $key_type = gettype($key_type);
  357. if ($type == 'array')
  358. {
  359. reset($default);
  360. $default = current($default);
  361. list($sub_key_type, $sub_type) = each($default);
  362. $sub_type = gettype($sub_type);
  363. $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type;
  364. $sub_key_type = gettype($sub_key_type);
  365. }
  366. }
  367. if (is_array($var))
  368. {
  369. $_var = $var;
  370. $var = array();
  371. foreach ($_var as $k => $v)
  372. {
  373. set_var($k, $k, $key_type);
  374. if (($type == 'array') && is_array($v))
  375. {
  376. foreach ($v as $_k => $_v)
  377. {
  378. if (is_array($_v))
  379. {
  380. $_v = null;
  381. }
  382. set_var($_k, $_k, $sub_key_type, $multibyte);
  383. set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
  384. }
  385. }
  386. else
  387. {
  388. if (($type == 'array') || is_array($v))
  389. {
  390. $v = null;
  391. }
  392. set_var($var[$k], $v, $type, $multibyte);
  393. }
  394. }
  395. }
  396. else
  397. {
  398. set_var($var, $var, $type, $multibyte);
  399. }
  400. return $var;
  401. }
  402. /**
  403. * Request the var value but returns only true of false, useful for forms validations
  404. */
  405. function request_boolean_var($var_name, $default, $multibyte = false, $post_only = false)
  406. {
  407. if ($post_only)
  408. {
  409. $return = request_post_var($var_name, $default, $multibyte);
  410. }
  411. else
  412. {
  413. $return = request_var($var_name, $default, $multibyte);
  414. }
  415. $return = !empty($return) ? true : false;
  416. return $return;
  417. }
  418. /**
  419. * Gets only POST vars
  420. */
  421. function request_post_var($var_name, $default, $multibyte = false)
  422. {
  423. $return = $default;
  424. if (isset($_POST[$var_name]))
  425. {
  426. $return = request_var($var_name, $default, $multibyte);
  427. }
  428. return $return;
  429. }
  430. /**
  431. * Get only GET vars
  432. */
  433. function request_get_var($var_name, $default, $multibyte = false)
  434. {
  435. $return = $default;
  436. if (isset($_GET[$var_name]))
  437. {
  438. $temp_post_var = isset($_POST[$var_name]) ? $_POST[$var_name] : '';
  439. $_POST[$var_name] = $_GET[$var_name];
  440. $return = request_var($var_name, $default, $multibyte);
  441. $_POST[$var_name] = $temp_post_var;
  442. }
  443. return $return;
  444. }
  445. /**
  446. * Check GET POST vars exists
  447. */
  448. function check_http_var_exists($var_name, $empty_var = false)
  449. {
  450. if ($empty_var)
  451. {
  452. if (isset($_GET[$var_name]) || isset($_POST[$var_name]))
  453. {
  454. return true;
  455. }
  456. else
  457. {
  458. return false;
  459. }
  460. }
  461. else
  462. {
  463. if (!empty($_GET[$var_name]) || !empty($_POST[$var_name]))
  464. {
  465. return true;
  466. }
  467. else
  468. {
  469. return false;
  470. }
  471. }
  472. return false;
  473. }
  474. /**
  475. * Check variable value against default array
  476. */
  477. function check_var_value($var, $var_array, $var_default = false)
  478. {
  479. if (!is_array($var_array) || empty($var_array))
  480. {
  481. return $var;
  482. }
  483. $var_default = (($var_default === false) ? $var_array[0] : $var_default);
  484. $var = in_array($var, $var_array) ? $var : $var_default;
  485. return $var;
  486. }
  487. /**
  488. * Function to add slashes to vars array, may be used to globally escape HTTP vars if needed
  489. */
  490. function slash_data(&$data)
  491. {
  492. if (is_array($data))
  493. {
  494. foreach ($data as $k => $v)
  495. {
  496. $data[$k] = (is_array($v)) ? slash_data($v) : addslashes($v);
  497. }
  498. }
  499. return $data;
  500. }
  501. /**
  502. * Set config value. Creates missing config entry.
  503. */
  504. function set_config($config_name, $config_value, $clear_cache = true, $return = false)
  505. {
  506. global $db, $cache, $config;
  507. $sql = "UPDATE " . CONFIG_TABLE . "
  508. SET config_value = '" . $db->sql_escape($config_value) . "'
  509. WHERE config_name = '" . $db->sql_escape($config_name) . "'";
  510. $db->sql_return_on_error($return);
  511. $db->sql_query($sql);
  512. $db->sql_return_on_error(false);
  513. if (!$db->sql_affectedrows() && !isset($config[$config_name]))
  514. {
  515. $sql = "INSERT INTO " . CONFIG_TABLE . " (`config_name`, `config_value`)
  516. VALUES ('" . $db->sql_escape($config_name) . "', '" . $db->sql_escape($config_value) . "')";
  517. $db->sql_return_on_error($return);
  518. $db->sql_query($sql);
  519. $db->sql_return_on_error(false);
  520. }
  521. $config[$config_name] = $config_value;
  522. if ($clear_cache)
  523. {
  524. $cache->destroy('config');
  525. //$db->clear_cache('config_');
  526. }
  527. }
  528. /**
  529. * Get config values
  530. */
  531. function get_config($from_cache = true)
  532. {
  533. global $db;
  534. $config = array();
  535. $from_cache = ($from_cache && (CACHE_CFG == true) && !defined('IN_ADMIN') && !defined('IN_CMS')) ? true : false;
  536. $sql = "SELECT * FROM " . CONFIG_TABLE;
  537. $result = $from_cache ? $db->sql_query($sql, 0, 'config_') : $db->sql_query($sql);
  538. while ($row = $db->sql_fetchrow($result))
  539. {
  540. $config[$row['config_name']] = stripslashes($row['config_value']);
  541. }
  542. $db->sql_freeresult($result);
  543. return $config;
  544. }
  545. /**
  546. * Get layouts config values
  547. */
  548. function get_layouts_config($from_cache = true)
  549. {
  550. global $db;
  551. $cms_config_layouts = array();
  552. $from_cache = $from_cache ? true : false;
  553. $sql = "SELECT lsid, page_id, filename, global_blocks, page_nav, view FROM " . CMS_LAYOUT_SPECIAL_TABLE . " ORDER BY page_id";
  554. $result = $from_cache ? $db->sql_query($sql, 0, 'cms_config_', CMS_CACHE_FOLDER) : $db->sql_query($sql);
  555. while ($row = $db->sql_fetchrow($result))
  556. {
  557. $cms_config_layouts[$row['page_id']] = $row;
  558. }
  559. $db->sql_freeresult($result);
  560. return $cms_config_layouts;
  561. }
  562. /**
  563. * Get CMS config values
  564. */
  565. function get_cms_config($from_cache = true)
  566. {
  567. global $db;
  568. $cms_config_vars = array();
  569. $from_cache = $from_cache ? true : false;
  570. $sql = "SELECT bid, config_name, config_value FROM " . CMS_CONFIG_TABLE;
  571. $result = $from_cache ? $db->sql_query($sql, 0, 'cms_config_', CMS_CACHE_FOLDER) : $db->sql_query($sql);
  572. while ($row = $db->sql_fetchrow($result))
  573. {
  574. if ($row['bid'] > 0)
  575. {
  576. $cms_config_vars[$row['config_name']][$row['bid']] = $row['config_value'];
  577. }
  578. else
  579. {
  580. $cms_config_vars[$row['config_name']] = $row['config_value'];
  581. }
  582. }
  583. $db->sql_freeresult($result);
  584. return $cms_config_vars;
  585. }
  586. if (!function_exists('htmlspecialchars_decode'))
  587. {
  588. /**
  589. * A wrapper for htmlspecialchars_decode
  590. */
  591. function htmlspecialchars_decode($string, $quote_style = ENT_NOQUOTES)
  592. {
  593. return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
  594. }
  595. }
  596. /**
  597. * html_entity_decode replacement (from php manual)
  598. */
  599. if (!function_exists('html_entity_decode'))
  600. {
  601. function html_entity_decode($given_html, $quote_style = ENT_QUOTES)
  602. {
  603. $trans_table = array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style));
  604. $trans_table['&#39;'] = "'";
  605. return (strtr($given_html, $trans_table));
  606. }
  607. }
  608. /**
  609. * HTML Special Chars markup cleaning
  610. */
  611. function htmlspecialchars_clean($string, $quote_style = ENT_NOQUOTES)
  612. {
  613. // Old version, to be verified why &amp; gets converted twice...
  614. //return trim(str_replace(array('& ', '<', '%3C', '>', '%3E'), array('&amp; ', '&lt;', '&lt;', '&gt;', '&gt;'), htmlspecialchars_decode($string, $quote_style)));
  615. return trim(str_replace(array('& ', '<', '%3C', '>', '%3E', '{IP_EAMP_ESCAPE}'), array('&amp; ', '&lt;', '&lt;', '&gt;', '&gt;', '&amp;'), htmlspecialchars_decode(str_replace('&amp;', '{IP_EAMP_ESCAPE}', $string), $quote_style)));
  616. }
  617. /**
  618. * Add slashes only if needed
  619. */
  620. function ip_addslashes($string)
  621. {
  622. return (STRIP ? addslashes($string) : $string);
  623. }
  624. /**
  625. * Strip slashes only if needed
  626. */
  627. function ip_stripslashes($string)
  628. {
  629. return (STRIP ? stripslashes($string) : $string);
  630. }
  631. /**
  632. * Escape single quotes for MySQL
  633. */
  634. function ip_mysql_escape($string)
  635. {
  636. return $db->sql_escape($string);
  637. }
  638. /**
  639. * Icy Phoenix UTF8 Conditional Decode
  640. */
  641. function ip_utf8_decode($string)
  642. {
  643. global $lang;
  644. $string = ($lang['ENCODING'] == 'utf8') ? $string : utf8_decode($string);
  645. return $string;
  646. }
  647. /**
  648. * Get option bitfield from custom data
  649. *
  650. * @param int $bitThe bit/value to get
  651. * @param int $data Current bitfield to check
  652. * @return bool Returns true if value of constant is set in bitfield, else false
  653. */
  654. function phpbb_optionget($bit, $data)
  655. {
  656. return ($data & 1 << (int) $bit) ? true : false;
  657. }
  658. /**
  659. * Set option bitfield
  660. *
  661. * @param int $bit The bit/value to set/unset
  662. * @param bool $set True if option should be set, false if option should be unset.
  663. * @param int $data Current bitfield to change
  664. * @return int The new bitfield
  665. */
  666. function phpbb_optionset($bit, $set, $data)
  667. {
  668. if ($set && !($data & 1 << $bit))
  669. {
  670. $data += 1 << $bit;
  671. }
  672. elseif (!$set && ($data & 1 << $bit))
  673. {
  674. $data -= 1 << $bit;
  675. }
  676. return $data;
  677. }
  678. /*
  679. * Get user data, $target_user can be username or user_id.
  680. * If force_str is true, the username will be forced.
  681. */
  682. function get_userdata($target_user, $force_str = false)
  683. {
  684. global $db;
  685. $target_user = (!is_numeric($target_user) || $force_str) ? phpbb_clean_username($target_user) : intval($target_user);
  686. $sql = "SELECT *
  687. FROM " . USERS_TABLE . "
  688. WHERE ";
  689. $sql .= (is_integer($target_user) ? ("user_id = " . (int) $target_user) : ("username_clean = '" . $db->sql_escape(utf8_clean_string($target_user)) . "'")) . " AND user_id <> " . ANONYMOUS;
  690. $result = $db->sql_query($sql);
  691. if ($db->sql_affectedrows() == 0)
  692. {
  693. //message_die(GENERAL_ERROR, 'User does not exist.');
  694. return false;
  695. }
  696. if ($row = $db->sql_fetchrow($result))
  697. {
  698. if (isset($row['user_level']) && ($row['user_level'] == JUNIOR_ADMIN))
  699. {
  700. $row['user_level'] = (!defined('IN_ADMIN') && !defined('IN_CMS')) ? ADMIN : MOD;
  701. }
  702. return $row;
  703. }
  704. else
  705. {
  706. return false;
  707. }
  708. }
  709. /*
  710. * Generate an SQL to get users based on a search string
  711. */
  712. function get_users_sql($username, $sql_like = false, $all_data = false, $data_escape = true, $clean_username = false)
  713. {
  714. global $config, $cache, $db;
  715. $username = (!empty($clean_username) ? phpbb_clean_username($username) : $username);
  716. $sql = "SELECT " . (!empty($all_data) ? "*" : ("user_id, username, username_clean, user_active, user_color, user_level")) . " FROM " . USERS_TABLE . "
  717. WHERE username_clean " . (!empty($sql_like) ? (" LIKE ") : (" = ")) . "'" . (!empty($data_escape) ? $db->sql_escape(utf8_clean_string($username)) : $username) . "'" . (!empty($sql_like) ? "" : (" LIMIT 1"));
  718. return $sql;
  719. }
  720. /*
  721. * Get founder id
  722. */
  723. function get_founder_id($clear_cache = false)
  724. {
  725. global $db, $config;
  726. if ($clear_cache)
  727. {
  728. $db->clear_cache('founder_id_');
  729. }
  730. $founder_id = (intval($config['main_admin_id']) >= 2) ? (int) $config['main_admin_id'] : 2;
  731. if ($founder_id != 2)
  732. {
  733. $sql = "SELECT user_id
  734. FROM " . USERS_TABLE . "
  735. WHERE user_id = '" . $founder_id . "'
  736. LIMIT 1";
  737. $result = $db->sql_query($sql, 0, 'founder_id_');
  738. $founder_id = 2;
  739. while ($row = $db->sql_fetchrow($result))
  740. {
  741. $founder_id = $row['user_id'];
  742. }
  743. $db->sql_freeresult($result);
  744. }
  745. return $founder_id;
  746. }
  747. /*
  748. * Get groups data
  749. */
  750. function get_groups_data($full_data = false, $sort_by_name = false, $sql_groups = array())
  751. {
  752. global $db, $cache, $config;
  753. $groups_data = array();
  754. $sql_select = !empty($full_data) ? '*' : 'g.group_id, g.group_name, g.group_color, g.group_legend, g.group_legend_order';
  755. $sql_where = '';
  756. if (!empty($sql_groups))
  757. {
  758. if (!is_array($sql_groups))
  759. {
  760. $sql_groups = array($sql_groups);
  761. }
  762. $sql_where = !empty($sql_groups) ? (' AND ' . $db->sql_in_set('g.group_id', $sql_groups)) : '';
  763. }
  764. $sql_sort = !empty($sort_by_name) ? ' ORDER BY g.group_name ASC' : ' ORDER BY g.group_legend DESC, g.group_legend_order ASC, g.group_name ASC';
  765. $sql = "SELECT " . $sql_select . "
  766. FROM " . GROUPS_TABLE . " g
  767. WHERE g.group_single_user = 0" .
  768. $sql_where .
  769. $sql_sort;
  770. $result = $db->sql_query($sql, 0, 'groups_', USERS_CACHE_FOLDER);
  771. $groups_data = $db->sql_fetchrowset($result);
  772. $db->sql_freeresult($result);
  773. return $groups_data;
  774. }
  775. /*
  776. * Get groups data for a specific user
  777. */
  778. function get_groups_data_user($user_id, $full_data = false, $sort_by_name = false, $sql_groups = array())
  779. {
  780. global $db, $cache, $config;
  781. $groups_data = array();
  782. $sql_select = !empty($full_data) ? 'g.*, ug.*' : 'g.group_id, g.group_name, g.group_color, g.group_legend, g.group_legend_order, ug.user_pending';
  783. $sql_where = '';
  784. if (!empty($sql_groups))
  785. {
  786. if (!is_array($sql_groups))
  787. {
  788. $sql_groups = array($sql_groups);
  789. }
  790. $sql_where = !empty($sql_groups) ? (' AND ' . $db->sql_in_set('g.group_id', $sql_groups)) : '';
  791. }
  792. $sql = "SELECT " . $sql_select . "
  793. FROM " . GROUPS_TABLE . " g, " . USER_GROUP_TABLE . " ug " . "
  794. WHERE g.group_single_user = 0" .
  795. $sql_where . "
  796. AND g.group_id = ug.group_id
  797. AND ug.user_id = " . (int) $user_id;
  798. $result = $db->sql_query($sql, 0, 'groups_', USERS_CACHE_FOLDER);
  799. $groups_data = $db->sql_fetchrowset($result);
  800. $db->sql_freeresult($result);
  801. return $groups_data;
  802. }
  803. /*
  804. * Founder protection
  805. */
  806. function founder_protect($founder_id)
  807. {
  808. global $db;
  809. // Activate Main Admin Account
  810. $sql = "UPDATE " . USERS_TABLE . "
  811. SET user_active = 1
  812. WHERE user_id = " . $founder_id;
  813. $result = $db->sql_query($sql);
  814. // Delete Main Admin Ban
  815. $sql = "DELETE FROM " . BANLIST_TABLE . "
  816. WHERE ban_userid = " . $founder_id;
  817. $result = $db->sql_query($sql);
  818. $db->clear_cache('ban_', USERS_CACHE_FOLDER);
  819. return true;
  820. }
  821. /**
  822. * Generates an alphanumeric random string of given length
  823. */
  824. function gen_rand_string($num_chars = 8)
  825. {
  826. $rand_str = unique_id();
  827. $rand_str = str_replace('0', 'Z', strtoupper(base_convert($rand_str, 16, 35)));
  828. return substr($rand_str, 0, $num_chars);
  829. }
  830. /**
  831. * Return unique id
  832. * @param string $extra additional entropy
  833. */
  834. function unique_id($extra = 'c')
  835. {
  836. static $dss_seeded = false;
  837. global $config, $cache;
  838. $val = $config['rand_seed'] . microtime();
  839. $val = md5($val);
  840. $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
  841. if(($dss_seeded !== true) && ($config['rand_seed_last_update'] < (time() - rand(1, 10))))
  842. {
  843. // Maybe we can avoid emptying cache every random seed generation...
  844. set_config('rand_seed', $config['rand_seed'], false);
  845. set_config('rand_seed_last_update', time(), false);
  846. $dss_seeded = true;
  847. }
  848. return substr($val, 4, 16);
  849. }
  850. // Modified by MG
  851. /**
  852. * Return formatted string for filesizes
  853. *
  854. * @param int $value filesize in bytes
  855. * @param bool $string_only true if language string should be returned
  856. * @param array $allowed_units only allow these units (data array indexes)
  857. *
  858. * @return mixed data array if $string_only is false
  859. * @author bantu
  860. */
  861. function get_formatted_filesize($value, $string_only = true, $allowed_units = false)
  862. {
  863. global $lang;
  864. $available_units = array(
  865. 'gb' => array(
  866. 'min' => 1073741824, // pow(2, 30)
  867. 'index' => 3,
  868. 'si_unit' => 'GB',
  869. 'iec_unit' => 'GIB',
  870. 'precision' => 2
  871. ),
  872. 'mb' => array(
  873. 'min' => 1048576, // pow(2, 20)
  874. 'index' => 2,
  875. 'si_unit' => 'MB',
  876. 'iec_unit' => 'MIB',
  877. 'precision' => 2
  878. ),
  879. 'kb' => array(
  880. 'min' => 1024, // pow(2, 10)
  881. 'index' => 1,
  882. 'si_unit' => 'KB',
  883. 'iec_unit' => 'KIB',
  884. 'precision' => 0
  885. ),
  886. 'b' => array(
  887. 'min' => 0,
  888. 'index' => 0,
  889. 'si_unit' => 'BYTES', // Language index
  890. 'iec_unit' => 'BYTES', // Language index
  891. 'precision' => 0
  892. ),
  893. );
  894. foreach ($available_units as $si_identifier => $unit_info)
  895. {
  896. if (!empty($allowed_units) && ($si_identifier != 'b') && !in_array($si_identifier, $allowed_units))
  897. {
  898. continue;
  899. }
  900. if ($value >= $unit_info['min'])
  901. {
  902. $unit_info['si_identifier'] = $si_identifier;
  903. break;
  904. }
  905. }
  906. unset($available_units);
  907. for ($i = 0; $i < $unit_info['index']; $i++)
  908. {
  909. $value /= 1024;
  910. }
  911. $value = round($value, $unit_info['precision']);
  912. // Lookup units in language dictionary
  913. $unit_info['si_unit'] = (isset($lang[$unit_info['si_unit']])) ? $lang[$unit_info['si_unit']] : $unit_info['si_unit'];
  914. $unit_info['iec_unit'] = (isset($lang[$unit_info['iec_unit']])) ? $lang[$unit_info['iec_unit']] : $unit_info['iec_unit'];
  915. // Default to SI
  916. $unit_info['unit'] = $unit_info['si_unit'];
  917. if (!$string_only)
  918. {
  919. $unit_info['value'] = $value;
  920. return $unit_info;
  921. }
  922. return $value . $unit_info['unit'];
  923. }
  924. /**
  925. *
  926. * @version Version 0.1 / slightly modified for phpBB 3.0.x (using $H$ as hash type identifier)
  927. *
  928. * Portable PHP password hashing framework.
  929. *
  930. * Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
  931. * the public domain.
  932. *
  933. * There's absolutely no warranty.
  934. *
  935. * The homepage URL for this framework is:
  936. *
  937. * http://www.openwall.com/phpass/
  938. *
  939. * Please be sure to update the Version line if you edit this file in any way.
  940. * It is suggested that you leave the main version number intact, but indicate
  941. * your project name (after the slash) and add your own revision information.
  942. *
  943. * Please do not change the "private" password hashing method implemented in
  944. * here, thereby making your hashes incompatible. However, if you must, please
  945. * change the hash type identifier (the "$P$") to something different.
  946. *
  947. * Obviously, since this code is in the public domain, the above are not
  948. * requirements (there can be none), but merely suggestions.
  949. *
  950. *
  951. * Hash the password
  952. */
  953. function phpbb_hash($password)
  954. {
  955. $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  956. $random_state = unique_id();
  957. $random = '';
  958. $count = 6;
  959. if (($fh = @fopen('/dev/urandom', 'rb')))
  960. {
  961. $random = fread($fh, $count);
  962. fclose($fh);
  963. }
  964. if (strlen($random) < $count)
  965. {
  966. $random = '';
  967. for ($i = 0; $i < $count; $i += 16)
  968. {
  969. $random_state = md5(unique_id() . $random_state);
  970. $random .= pack('H*', md5($random_state));
  971. }
  972. $random = substr($random, 0, $count);
  973. }
  974. $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
  975. if (strlen($hash) == 34)
  976. {
  977. return $hash;
  978. }
  979. return md5($password);
  980. }
  981. /**
  982. * Check for correct password
  983. *
  984. * @param string $password The password in plain text
  985. * @param string $hash The stored password hash
  986. *
  987. * @return bool Returns true if the password is correct, false if not.
  988. */
  989. function phpbb_check_hash($password, $hash)
  990. {
  991. if (strlen($hash) == 34)
  992. {
  993. $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  994. return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
  995. }
  996. return (md5($password) === $hash) ? true : false;
  997. }
  998. /**
  999. * Generate salt for hash generation
  1000. */
  1001. function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6)
  1002. {
  1003. if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31)
  1004. {
  1005. $iteration_count_log2 = 8;
  1006. }
  1007. $output = '$H$';
  1008. $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)];
  1009. $output .= _hash_encode64($input, 6, $itoa64);
  1010. return $output;
  1011. }
  1012. /**
  1013. * Encode hash
  1014. */
  1015. function _hash_encode64($input, $count, &$itoa64)
  1016. {
  1017. $output = '';
  1018. $i = 0;
  1019. do
  1020. {
  1021. $value = ord($input[$i++]);
  1022. $output .= $itoa64[$value & 0x3f];
  1023. if ($i < $count)
  1024. {
  1025. $value |= ord($input[$i]) << 8;
  1026. }
  1027. $output .= $itoa64[($value >> 6) & 0x3f];
  1028. if ($i++ >= $count)
  1029. {
  1030. break;
  1031. }
  1032. if ($i < $count)
  1033. {
  1034. $value |= ord($input[$i]) << 16;
  1035. }
  1036. $output .= $itoa64[($value >> 12) & 0x3f];
  1037. if ($i++ >= $count)
  1038. {
  1039. break;
  1040. }
  1041. $output .= $itoa64[($value >> 18) & 0x3f];
  1042. }
  1043. while ($i < $count);
  1044. return $output;
  1045. }
  1046. /**
  1047. * The crypt function/replacement
  1048. */
  1049. function _hash_crypt_private($password, $setting, &$itoa64)
  1050. {
  1051. $output = '*';
  1052. // Check for correct hash
  1053. if (substr($setting, 0, 3) != '$H$')
  1054. {
  1055. return $output;
  1056. }
  1057. $count_log2 = strpos($itoa64, $setting[3]);
  1058. if ($count_log2 < 7 || $count_log2 > 30)
  1059. {
  1060. return $output;
  1061. }
  1062. $count = 1 << $count_log2;
  1063. $salt = substr($setting, 4, 8);
  1064. if (strlen($salt) != 8)
  1065. {
  1066. return $output;
  1067. }
  1068. /**
  1069. * We're kind of forced to use MD5 here since it's the only
  1070. * cryptographic primitive available in all versions of PHP
  1071. * currently in use. To implement our own low-level crypto
  1072. * in PHP would result in much worse performance and
  1073. * consequently in lower iteration counts and hashes that are
  1074. * quicker to crack (by non-PHP code).
  1075. */
  1076. if (PHP_VERSION >= 5)
  1077. {
  1078. $hash = md5($salt . $password, true);
  1079. do
  1080. {
  1081. $hash = md5($hash . $password, true);
  1082. }
  1083. while (--$count);
  1084. }
  1085. else
  1086. {
  1087. $hash = pack('H*', md5($salt . $password));
  1088. do
  1089. {
  1090. $hash = pack('H*', md5($hash . $password));
  1091. }
  1092. while (--$count);
  1093. }
  1094. $output = substr($setting, 0, 12);
  1095. $output .= _hash_encode64($hash, 16, $itoa64);
  1096. return $output;
  1097. }
  1098. /**
  1099. * Hashes an email address to a big integer
  1100. *
  1101. * @param string $email Email address
  1102. * @return string Big Integer
  1103. */
  1104. function phpbb_email_hash($email)
  1105. {
  1106. return sprintf('%u', crc32(strtolower($email))) . strlen($email);
  1107. }
  1108. //Form validation
  1109. /**
  1110. * Add a secret hash for use in links/GET requests
  1111. * @param string $link_name The name of the link; has to match the name used in check_link_hash, otherwise no restrictions apply
  1112. * @return string the hash
  1113. */
  1114. function generate_link_hash($link_name)
  1115. {
  1116. global $user;
  1117. if (!isset($user->data["hash_$link_name"]))
  1118. {
  1119. $user->data["hash_$link_name"] = substr(sha1($user->data['user_form_salt'] . $link_name), 0, 8);
  1120. }
  1121. return $user->data["hash_$link_name"];
  1122. }
  1123. /**
  1124. * checks a link hash - for GET requests
  1125. * @param string $token the submitted token
  1126. * @param string $link_name The name of the link
  1127. * @return boolean true if all is fine
  1128. */
  1129. function check_link_hash($token, $link_name)
  1130. {
  1131. return $token === generate_link_hash($link_name);
  1132. }
  1133. /**
  1134. * Add a secret token to the form (requires the S_FORM_TOKEN template variable)
  1135. * @param string $form_name The name of the form; has to match the name used in check_form_key, otherwise no restrictions apply
  1136. */
  1137. function add_form_key($form_name)
  1138. {
  1139. global $config, $template, $user;
  1140. $now = time();
  1141. $token_sid = (($user->data['user_id'] == ANONYMOUS) && !empty($config['form_token_sid_guests'])) ? $user->data['session_id'] : '';
  1142. $token = sha1($now . $user->data['user_form_salt'] . $form_name . $token_sid);
  1143. $s_fields = build_hidden_fields(array(
  1144. 'creation_time' => $now,
  1145. 'form_token' => $token,
  1146. )
  1147. );
  1148. $template->assign_vars(array(
  1149. 'S_FORM_TOKEN' => $s_fields,
  1150. )
  1151. );
  1152. }
  1153. /**
  1154. * Check the form key. Required for all altering actions not secured by confirm_box
  1155. * @param string $form_name The name of the form; has to match the name used in add_form_key, otherwise no restrictions apply
  1156. * @param int $timespan The maximum acceptable age for a submitted form in seconds. Defaults to the config setting.
  1157. * @param string $return_page The address for the return link
  1158. * @param bool $trigger If true, the function will triger an error when encountering an invalid form
  1159. */
  1160. function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false)
  1161. {
  1162. global $config, $user, $lang;
  1163. if ($timespan === false)
  1164. {
  1165. // we enforce a minimum value of half a minute here.
  1166. $timespan = ($config['form_token_lifetime'] == -1) ? -1 : max(30, $config['form_token_lifetime']);
  1167. }
  1168. if (isset($_POST['creation_time']) && isset($_POST['form_token']))
  1169. {
  1170. $creation_time = abs(request_var('creation_time', 0));
  1171. $token = request_var('form_token', '');
  1172. $diff = time() - $creation_time;
  1173. // If creation_time and the time() now is zero we can assume it was not a human doing this (the check for if ($diff)...
  1174. if ($diff && (($diff <= $timespan) || ($timespan === -1)))
  1175. {
  1176. $token_sid = (($user->data['user_id'] == ANONYMOUS) && !empty($config['form_token_sid_guests'])) ? $user->data['session_id'] : '';
  1177. $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid);
  1178. if ($key === $token)
  1179. {
  1180. return true;
  1181. }
  1182. }
  1183. }
  1184. if ($trigger)
  1185. {
  1186. trigger_error($lang['FORM_INVALID'] . $return_page);
  1187. }
  1188. return false;
  1189. }
  1190. // added at phpBB 2.0.11 to properly format the username
  1191. function phpbb_clean_username($username)
  1192. {
  1193. $username = substr(htmlspecialchars(trim($username)), 0, 36);
  1194. $username = rtrim($username, "\\");
  1195. return $username;
  1196. }
  1197. /*
  1198. * Function to clear all unwanted chars in username
  1199. */
  1200. function ip_clean_username($username)
  1201. {
  1202. $username = preg_replace('/[^A-Za-z0-9\-_. ]+/', '', trim($username));
  1203. return $username;
  1204. }
  1205. /*
  1206. * Create email signature
  1207. */
  1208. function create_signature($signature = '')
  1209. {
  1210. global $config;
  1211. $signature = !empty($signature) ? $signature : $config['board_email_sig'];
  1212. $email_sig = (!empty($signature) ? str_replace('<br />', "\n", $config['sig_line'] . " \n" . $signature) : '');
  1213. if (!empty($config['html_email']))
  1214. {
  1215. $email_sig = nl2br($email_sig);
  1216. }
  1217. return $email_sig;
  1218. }
  1219. /*
  1220. * Clean string
  1221. */
  1222. function ip_clean_string($text, $charset = false, $extra_chars = false, $is_filename = false)
  1223. {
  1224. $charset = empty($charset) ? 'utf-8' : $charset;
  1225. // Function needed to convert some of the German characters into Latin correspondent characters
  1226. $text = utf_ger_to_latin($text, false);
  1227. // Function needed to convert some of the Cyrillic characters into Latin correspondent characters
  1228. $text = utf_cyr_to_latin($text, false);
  1229. // Remove all HTML tags and convert to lowercase
  1230. $text = strtolower(strip_tags($text));
  1231. // Convert &
  1232. $text = str_replace(array('&amp;', '&nbsp;', '&quot;'), array('&', ' ', ''), $text);
  1233. // Decode all HTML entities
  1234. $text = html_entity_decode($text, ENT_COMPAT, $charset);
  1235. // Some common chars replacements... are we sure we want to replace "&"???
  1236. $find = array('&', '@', '©', '®', '€', '$', '£');
  1237. $repl = array('and', 'at', 'copyright', 'rights', 'euro', 'dollar', 'pound');
  1238. $text = str_replace($find, $repl, $text);
  1239. // Attempt to convert all HTML numeric entities.
  1240. if (preg_match('@\&\#\d+;@s', $text))
  1241. {
  1242. $text = preg_replace('~&#([0-9]+);~e', 'chr("\\1")', $text);
  1243. }
  1244. // Convert back all HTML entities into their aliases
  1245. // Mighty Gorgon: added a workaround for some special case... :-(
  1246. $text_tmp = $text;
  1247. $text = @htmlentities($text, ENT_COMPAT, $charset);
  1248. if (!empty($text_tmp) && empty($text))
  1249. {
  1250. $text = htmlentities($text_tmp);
  1251. }
  1252. // Replace some known HTML entities
  1253. $find = array(
  1254. '&#268;', '&#269;', // c
  1255. '&#356;', '&#357;', // t
  1256. '&#270;', '&#271;', // d
  1257. '&#317;', '&#318;', // L, l
  1258. '&#327;', '&#328;', // N, n
  1259. '&#381;', '&#382;', 'Ž', 'ž', // z
  1260. '&#223;', '&#946;', 'ß', // ß
  1261. 'œ', '&#338;', '&#339;', // OE, oe
  1262. '&#198;', '&#230;', // AE, ae
  1263. 'š', 'Š', // 'š','Š'
  1264. '&#273;', '&#272;', // ?', '?', // 'dj','dj'
  1265. '`', '‘', '’',
  1266. );
  1267. $repl = array(
  1268. 'c', 'c',
  1269. 't', 't',
  1270. 'd', 'd',
  1271. 'l', 'l',
  1272. 'n', 'n',
  1273. 'z', 'z', 'z', 'z',
  1274. 'ss', 'ss', 'ss',
  1275. 'oe', 'oe', 'oe',
  1276. 'ae', 'ae',
  1277. 's', 's',
  1278. 'dj', 'dj',
  1279. '-', '-', '-',
  1280. );
  1281. $text = str_replace($find, $repl, $text);
  1282. // Convert localized special chars
  1283. $text = preg_replace('/&([a-z][ez]?)(?:acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig);/','$1', $text);
  1284. // Convert all remaining special chars
  1285. $text = preg_replace('/&([a-z]+);/', '$1', $text);
  1286. // If still some unrecognized HTML entities are there... kill them!!!
  1287. $text = preg_replace('@\&\#\d+;@s', '', $text);
  1288. // Replace all illegal chars with '-'
  1289. if ($extra_chars || $is_filename)
  1290. {
  1291. // if $extra_chars is true then we will allow spaces, underscores and dots
  1292. $text = preg_replace('![^a-z0-9\-._ ]!s', '-', $text);
  1293. if ($is_filename)
  1294. {
  1295. $text = str_replace(' ', '_', $text);
  1296. }
  1297. }
  1298. else
  1299. {
  1300. $text = preg_replace('![^a-z0-9\-]!s', '-', $text);
  1301. // Convert every white space char with "-"
  1302. $text = preg_replace('!\s+!s', '-', $text);
  1303. }
  1304. // Replace multiple "-"
  1305. $text = preg_replace('!-+!s', '-', $text);
  1306. // Replace multiple "_"
  1307. $text = preg_replace('!_+!s', '_', $text);
  1308. // Remove leading / trailing "-"/"_"...
  1309. $text = preg_replace('!^[-_]|[-_]$!s', '', $text);
  1310. if ($is_filename)
  1311. {
  1312. // Remove any trailing dot at the end, to avoid messing up Windows naming system...
  1313. $text = rtrim($text, '.');
  1314. }
  1315. return $text;
  1316. }
  1317. /**
  1318. * German to Latin chars conversion
  1319. */
  1320. function utf_ger_to_latin($string, $reverse = false)
  1321. {
  1322. $ger = array(
  1323. '&#223;', '&#946;', 'ß', // ß
  1324. '&#196;', '&#228;', 'Ä', 'ä', // Ä, ä
  1325. '&#214;', '&#246;', 'Ö', 'ö', // Ö, ö
  1326. '&#220;', '&#252;', 'Ü', 'ü', // Ü, ü
  1327. );
  1328. $lat = array(
  1329. 'ss', 'ss', 'ss',
  1330. 'ae', 'ae', 'ae', 'ae',
  1331. 'oe', 'oe', 'oe', 'oe',
  1332. 'ue', 'ue', 'ue', 'ue',
  1333. );
  1334. $string = !empty($reverse) ? str_replace($lat, $ger, $string) : str_replace($ger, $lat, $string);
  1335. return $string;
  1336. }
  1337. /**
  1338. * Cyrillic to Latin chars conversion
  1339. */
  1340. function utf_cyr_to_latin($string, $reverse = false)
  1341. {
  1342. $cyr = array(
  1343. 'а', 'б', 'в', 'г', 'д',
  1344. 'e', 'ж', 'з', 'и', 'й',
  1345. 'к', 'л', 'м', 'н', 'о',
  1346. 'п', 'р', 'с', 'т', 'у',
  1347. 'ф', 'х', 'ц', 'ч', 'ш',
  1348. 'щ', 'ъ', 'ь', 'ю', 'я',
  1349. 'А', 'Б', 'В', 'Г', 'Д',
  1350. 'Е', 'Ж', 'З', 'И', 'Й',
  1351. 'К', 'Л', 'М', 'Н', 'О',
  1352. 'П', 'Р', 'С', 'Т', 'У',
  1353. 'Ф', 'Х', 'Ц', 'Ч', 'Ш',
  1354. 'Щ', 'Ъ', 'Ь', 'Ю', 'Я'
  1355. );
  1356. $lat = array(
  1357. 'a', 'b', 'v', 'g', 'd',
  1358. 'e', 'zh', 'z', 'i', 'y',
  1359. 'k', 'l', 'm', 'n', 'o',
  1360. 'p', 'r', 's', 't', 'u',
  1361. 'f', 'h', 'ts', 'ch', 'sh',
  1362. 'sht', 'a', 'y', 'yu', 'ya',
  1363. 'A', 'B', 'V', 'G', 'D',
  1364. 'E', 'Zh', 'Z', 'I', 'Y',
  1365. 'K', 'L', 'M', 'N', 'O',
  1366. 'P', 'R', 'S', 'T', 'U',
  1367. 'F', 'H', 'Ts', 'Ch', 'Sh',
  1368. 'Sht', 'A', 'Y', 'Yu', 'Ya'
  1369. );
  1370. $string = !empty($reverse) ? str_replace($lat, $cyr, $string) : str_replace($cyr, $lat, $string);
  1371. return $string;
  1372. }
  1373. /**
  1374. * Generate back link
  1375. */
  1376. function page_back_link($u_action)
  1377. {
  1378. global $lang;
  1379. return '<br /><br /><a href="' . $u_action . '">&laquo; ' . $lang['BACK_TO_PREV'] . '</a>';
  1380. }
  1381. /**
  1382. * Build Confirm box
  1383. * @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box
  1384. * @param string $title Title/Message used for confirm box.
  1385. * message text is _CONFIRM appended to title.
  1386. * If title cannot be found in user->lang a default one is displayed
  1387. * If title_CONFIRM cannot be found in user->lang the text given is used.
  1388. * @param string $hidden Hidden variables
  1389. * @param string $html_body Template used for confirm box
  1390. * @param string $u_action Custom form action
  1391. */
  1392. function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.tpl', $u_action = '')
  1393. {
  1394. global $db, $user, $lang, $template;
  1395. if (isset($_POST['cancel']))
  1396. {
  1397. return false;
  1398. }
  1399. $confirm = false;
  1400. if (isset($_POST['confirm']))
  1401. {
  1402. // language frontier
  1403. if ($_POST['confirm'] === $lang['YES'])
  1404. {
  1405. $confirm = true;
  1406. }
  1407. }
  1408. if ($check && $confirm)
  1409. {
  1410. $user_id = request_var('confirm_uid', 0);
  1411. $session_id = request_var('sess', '');
  1412. if (($user_id != $user->data['user_id']) || ($session_id != $user->session_id))
  1413. {
  1414. return false;
  1415. }
  1416. return true;
  1417. }
  1418. elseif ($check)
  1419. {
  1420. return false;
  1421. }
  1422. $s_hidden_fields = build_hidden_fields(array(
  1423. 'confirm_uid' => $user->data['user_id'],
  1424. 'sess' => $user->session_id,
  1425. 'sid' => $user->session_id,
  1426. )
  1427. );
  1428. // re-add sid / transform & to &amp; for user->page (user->page is always using &)
  1429. $use_page = ($u_action) ? IP_ROOT_PATH . $u_action : IP_ROOT_PATH . str_replace('&', '&amp;', $user->page['page']);
  1430. $u_action = reapply_sid($use_page);
  1431. $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&amp;');
  1432. $confirm_title = (!isset($lang[$title])) ? $lang['Confirm'] : $lang[$title];
  1433. $template->assign_vars(array(
  1434. 'MESSAGE_TITLE' => $confirm_title,
  1435. 'MESSAGE_TEXT' => (!isset($lang[$title . '_CONFIRM'])) ? $title : $lang[$title . '_CONFIRM'],
  1436. 'YES_VALUE' => $lang['YES'],
  1437. 'S_CONFIRM_ACTION' => $u_action,
  1438. 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields
  1439. )
  1440. );
  1441. full_page_generation($html_body, $confirm_title, '', '');
  1442. }
  1443. /*
  1444. * jumpbox() : replace the original phpBB make_jumpbox()
  1445. */
  1446. function jumpbox($action, $match_forum_id = 0)
  1447. {
  1448. global $db, $template, $user, $lang;
  1449. // build the jumpbox
  1450. $boxstring = '<select name="selected_id" onchange="if(this.options[this.selectedIndex].value != -1){ forms[\'jumpbox\'].submit() }">';
  1451. $boxstring .= get_tree_option(POST_FORUM_URL . $match_forum_id);
  1452. $boxstring .= '</select>';
  1453. $boxstring .= '<input type="hidden" name="sid" value="' . $user->data['session_id'] . '" />';
  1454. // dump this to template
  1455. $template->set_filenames(array('jumpbox' => 'jumpbox.tpl'));
  1456. $template->assign_vars(array(
  1457. 'L_GO' => $lang['Go'],
  1458. 'L_JUMP_TO' => $lang['Jump_to'],
  1459. 'L_SELECT_FORUM' => $lang['Select_forum'],
  1460. 'S_JUMPBOX_SELECT' => $boxstring,
  1461. 'S_JUMPBOX_ACTION' => append_sid($action)
  1462. )
  1463. );
  1464. $template->assign_var_from_handle('JUMPBOX', 'jumpbox');
  1465. return;
  1466. }
  1467. /*
  1468. * Creates forum jumpbox
  1469. */
  1470. function make_jumpbox($action, $match_forum_id = 0)
  1471. {
  1472. return jumpbox($action, $match_forum_id);
  1473. }
  1474. /**
  1475. * Checks if a path ($path) is absolute or relative
  1476. *
  1477. * @param string $path Path to check absoluteness of
  1478. * @return boolean
  1479. */
  1480. function is_absolute($path)
  1481. {
  1482. return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false;
  1483. }
  1484. /**
  1485. * @author Chris Smith <chris@project-minerva.org>
  1486. * @copyright 2006 Project Minerva Team
  1487. * @param string $path The path which we should attempt to resolve.
  1488. * @return mixed
  1489. */
  1490. function phpbb_own_realpath($path)
  1491. {
  1492. // Now to perform funky shizzle
  1493. // Switch to use UNIX slashes
  1494. $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
  1495. $path_prefix = '';
  1496. // Determine what sort of path we have
  1497. if (is_absolute($path))
  1498. {
  1499. $absolute = true;
  1500. if ($path[0] == '/')
  1501. {
  1502. // Absolute path, *NIX style
  1503. $path_prefix = '';
  1504. }
  1505. else
  1506. {
  1507. // Absolute path, Windows style
  1508. // Remove the drive letter and colon
  1509. $path_prefix = $path[0] . ':';
  1510. $path = substr($path, 2);
  1511. }
  1512. }
  1513. else
  1514. {
  1515. // Relative Path
  1516. // Prepend the current working directory
  1517. if (function_exists('getcwd'))
  1518. {
  1519. // This is the best method, hopefully it is enabled!
  1520. $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
  1521. $absolute = true;
  1522. if (preg_match('#^[a-z]:#i', $path))
  1523. {
  1524. $path_prefix = $path[0] . ':';
  1525. $path = substr($path, 2);
  1526. }
  1527. else
  1528. {
  1529. $path_prefix = '';
  1530. }
  1531. }
  1532. elseif (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
  1533. {
  1534. // Warning: If chdir() has been used this will lie!
  1535. // Warning: This has some problems sometime (CLI can create them easily)
  1536. $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
  1537. $absolute = true;
  1538. $path_prefix = '';
  1539. }
  1540. else
  1541. {
  1542. // We have no way of getting the absolute path, just run on using relative ones.
  1543. $absolute = false;
  1544. $path_prefix = '.';
  1545. }
  1546. }
  1547. // Remove any repeated slashes
  1548. $path = preg_replace('#/{2,}#', '/', $path);
  1549. // Remove the slashes from the start and end of the path
  1550. $path = trim($path, '/');
  1551. // Break the string into little bits for us to nibble on
  1552. $bits = explode('/', $path);
  1553. // Remove any . in the path, renumber array for the loop below
  1554. $bits = array_values(array_diff($bits, array('.')));
  1555. // Lets get looping, run over and resolve any .. (up directory)
  1556. for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
  1557. {
  1558. // @todo Optimise
  1559. if ($bits[$i] == '..')
  1560. {
  1561. if (isset($bits[$i - 1]))
  1562. {
  1563. if ($bits[$i - 1] != '..')
  1564. {
  1565. // We found a .. and we are able to traverse upwards, lets do it!
  1566. unset($bits[$i]);
  1567. unset($bits[$i - 1]);
  1568. $i -= 2;
  1569. $max -= 2;
  1570. $bits = array_values($bits);
  1571. }
  1572. }
  1573. else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
  1574. {
  1575. // We have an absolute path trying to descend above the root of the filesystem
  1576. // ... Error!
  1577. return false;
  1578. }
  1579. }
  1580. }
  1581. // Prepend the path prefix
  1582. array_unshift($bits, $path_prefix);
  1583. $resolved = '';
  1584. $max = sizeof($bits) - 1;
  1585. // Check if we are able to resolve symlinks, Windows cannot.
  1586. $symlink_resolve = (function_exists('readlink')) ? true : false;
  1587. foreach ($bits as $i => $bit)
  1588. {
  1589. if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
  1590. {
  1591. // Path Exists
  1592. if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
  1593. {
  1594. // Resolved a symlink.
  1595. $resolved = $link . (($i == $max) ? '' : '/');
  1596. continue;
  1597. }
  1598. }
  1599. else
  1600. {
  1601. // Something doesn't exist here!
  1602. // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
  1603. // return false;
  1604. }
  1605. $resolved .= $bit . (($i == $max) ? '' : '/');
  1606. }
  1607. // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
  1608. // because we must be inside that basedir, the question is where...
  1609. // @internal The slash in is_dir() gets around an open_basedir restriction
  1610. if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
  1611. {
  1612. return false;
  1613. }
  1614. // Put the slashes back to the native operating systems slashes
  1615. $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
  1616. // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
  1617. if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
  1618. {
  1619. return substr($resolved, 0, -1);
  1620. }
  1621. return $resolved; // We got here, in the end!
  1622. }
  1623. /**
  1624. * A wrapper for realpath
  1625. * @ignore
  1626. */
  1627. function phpbb_realpath($path)
  1628. {
  1629. if (!function_exists('realpath'))
  1630. {
  1631. return phpbb_own_realpath($path);
  1632. }
  1633. else
  1634. {
  1635. $realpath = realpath($path);
  1636. // Strangely there are provider not disabling realpath but returning strange values. :o
  1637. // We at least try to cope with them.
  1638. if ($realpath === $path || $realpath === false)
  1639. {
  1640. return phpbb_own_realpath($path);
  1641. }
  1642. // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
  1643. if (substr($realpath, -1) == DIRECTORY_SEPARATOR)
  1644. {
  1645. $realpath = substr($realpath, 0, -1);
  1646. }
  1647. return $realpath;
  1648. }
  1649. }
  1650. /*
  1651. * Creates a full server path
  1652. */
  1653. function create_server_url($without_script_path = false)
  1654. {
  1655. // usage: $server_url = create_server_url();
  1656. global $config;
  1657. $server_protocol = ($config['cookie_secure']) ? 'https://' : 'http://';
  1658. $server_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($config['server_name']));
  1659. $server_port = ($config['server_port'] <> 80) ? ':' . trim($config['server_port']) : '';
  1660. $script_name = preg_replace('/^\/?(.*?)\/?$/', '\1', trim($config['script_path']));
  1661. $script_name = ($script_name == '') ? '' : '/' . $script_name;
  1662. $server_url = $server_protocol . $server_name . $server_port . ($without_sc

Large files files are truncated, but you can click here to view the full file