PageRenderTime 99ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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_script_path ? '' : $script_name);
  1663. while(substr($server_url, -1, 1) == '/')
  1664. {
  1665. $server_url = substr($server_url, 0, -1);
  1666. }
  1667. $server_url = $server_url . '/';
  1668. return $server_url;
  1669. }
  1670. /**
  1671. * Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url
  1672. */
  1673. function build_url($strip_vars = false)
  1674. {
  1675. global $user;
  1676. // Append SID
  1677. $redirect = append_sid($user->page['page'], true);
  1678. // Add delimiter if not there...
  1679. if (strpos($redirect, '?') === false)
  1680. {
  1681. $redirect .= '?';
  1682. }
  1683. // Strip vars...
  1684. if (($strip_vars !== false) && strpos($redirect, '?') !== false)
  1685. {
  1686. if (!is_array($strip_vars))
  1687. {
  1688. $strip_vars = array($strip_vars);
  1689. }
  1690. $query = $_query = array();
  1691. $args = substr($redirect, strpos($redirect, '?') + 1);
  1692. $args = ($args) ? explode('&', $args) : array();
  1693. $redirect = substr($redirect, 0, strpos($redirect, '?'));
  1694. foreach ($args as $argument)
  1695. {
  1696. $arguments = explode('=', $argument);
  1697. $key = $arguments[0];
  1698. unset($arguments[0]);
  1699. if ($key === '')
  1700. {
  1701. continue;
  1702. }
  1703. $query[$key] = implode('=', $arguments);
  1704. }
  1705. // Strip the vars off
  1706. foreach ($strip_vars as $strip)
  1707. {
  1708. if (isset($query[$strip]))
  1709. {
  1710. unset($query[$strip]);
  1711. }
  1712. }
  1713. // Glue the remaining parts together... already urlencoded
  1714. foreach ($query as $key => $value)
  1715. {
  1716. $_query[] = $key . '=' . $value;
  1717. }
  1718. $query = implode('&', $_query);
  1719. $redirect .= ($query) ? '?' . $query : '';
  1720. }
  1721. // We need to be cautious here.
  1722. // On some situations, the redirect path is an absolute URL, sometimes a relative path
  1723. // For a relative path, let's prefix it with IP_ROOT_PATH to point to the correct location,
  1724. // else we use the URL directly.
  1725. $url_parts = @parse_url($redirect);
  1726. // URL
  1727. if (($url_parts !== false) && !empty($url_parts['scheme']) && !empty($url_parts['host']))
  1728. {
  1729. return str_replace('&', '&amp;', $redirect);
  1730. }
  1731. return IP_ROOT_PATH . str_replace('&', '&amp;', $redirect);
  1732. }
  1733. /**
  1734. * Redirects the user to another page then exits the script nicely
  1735. * This function is intended for urls within the board. It's not meant to redirect to cross-domains.
  1736. *
  1737. * @param string $url The url to redirect to
  1738. * @param bool $return If true, do not redirect but return the sanitized URL. Default is no return.
  1739. * @param bool $disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false.
  1740. */
  1741. function redirect($url, $return = false, $disable_cd_check = false)
  1742. {
  1743. global $db, $cache, $config, $user, $lang;
  1744. $failover_flag = false;
  1745. if (empty($lang))
  1746. {
  1747. setup_basic_lang();
  1748. }
  1749. if (!$return)
  1750. {
  1751. garbage_collection();
  1752. }
  1753. $server_url = create_server_url();
  1754. // Make sure no &amp;'s are in, this will break the redirect
  1755. $url = str_replace('&amp;', '&', $url);
  1756. // Determine which type of redirect we need to handle...
  1757. $url_parts = @parse_url($url);
  1758. if ($url_parts === false)
  1759. {
  1760. // Malformed url, redirect to current page...
  1761. $url = $server_url . $user->page['page'];
  1762. }
  1763. elseif (!empty($url_parts['scheme']) && !empty($url_parts['host']))
  1764. {
  1765. // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work)
  1766. if (!$disable_cd_check && ($url_parts['host'] !== $user->host))
  1767. {
  1768. $url = $server_url;
  1769. }
  1770. }
  1771. elseif ($url[0] == '/')
  1772. {
  1773. // Absolute uri, prepend direct url...
  1774. $url = create_server_url(true) . $url;
  1775. }
  1776. else
  1777. {
  1778. // Relative uri
  1779. $pathinfo = pathinfo($url);
  1780. if (!$disable_cd_check && !file_exists($pathinfo['dirname'] . '/'))
  1781. {
  1782. $url = str_replace('../', '', $url);
  1783. $pathinfo = pathinfo($url);
  1784. if (!file_exists($pathinfo['dirname'] . '/'))
  1785. {
  1786. // fallback to "last known user page"
  1787. // at least this way we know the user does not leave the phpBB root
  1788. $url = $server_url . $user->page['page'];
  1789. $failover_flag = true;
  1790. }
  1791. }
  1792. if (!$failover_flag)
  1793. {
  1794. // Is the uri pointing to the current directory?
  1795. if ($pathinfo['dirname'] == '.')
  1796. {
  1797. $url = str_replace('./', '', $url);
  1798. // Strip / from the beginning
  1799. if ($url && (substr($url, 0, 1) == '/'))
  1800. {
  1801. $url = substr($url, 1);
  1802. }
  1803. if ($user->page['page_dir'])
  1804. {
  1805. $url = $server_url . $user->page['page_dir'] . '/' . $url;
  1806. }
  1807. else
  1808. {
  1809. $url = $server_url . $url;
  1810. }
  1811. }
  1812. else
  1813. {
  1814. // Used ./ before, but IP_ROOT_PATH is working better with urls within another root path
  1815. $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath(IP_ROOT_PATH)));
  1816. $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
  1817. $intersection = array_intersect_assoc($root_dirs, $page_dirs);
  1818. $root_dirs = array_diff_assoc($root_dirs, $intersection);
  1819. $page_dirs = array_diff_assoc($page_dirs, $intersection);
  1820. $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
  1821. // Strip / from the end
  1822. if ($dir && substr($dir, -1, 1) == '/')
  1823. {
  1824. $dir = substr($dir, 0, -1);
  1825. }
  1826. // Strip / from the beginning
  1827. if ($dir && substr($dir, 0, 1) == '/')
  1828. {
  1829. $dir = substr($dir, 1);
  1830. }
  1831. $url = str_replace($pathinfo['dirname'] . '/', '', $url);
  1832. // Strip / from the beginning
  1833. if (substr($url, 0, 1) == '/')
  1834. {
  1835. $url = substr($url, 1);
  1836. }
  1837. $url = (!empty($dir) ? $dir . '/' : '') . $url;
  1838. $url = $server_url . $url;
  1839. }
  1840. }
  1841. }
  1842. // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
  1843. if ((strpos(urldecode($url), "\n") !== false) || (strpos(urldecode($url), "\r") !== false) || (strpos($url, ';') !== false))
  1844. {
  1845. message_die(GENERAL_ERROR, 'Tried to redirect to potentially insecure url');
  1846. //trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
  1847. }
  1848. // Now, also check the protocol and for a valid url the last time...
  1849. $allowed_protocols = array('http', 'https', 'ftp', 'ftps');
  1850. $url_parts = parse_url($url);
  1851. if (($url_parts === false) || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
  1852. {
  1853. message_die(GENERAL_ERROR, 'Tried to redirect to potentially insecure url');
  1854. //trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
  1855. }
  1856. if ($return)
  1857. {
  1858. return $url;
  1859. }
  1860. // Redirect via an HTML form for PITA webservers
  1861. if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE')))
  1862. {
  1863. header('Refresh: 0; URL=' . $url);
  1864. $encoding_charset = !empty($lang['ENCODING']) ? $lang['ENCODING'] : 'UTF-8';
  1865. $lang_dir = !empty($lang['DIRECTION']) ? $lang['DIRECTION'] : 'ltr';
  1866. $header_lang = !empty($lang['HEADER_LANG']) ? $lang['HEADER_LANG'] : 'en-gb';
  1867. $xml_header_lang = !empty($lang['HEADER_LANG_XML']) ? $lang['HEADER_LANG_XML'] : 'en-gb';
  1868. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
  1869. echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $lang_dir . '" lang="' . $header_lang . '" xml:lang="' . $xml_header_lang . '">';
  1870. echo '<head>';
  1871. echo '<meta http-equiv="content-type" content="text/html; charset=' . $encoding_charset . '" />';
  1872. echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&amp;', $url) . '" />';
  1873. echo '<title>' . $lang['Redirect'] . '</title>';
  1874. echo '</head>';
  1875. echo '<body>';
  1876. echo '<div style="text-align: center;">' . sprintf($lang['Redirect_to'], '<a href="' . str_replace('&', '&amp;', $url) . '">', '</a>') . '</div>';
  1877. echo '</body>';
  1878. echo '</html>';
  1879. exit;
  1880. }
  1881. // Behave as per HTTP/1.1 spec for others
  1882. header('Location: ' . $url);
  1883. exit;
  1884. }
  1885. /**
  1886. * Global function for chmodding directories and files for internal use
  1887. * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
  1888. * The function determines owner and group from common.php file and sets the same to the provided file. Permissions are mapped to the group, user always has rw(x) permission.
  1889. * The function uses bit fields to build the permissions.
  1890. * The function sets the appropiate execute bit on directories.
  1891. *
  1892. * Supported constants representing bit fields are:
  1893. *
  1894. * CHMOD_ALL - all permissions (7)
  1895. * CHMOD_READ - read permission (4)
  1896. * CHMOD_WRITE - write permission (2)
  1897. * CHMOD_EXECUTE - execute permission (1)
  1898. *
  1899. * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
  1900. *
  1901. * @param $filename The file/directory to be chmodded
  1902. * @param $perms Permissions to set
  1903. * @return true on success, otherwise false
  1904. *
  1905. * @author faw, phpBB Group
  1906. */
  1907. function phpbb_chmod($filename, $perms = CHMOD_READ)
  1908. {
  1909. // Return if the file no longer exists.
  1910. if (!file_exists($filename))
  1911. {
  1912. return false;
  1913. }
  1914. if (!function_exists('fileowner') || !function_exists('filegroup'))
  1915. {
  1916. $file_uid = $file_gid = false;
  1917. $common_php_owner = $common_php_group = false;
  1918. }
  1919. else
  1920. {
  1921. // Determine owner/group of common.php file and the filename we want to change here
  1922. $common_php_owner = fileowner(IP_ROOT_PATH . 'common.' . PHP_EXT);
  1923. $common_php_group = filegroup(IP_ROOT_PATH . 'common.' . PHP_EXT);
  1924. $file_uid = fileowner($filename);
  1925. $file_gid = filegroup($filename);
  1926. // Try to set the owner to the same common.php has
  1927. if (($common_php_owner !== $file_uid) && ($common_php_owner !== false) && ($file_uid !== false))
  1928. {
  1929. // Will most likely not work
  1930. if (@chown($filename, $common_php_owner));
  1931. {
  1932. clearstatcache();
  1933. $file_uid = fileowner($filename);
  1934. }
  1935. }
  1936. // Try to set the group to the same common.php has
  1937. if (($common_php_group !== $file_gid) && ($common_php_group !== false) && ($file_gid !== false))
  1938. {
  1939. if (@chgrp($filename, $common_php_group));
  1940. {
  1941. clearstatcache();
  1942. $file_gid = filegroup($filename);
  1943. }
  1944. }
  1945. }
  1946. // And the owner and the groups PHP is running under.
  1947. $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false;
  1948. $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false;
  1949. // Who is PHP?
  1950. if (($file_uid === false) || ($file_gid === false) || ($php_uid === false) || ($php_gids === false))
  1951. {
  1952. $php = NULL;
  1953. }
  1954. elseif ($file_uid == $php_uid)
  1955. {
  1956. $php = 'owner';
  1957. }
  1958. elseif (in_array($file_gid, $php_gids))
  1959. {
  1960. $php = 'group';
  1961. }
  1962. else
  1963. {
  1964. $php = 'other';
  1965. }
  1966. // Owner always has read/write permission
  1967. $owner = CHMOD_READ | CHMOD_WRITE;
  1968. if (is_dir($filename))
  1969. {
  1970. $owner |= CHMOD_EXECUTE;
  1971. // Only add execute bit to the permission if the dir needs to be readable
  1972. if ($perms & CHMOD_READ)
  1973. {
  1974. $perms |= CHMOD_EXECUTE;
  1975. }
  1976. }
  1977. switch ($php)
  1978. {
  1979. case null:
  1980. case 'owner':
  1981. /* ATTENTION: if php is owner or NULL we set it to group here. This is the most failsafe combination for the vast majority of server setups.
  1982. $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0));
  1983. clearstatcache();
  1984. if (!is_null($php) || (is_readable($filename) && is_writable($filename)))
  1985. {
  1986. break;
  1987. }
  1988. */
  1989. case 'group':
  1990. $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0));
  1991. clearstatcache();
  1992. if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))))
  1993. {
  1994. break;
  1995. }
  1996. case 'other':
  1997. $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0));
  1998. clearstatcache();
  1999. if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))))
  2000. {
  2001. break;
  2002. }
  2003. default:
  2004. return false;
  2005. break;
  2006. }
  2007. return $result;
  2008. }
  2009. /**
  2010. * Meta refresh assignment
  2011. */
  2012. function meta_refresh($time, $url)
  2013. {
  2014. global $template;
  2015. $url = redirect($url, true);
  2016. // For XHTML compatibility we change back & to &amp;
  2017. $url = str_replace('&', '&amp;', $url);
  2018. $template->assign_vars(array('META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />'));
  2019. return $url;
  2020. }
  2021. /**
  2022. * Outputs correct status line header.
  2023. *
  2024. * Depending on php sapi one of the two following forms is used:
  2025. *
  2026. * Status: 404 Not Found
  2027. *
  2028. * HTTP/1.x 404 Not Found
  2029. *
  2030. * HTTP version is taken from HTTP_VERSION environment variable,
  2031. * and defaults to 1.0.
  2032. *
  2033. * Sample usage:
  2034. *
  2035. * send_status_line(404, 'Not Found');
  2036. *
  2037. * @param int $code HTTP status code
  2038. * @param string $message Message for the status code
  2039. * @return void
  2040. */
  2041. function send_status_line($code, $message)
  2042. {
  2043. if (substr(strtolower(@php_sapi_name()), 0, 3) === 'cgi')
  2044. {
  2045. // in theory, we shouldn't need that due to php doing it. Reality offers a differing opinion, though
  2046. @header("Status: $code $message", true, $code);
  2047. }
  2048. else
  2049. {
  2050. if (!empty($_SERVER['SERVER_PROTOCOL']))
  2051. {
  2052. $version = $_SERVER['SERVER_PROTOCOL'];
  2053. }
  2054. else
  2055. {
  2056. $version = 'HTTP/1.0';
  2057. }
  2058. @header("$version $code $message", true, $code);
  2059. }
  2060. }
  2061. /**
  2062. * Setup basic lang
  2063. */
  2064. function setup_basic_lang()
  2065. {
  2066. global $cache, $config, $lang, $class_plugins;
  2067. if (empty($lang))
  2068. {
  2069. $setup = true;
  2070. if(!file_exists(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/lang_main.' . PHP_EXT))
  2071. {
  2072. $config['default_lang'] = 'english';
  2073. }
  2074. $lang_files = array(
  2075. 'lang_main',
  2076. 'lang_bbcb_mg',
  2077. 'lang_main_upi2db',
  2078. 'lang_news',
  2079. 'lang_main_attach',
  2080. 'lang_main_cback_ctracker',
  2081. );
  2082. if (!empty($config['plugins']['cash']['enabled']) && defined('IN_CASHMOD'))
  2083. {
  2084. $lang_files = array_merge($lang_files, array('lang_cash'));
  2085. }
  2086. $lang_extend_admin = false;
  2087. if (defined('IN_ADMIN'))
  2088. {
  2089. $lang_extend_admin = true;
  2090. $lang_files_admin = array(
  2091. 'lang_admin',
  2092. 'lang_admin_cback_ctracker',
  2093. 'lang_admin_upi2db',
  2094. 'lang_admin_attach',
  2095. 'lang_jr_admin',
  2096. );
  2097. $lang_files = array_merge($lang_files, $lang_files_admin);
  2098. }
  2099. if (defined('IN_CMS'))
  2100. {
  2101. $lang_files_cms = array(
  2102. 'lang_admin',
  2103. 'lang_cms',
  2104. 'lang_blocks',
  2105. 'lang_permissions',
  2106. );
  2107. $lang_files = array_merge($lang_files, $lang_files_cms);
  2108. }
  2109. $lang_files = array_merge($lang_files, $cache->obtain_lang_files());
  2110. // Make sure we keep these files as last inclusion... to be sure they override what is needed to be overridden!!!
  2111. $lang_files = array_merge($lang_files, array('lang_dyn_menu', 'lang_main_settings', 'lang_user_created'));
  2112. foreach ($lang_files as $lang_file)
  2113. {
  2114. // Do not suppress error if in DEBUG_EXTRA mode
  2115. $include_result = (defined('DEBUG_EXTRA') && DEBUG_EXTRA) ? (include(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/' . $lang_file . '.' . PHP_EXT)) : (@include(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/' . $lang_file . '.' . PHP_EXT));
  2116. if ($include_result === false)
  2117. {
  2118. die('Language file ' . IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/' . $lang_file . '.' . PHP_EXT . ' couldn\'t be opened.');
  2119. }
  2120. }
  2121. foreach ($config['plugins'] as $k => $plugin)
  2122. {
  2123. if ($plugin['enabled'])
  2124. {
  2125. $class_plugins->setup_lang($plugin['dir']);
  2126. }
  2127. }
  2128. }
  2129. return true;
  2130. }
  2131. /**
  2132. * Setup extra lang
  2133. */
  2134. function setup_extra_lang($lang_files_array, $lang_base_path = '', $lang_override = '')
  2135. {
  2136. global $config, $lang, $images, $faq, $mtnc;
  2137. if (empty($lang_files_array))
  2138. {
  2139. return false;
  2140. }
  2141. if (!is_array($lang_files_array))
  2142. {
  2143. $lang_files_array = array($lang_files_array);
  2144. }
  2145. $lang_base_path = (empty($lang_base_path) ? (IP_ROOT_PATH . 'language/') : $lang_base_path);
  2146. for ($i = 0; $i < sizeof($lang_files_array); $i++)
  2147. {
  2148. $lang_override = !empty($lang_override) ? $lang_override : $config['default_lang'];
  2149. $user_lang_file = $lang_base_path . 'lang_' . $lang_override . '/' . $lang_files_array[$i] . '.' . PHP_EXT;
  2150. $default_lang_file = $lang_base_path . 'lang_english/' . $lang_files_array[$i] . '.' . PHP_EXT;
  2151. if (@file_exists($user_lang_file))
  2152. {
  2153. @include($user_lang_file);
  2154. }
  2155. elseif (@file_exists($default_lang_file))
  2156. {
  2157. @include($default_lang_file);
  2158. }
  2159. }
  2160. return true;
  2161. }
  2162. /**
  2163. * Merge $lang with $user->lang
  2164. */
  2165. function merge_user_lang()
  2166. {
  2167. global $user, $lang;
  2168. $user->lang = array_merge($user->lang, $lang);
  2169. return true;
  2170. }
  2171. /**
  2172. * Stopwords, Synonyms, INIT
  2173. */
  2174. function stopwords_synonyms_init()
  2175. {
  2176. global $config, $stopwords_array, $synonyms_array;
  2177. if (empty($stopwords_array))
  2178. {
  2179. $stopwords_array = @file(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/search_stopwords.txt');
  2180. }
  2181. if (empty($synonyms_array))
  2182. {
  2183. $synonyms_array = @file(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/search_synonyms.txt');
  2184. }
  2185. }
  2186. /**
  2187. * Get style details
  2188. */
  2189. function get_style($style_id, $from_cache = true)
  2190. {
  2191. global $db, $config, $all_styles_array;
  2192. if (!empty($all_styles_array[$style_id]))
  2193. {
  2194. $style_row = $all_styles_array[$style_id];
  2195. }
  2196. else
  2197. {
  2198. $style_row = array();
  2199. $sql = "SELECT * FROM " . THEMES_TABLE . " WHERE themes_id = " . $style_id . " LIMIT 1";
  2200. $result = $from_cache ? $db->sql_query($sql, 0, 'styles_') : $db->sql_query($sql);
  2201. $style_row = $db->sql_fetchrow($result);
  2202. $db->sql_freeresult($result);
  2203. if (!empty($style_row))
  2204. {
  2205. $all_styles_array[$style_row['themes_id']] = $style_row;
  2206. }
  2207. }
  2208. return $style_row;
  2209. }
  2210. /**
  2211. * Setup the default style
  2212. */
  2213. function setup_style($style_id, $current_default_style)
  2214. {
  2215. global $db, $config, $template, $images, $all_styles_array;
  2216. if (!empty($all_styles_array[$style_id]))
  2217. {
  2218. $template_row = $all_styles_array[$style_id];
  2219. }
  2220. elseif (($style_id == $config['default_style']) && !empty($config['default_style_row']))
  2221. {
  2222. $template_row = $config['default_style_row'];
  2223. }
  2224. else
  2225. {
  2226. $style_id = (int) $style_id;
  2227. $template_row = get_style($style_id, true);
  2228. $style_exists = !empty($template_row) ? true : false;
  2229. if (!$style_exists)
  2230. {
  2231. // We are trying to setup a style which does not exist in the database
  2232. // Try to fallback to the board default (if the user had a custom style)
  2233. // and then any users using this style to the default if it succeeds
  2234. if ($style_id != $config['default_style'])
  2235. {
  2236. $config['default_style'] = $current_default_style;
  2237. $style_id = (int) $config['default_style'];
  2238. $template_row = get_style($style_id, true);
  2239. $style_exists = !empty($template_row) ? true : false;
  2240. if ($style_exists)
  2241. {
  2242. $sql = "UPDATE " . USERS_TABLE . "
  2243. SET user_style = " . (int) $config['default_style'] . "
  2244. WHERE user_style = '" . $style_id . "'";
  2245. $result = $db->sql_query($sql);
  2246. }
  2247. }
  2248. if (!$style_exists)
  2249. {
  2250. message_die(CRITICAL_ERROR, "Could not get theme data for themes_id [$style_id]", '', __LINE__, __FILE__);
  2251. }
  2252. }
  2253. }
  2254. unset($row);
  2255. $all_styles_array[$style_id] = $template_row;
  2256. $row = $template_row;
  2257. $template_path = 'templates/';
  2258. $template_name = $row['template_name'];
  2259. $template = new Template(IP_ROOT_PATH . $template_path . $template_name);
  2260. if ($template)
  2261. {
  2262. $current_template_path = $template_path . $template_name;
  2263. // Mighty Gorgon - Common TPL - BEGIN
  2264. $cfg_path = $template_name;
  2265. $cfg_name = $template_name;
  2266. if (defined('IN_CMS') || defined('IN_ADMIN'))
  2267. {
  2268. $cfg_path = 'common';
  2269. $cfg_name = 'style';
  2270. }
  2271. // Mighty Gorgon - Common TPL - END
  2272. $current_template_cfg = IP_ROOT_PATH . $template_path . $cfg_path . '/' . $cfg_name . '.cfg';
  2273. @include($current_template_cfg);
  2274. if (!defined('TEMPLATE_CONFIG'))
  2275. {
  2276. message_die(CRITICAL_ERROR, "Could not open $current_template_cfg", '', __LINE__, __FILE__);
  2277. }
  2278. }
  2279. return $row;
  2280. }
  2281. /**
  2282. * Setup the mobile style
  2283. */
  2284. function setup_mobile_style()
  2285. {
  2286. global $db, $config, $template, $images;
  2287. $row = array(
  2288. 'themes_id' => 0,
  2289. 'template_name' => 'mobile',
  2290. 'style_name' => 'Mobile',
  2291. 'head_stylesheet' => 'style_white.css',
  2292. 'body_background' => 'white',
  2293. 'body_bgcolor' => '',
  2294. 'tr_class1' => 'row1',
  2295. 'tr_class2' => 'row2',
  2296. 'tr_class3' => 'row3',
  2297. 'td_class1' => 'row1',
  2298. 'td_class2' => 'row2',
  2299. 'td_class3' => 'row3',
  2300. );
  2301. $template_path = 'templates/';
  2302. $template_name = $row['template_name'];
  2303. $template = new Template(IP_ROOT_PATH . $template_path . $template_name);
  2304. if ($template)
  2305. {
  2306. $current_template_path = $template_path . $template_name;
  2307. $current_template_cfg = IP_ROOT_PATH . $template_path . $template_name . '/' . $template_name . '.cfg';
  2308. @include($current_template_cfg);
  2309. if (!defined('TEMPLATE_CONFIG'))
  2310. {
  2311. message_die(CRITICAL_ERROR, "Could not open $current_template_cfg", '', __LINE__, __FILE__);
  2312. }
  2313. }
  2314. return $row;
  2315. }
  2316. /*
  2317. * Checks if a style exists
  2318. */
  2319. function check_style_exists($style_id)
  2320. {
  2321. global $db, $config, $template, $images, $all_styles_array;
  2322. $style_exists = false;
  2323. if (!empty($all_styles_array[$style_id]))
  2324. {
  2325. $style_exists = true;
  2326. }
  2327. else
  2328. {
  2329. $template_row = array();
  2330. $style_id = (int) $style_id;
  2331. $template_row = get_style($style_id, true);
  2332. $style_exists = !empty($template_row) ? true : false;
  2333. }
  2334. return $style_exists;
  2335. }
  2336. /*
  2337. * Get forum id for a post
  2338. */
  2339. function get_forum_topic_id_post($post_id)
  2340. {
  2341. global $db, $cache, $config;
  2342. $post_data = array();
  2343. $sql = "SELECT forum_id, topic_id FROM " . POSTS_TABLE . " WHERE post_id = '" . (int) $post_id . "' LIMIT 1";
  2344. $result = $db->sql_query($sql);
  2345. $post_data = $db->sql_fetchrow($result);
  2346. $db->sql_freeresult($result);
  2347. return $post_data;
  2348. }
  2349. /*
  2350. * Check if a user is allowed to view IP addresses
  2351. */
  2352. function ip_display_auth($user_data, $is_forum = false)
  2353. {
  2354. global $config;
  2355. $is_mod = ($user_data['user_level'] == MOD) ? true : false;
  2356. if (!empty($is_forum))
  2357. {
  2358. global $is_auth;
  2359. $is_mod = !empty($is_auth['auth_mod']) ? MOD : USER;
  2360. }
  2361. $ip_display_auth = (($user_data['user_level'] == ADMIN) || (empty($config['ip_admins_only']) && !empty($is_mod))) ? true : false;
  2362. return $ip_display_auth;
  2363. }
  2364. /*
  2365. * Encode IP addresses to HEX
  2366. */
  2367. function encode_ip($dotquad_ip)
  2368. {
  2369. $ip_sep = explode('.', $dotquad_ip);
  2370. return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
  2371. }
  2372. /*
  2373. * Decode IP addresses from HEX
  2374. */
  2375. function decode_ip($int_ip)
  2376. {
  2377. $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
  2378. return hexdec($hexipbang[0]) . '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
  2379. }
  2380. /*
  2381. * Create calendar timestamp from timezone
  2382. */
  2383. function cal_date($gmepoch, $tz)
  2384. {
  2385. global $config;
  2386. return (@strtotime(gmdate('M d Y H.i.s', $gmepoch + (3600 * $tz))));
  2387. }
  2388. /*
  2389. * A more logic function to output serial dates
  2390. */
  2391. /*
  2392. function dateserial($year, $month, $day, $hour, $minute, $timezone = 'UTC')
  2393. {
  2394. $org_tz = date_default_timezone_get();
  2395. date_default_timezone_set($timezone);
  2396. $date_serial = gmmktime($hour, $minute, 0, $month, $day, $year);
  2397. date_default_timezone_set($org_tz);
  2398. return $date_serial;
  2399. }
  2400. */
  2401. /*
  2402. * strutime function which should convert some time formats into fragments of time
  2403. * (basic idea taken from here: http://it.php.net/manual/en/function.strptime.php)
  2404. */
  2405. function strutime($date, $format)
  2406. {
  2407. $masks = array(
  2408. 'Y' => '(?P<Y>[0-9]{4})',
  2409. 'm' => '(?P<m>[0-9]{2})',
  2410. 'd' => '(?P<d>[0-9]{2})',
  2411. 'H' => '(?P<H>[0-9]{2})',
  2412. 'M' => '(?P<M>[0-9]{2})',
  2413. 'S' => '(?P<S>[0-9]{2})',
  2414. );
  2415. $rexep = "#" . strtr(preg_quote($format), $masks) . "#";
  2416. if(!preg_match($rexep, $date, $out))
  2417. {
  2418. return false;
  2419. }
  2420. $ret = array(
  2421. 'year' => !empty($out['Y']) ? (int) $out['Y'] : 0,
  2422. 'month' => !empty($out['m']) ? (int) $out['m'] : 0,
  2423. 'day' => !empty($out['d']) ? (int) $out['d'] : 0,
  2424. 'hour' => !empty($out['H']) ? (int) $out['H'] : 0,
  2425. 'minute' => !empty($out['M']) ? (int) $out['M'] : 0,
  2426. 'second' => !empty($out['S']) ? (int) $out['S'] : 0,
  2427. );
  2428. return $ret;
  2429. }
  2430. /*
  2431. * Get DST
  2432. */
  2433. function get_dst($gmepoch, $tz = 0)
  2434. {
  2435. global $config, $user;
  2436. $tz = empty($tz) ? $config['board_timezone'] : $tz;
  2437. if (!empty($user->data) && !$user->data['session_logged_in'])
  2438. {
  2439. $user->data['user_time_mode'] = $config['default_time_mode'];
  2440. $user->data['user_dst_time_lag'] = $config['default_dst_time_lag'];
  2441. }
  2442. elseif (!empty($user->data))
  2443. {
  2444. $config['default_time_mode'] = $user->data['user_time_mode'];
  2445. $config['default_dst_time_lag'] = $user->data['user_dst_time_lag'];
  2446. }
  2447. $time_mode = $config['default_time_mode'];
  2448. $dst_time_lag = $config['default_dst_time_lag'];
  2449. switch ($time_mode)
  2450. {
  2451. case MANUAL_DST:
  2452. $dst_sec = $dst_time_lag * 60;
  2453. break;
  2454. case SERVER_SWITCH:
  2455. //$dst_sec = gmdate('I', $gmepoch + (3600 * $tz)) * $dst_time_lag * 60;
  2456. $dst_sec = @date('I', $gmepoch) * $dst_time_lag * 60;
  2457. break;
  2458. default:
  2459. $dst_sec = 0;
  2460. break;
  2461. }
  2462. return $dst_sec;
  2463. }
  2464. /*
  2465. * Create date/time using the specified format and timezone
  2466. */
  2467. function create_date($format, $gmepoch, $tz = 0)
  2468. {
  2469. global $config, $user, $lang;
  2470. static $translate;
  2471. $tz = empty($tz) ? $config['board_timezone'] : $tz;
  2472. // We need to force this ==> isset($lang['datetime']) <== otherwise we may have $lang initialized and we don't want that...
  2473. if (empty($translate) && ($config['default_lang'] != 'english') && isset($lang['datetime']))
  2474. {
  2475. $use_short_names = false;
  2476. if (((strpos($format, '\M') === false) && (strpos($format, 'M') !== false)) || ((strpos($format, '\r') === false) && (strpos($format, 'r') !== false)))
  2477. {
  2478. $use_short_names = true;
  2479. }
  2480. @reset($lang['datetime']);
  2481. while (list($match, $replace) = @each($lang['datetime']))
  2482. {
  2483. $var_name = $match;
  2484. if ((strpos($match, '_short') !== false) && $use_short_names)
  2485. {
  2486. $var_name = str_replace('_short', '', $match);
  2487. }
  2488. $translate[$var_name] = $replace;
  2489. }
  2490. }
  2491. $dst_sec = get_dst($gmepoch, $tz);
  2492. $date = @gmdate($format, $gmepoch + (3600 * $tz) + $dst_sec);
  2493. $date = (!empty($translate) ? strtr($date, $translate) : $date);
  2494. return $date;
  2495. }
  2496. /*
  2497. * Create midnight time for a date
  2498. */
  2499. function create_date_midnight($gmepoch, $tz = 0)
  2500. {
  2501. global $config;
  2502. $tz = empty($tz) ? $config['board_timezone'] : $tz;
  2503. $dst_sec = get_dst($gmepoch, $tz);
  2504. $zone_offset = (3600 * $tz) + $dst_sec;
  2505. list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset));
  2506. $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset;
  2507. return $midnight;
  2508. }
  2509. /*
  2510. * Create date/time using the specified format and timezone
  2511. */
  2512. function create_date_ip($format, $gmepoch, $tz = 0, $day_only = false)
  2513. {
  2514. global $config, $lang;
  2515. $tz = empty($tz) ? $config['board_timezone'] : $tz;
  2516. $midnight = create_date_midnight($gmepoch, $tz);
  2517. $output_date = '';
  2518. $time_sep = !empty($lang['NUMBER_FORMAT_TIME_SEP']) ? $lang['NUMBER_FORMAT_TIME_SEP'] : ':';
  2519. $format_hour = 'H' . $time_sep . 'i';
  2520. if (($gmepoch >= $midnight) && ($gmepoch < ($midnight + 86400)))
  2521. {
  2522. $format = ($day_only) ? $format : $format_hour;
  2523. $output_date = ($day_only) ? $lang['TODAY'] : ($lang['Today_at'] . ' ');
  2524. }
  2525. elseif (($gmepoch < $midnight) && ($gmepoch >= ($midnight - 86400)))
  2526. {
  2527. $format = ($day_only) ? $format : $format_hour;
  2528. $output_date = ($day_only) ? $lang['YESTERDAY'] : ($lang['Yesterday_at'] . ' ');
  2529. }
  2530. $output_date = $output_date . (($day_only && !empty($output_date)) ? '' : create_date($format, $gmepoch, $tz));
  2531. return $output_date;
  2532. }
  2533. /*
  2534. * Converts time fragments to MySQL dates ready for DB storage
  2535. */
  2536. function create_date_mysql_db($date_fragments, $format)
  2537. {
  2538. $date_fragments = array(
  2539. 'year' => !empty($date_fragments['year']) ? (string) $date_fragments['year'] : '0000',
  2540. 'month' => !empty($date_fragments['month']) ? (string) $date_fragments['month'] : '00',
  2541. 'day' => !empty($date_fragments['day']) ? (string) $date_fragments['day'] : '00',
  2542. 'hour' => !empty($date_fragments['hour']) ? (string) $date_fragments['hour'] : '00',
  2543. 'minute' => !empty($date_fragments['minute']) ? (string) $date_fragments['minute'] : '00',
  2544. 'second' => !empty($date_fragments['second']) ? (string) $date_fragments['second'] : '00',
  2545. );
  2546. $date_sep = '-';
  2547. $time_sep = ':';
  2548. $mysql_date = $date_fragments['year'] . $date_sep . $date_fragments['month'] . $date_sep . $date_fragments['day'];
  2549. $mysql_time = $date_fragments['hour'] . $time_sep . $date_fragments['minute'] . $time_sep . $date_fragments['second'];
  2550. switch ($format)
  2551. {
  2552. case 'date':
  2553. $mysql_date_db = $mysql_date;
  2554. break;
  2555. case 'time':
  2556. $mysql_date_db = $mysql_time;
  2557. break;
  2558. default:
  2559. $mysql_date_db = $mysql_date . ' ' . $mysql_time;
  2560. break;
  2561. }
  2562. return $mysql_date_db;
  2563. }
  2564. /*
  2565. * Convert unix to MySQL dates
  2566. */
  2567. function create_date_mysql($time, $output = 'datetime', $tz = false)
  2568. {
  2569. global $config, $lang;
  2570. $tz = ($tz === false) ? $config['board_timezone'] : $tz;
  2571. switch ($output)
  2572. {
  2573. case 'date':
  2574. $mysql_date = create_date('Y-m-d', $time, $tz);
  2575. break;
  2576. case 'time':
  2577. $mysql_date = create_date('H:i:s', $time, $tz);
  2578. break;
  2579. default:
  2580. $mysql_date = create_date('Y-m-d H:i:s', $time, $tz);
  2581. break;
  2582. }
  2583. return $mysql_date;
  2584. }
  2585. /*
  2586. * Format MySQL dates
  2587. */
  2588. function format_date_mysql_php($mysql_date, $format = 'datetime', $output = 'mysql')
  2589. {
  2590. global $config, $lang;
  2591. $date_format = $lang['DATE_FORMAT_DATE_MYSQL_PHP'];
  2592. $mysql_date_sep = ((empty($lang['NUMBER_FORMAT_DATE_SEP']) || ($output == 'mysql')) ? '-' : $lang['NUMBER_FORMAT_DATE_SEP']);
  2593. $mysql_time_sep = ((empty($lang['NUMBER_FORMAT_TIME_SEP']) || ($output == 'mysql')) ? ':' : $lang['NUMBER_FORMAT_TIME_SEP']);
  2594. if (($format == 'datetime') || ($format == 'date'))
  2595. {
  2596. // Mighty Gorgon: we suppose dates are always with leading zeroes and in one of the following formats: dd/mm/yyyy, mm/dd/yyyy, yyyy/mm/dd
  2597. switch ($date_format)
  2598. {
  2599. case 'dmy':
  2600. $mysql_date_only = ($output == 'mysql') ? (substr($mysql_date, 6, 4) . $mysql_date_sep . substr($mysql_date, 3, 2) . $mysql_date_sep . substr($mysql_date, 0, 2)) : (substr($mysql_date, 8, 2) . $mysql_date_sep . substr($mysql_date, 5, 2) . $mysql_date_sep . substr($mysql_date, 0, 4));
  2601. break;
  2602. case 'mdy':
  2603. $mysql_date_only = ($output == 'mysql') ? (substr($mysql_date, 6, 4) . $mysql_date_sep . substr($mysql_date, 0, 2) . $mysql_date_sep . substr($mysql_date, 3, 2)) : (substr($mysql_date, 5, 2) . $mysql_date_sep . substr($mysql_date, 8, 2) . $mysql_date_sep . substr($mysql_date, 0, 4));
  2604. break;
  2605. case 'ymd':
  2606. default:
  2607. $mysql_date_only = ($output == 'mysql') ? (substr($mysql_date, 0, 4) . $mysql_date_sep . substr($mysql_date, 5, 2) . $mysql_date_sep . substr($mysql_date, 8, 2)) : (substr($mysql_date, 0, 4) . $mysql_date_sep . substr($mysql_date, 5, 2) . $mysql_date_sep . substr($mysql_date, 8, 2));
  2608. break;
  2609. }
  2610. }
  2611. switch ($format)
  2612. {
  2613. case 'date':
  2614. $mysql_date = $mysql_date_only;
  2615. break;
  2616. case 'time':
  2617. // Mighty Gorgon: we suppose time is always in the following format: hh:mm:ss
  2618. $mysql_date = empty($mysql_date) ? ('00' . $mysql_time_sep . '00' . $mysql_time_sep . '00') : (substr($mysql_date, 0, 2) . $mysql_time_sep . substr($mysql_date, 3, 2) . $mysql_time_sep . substr($mysql_date, 6, 2));
  2619. break;
  2620. default:
  2621. $mysql_date = $mysql_date_only . ' ' . substr($mysql_date, 12, 2) . $mysql_time_sep . substr($mysql_date, 15, 2) . $mysql_time_sep . substr($mysql_date, 18, 2);
  2622. break;
  2623. }
  2624. return $mysql_date;
  2625. }
  2626. /*
  2627. * Convert time in hours in decimal format
  2628. */
  2629. function convert_time_to_decimal($time, $time_sep = ':')
  2630. {
  2631. $time_decimal = $time;
  2632. $time_fragments = explode($time_sep, $time);
  2633. if (sizeof($time_fragments) > 1)
  2634. {
  2635. $time_decimal = (int) $time_fragments[0] + ((int) $time_fragments[1] / 60);
  2636. if (sizeof($time_fragments) == 3)
  2637. {
  2638. $time_decimal = $time_decimal + ((int) $time_fragments[2] / 3600);
  2639. }
  2640. }
  2641. return $time_decimal;
  2642. }
  2643. // Birthday - BEGIN
  2644. // Add function realdate for Birthday MOD
  2645. // the originate php "date()", does not work proberly on all OS, especially when going back in time
  2646. // before year 1970 (year 0), this function "realdate()", has a much larger valid date range,
  2647. // from 1901 - 2099. it returns a "like" UNIX date format (only date, related letters may be used, due to the fact that
  2648. // the given date value should already be divided by 86400 - leaving no time information left)
  2649. // a input like a UNIX timestamp divided by 86400 is expected, so
  2650. // calculation from the originate php date and mktime is easy.
  2651. // e.g. realdate ("m d Y", 3) returns the string "1 3 1970"
  2652. function realdate($date_syntax = 'Ymd', $date = 0)
  2653. {
  2654. global $config;
  2655. $unix_time = ($date * 86400) + 1;
  2656. // Since we are using create_date, we need to adjust time back by timezone and dst to avoid date change...
  2657. $zone_offset = (3600 * $config['board_timezone']) + get_dst($unix_time, $config['board_timezone']);
  2658. $unix_time = $unix_time - $zone_offset;
  2659. return create_date($date_syntax, $unix_time, $config['board_timezone']);
  2660. }
  2661. // Birthday - END
  2662. /*
  2663. * Format file size
  2664. */
  2665. function format_file_size($filesize)
  2666. {
  2667. global $lang;
  2668. $filesize = (int) $filesize;
  2669. if($filesize >= 1073741824)
  2670. {
  2671. $filesize = sprintf('%.2f ' . $lang['GB'], ($filesize / 1073741824));
  2672. }
  2673. elseif($filesize >= 1048576)
  2674. {
  2675. $filesize = sprintf('%.2f ' . $lang['MB'], ($filesize / 1048576));
  2676. }
  2677. elseif($filesize >= 1024)
  2678. {
  2679. $filesize = sprintf('%.2f ' . $lang['KB'], ($filesize / 1024));
  2680. }
  2681. else
  2682. {
  2683. $filesize = sprintf('%.2f ' . $lang['Bytes'], $filesize);
  2684. }
  2685. return $filesize;
  2686. }
  2687. /*
  2688. * Pagination get the page
  2689. */
  2690. function get_page($num_items, $per_page, $start_item)
  2691. {
  2692. $total_pages = ceil($num_items/$per_page);
  2693. if ($total_pages == 1)
  2694. {
  2695. return '1';
  2696. exit;
  2697. }
  2698. $on_page = floor($start_item / $per_page) + 1;
  2699. $page_string = '';
  2700. for($i = 0; $i < $total_pages + 1; $i++)
  2701. {
  2702. if($i == $on_page)
  2703. {
  2704. $page_string = $i;
  2705. }
  2706. }
  2707. return $page_string;
  2708. }
  2709. /**
  2710. * Return current page (pagination)
  2711. */
  2712. function on_page($num_items, $per_page, $start)
  2713. {
  2714. global $lang;
  2715. // Make sure $per_page is a valid value
  2716. $per_page = ($per_page <= 0) ? 1 : $per_page;
  2717. $on_page = floor($start / $per_page) + 1;
  2718. $total_pages = ceil($num_items / $per_page);
  2719. $page_number = sprintf($lang['Page_of'], $on_page, max($total_pages, 1));
  2720. return $page_number;
  2721. }
  2722. /*
  2723. * Pagination routine, generates page number sequence
  2724. */
  2725. function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = true, $start = 'start')
  2726. {
  2727. global $lang;
  2728. $total_pages = ceil($num_items / $per_page);
  2729. if ($total_pages == 1)
  2730. {
  2731. return '&nbsp;';
  2732. }
  2733. $on_page = floor($start_item / $per_page) + 1;
  2734. $page_string = '';
  2735. if ($total_pages > 10)
  2736. {
  2737. $init_page_max = ($total_pages > 3) ? 3 : $total_pages;
  2738. for($i = 1; $i < $init_page_max + 1; $i++)
  2739. {
  2740. $page_string .= ($i == $on_page) ? '<b>' . $i . '</b>' : '<a href="' . append_sid($base_url . '&amp;' . $start . '=' . (($i - 1) * $per_page)) . '">' . $i . '</a>';
  2741. if ($i < $init_page_max)
  2742. {
  2743. $page_string .= ', ';
  2744. }
  2745. }
  2746. if ($total_pages > 3)
  2747. {
  2748. if (($on_page > 1) && ($on_page < $total_pages))
  2749. {
  2750. $page_string .= ($on_page > 5) ? ' ... ' : ', ';
  2751. $init_page_min = ($on_page > 4) ? $on_page : 5;
  2752. $init_page_max = ($on_page < $total_pages - 4) ? $on_page : $total_pages - 4;
  2753. for($i = $init_page_min - 1; $i < $init_page_max + 2; $i++)
  2754. {
  2755. $page_string .= ($i == $on_page) ? '<b>' . $i . '</b>' : '<a href="' . append_sid($base_url . '&amp;' . $start . '=' . (($i - 1) * $per_page)) . '">' . $i . '</a>';
  2756. if ($i < $init_page_max + 1)
  2757. {
  2758. $page_string .= ', ';
  2759. }
  2760. }
  2761. $page_string .= ($on_page < $total_pages - 4) ? ' ... ' : ', ';
  2762. }
  2763. else
  2764. {
  2765. $page_string .= ' ... ';
  2766. }
  2767. for($i = $total_pages - 2; $i < $total_pages + 1; $i++)
  2768. {
  2769. $page_string .= ($i == $on_page) ? '<b>' . $i . '</b>' : '<a href="' . append_sid($base_url . '&amp;' . $start . '=' . (($i - 1) * $per_page)) . '">' . $i . '</a>';
  2770. if($i < $total_pages)
  2771. {
  2772. $page_string .= ', ';
  2773. }
  2774. }
  2775. }
  2776. }
  2777. else
  2778. {
  2779. for($i = 1; $i < $total_pages + 1; $i++)
  2780. {
  2781. $page_string .= ($i == $on_page) ? '<b>' . $i . '</b>' : '<a href="' . append_sid($base_url . '&amp;' . $start . '=' . (($i - 1) * $per_page)) . '">' . $i . '</a>';
  2782. if ($i < $total_pages)
  2783. {
  2784. $page_string .= ', ';
  2785. }
  2786. }
  2787. }
  2788. if ($add_prevnext_text)
  2789. {
  2790. if ($on_page > 1)
  2791. {
  2792. $page_string = ' <a href="' . append_sid($base_url . '&amp;' . $start . '=' . (($on_page - 2) * $per_page)) . '">' . $lang['Previous'] . '</a>&nbsp;&nbsp;' . $page_string;
  2793. }
  2794. if ($on_page < $total_pages)
  2795. {
  2796. $page_string .= '&nbsp;&nbsp;<a href="' . append_sid($base_url . '&amp;' . $start . '=' . ($on_page * $per_page)) . '">' . $lang['Next'] . '</a>';
  2797. }
  2798. }
  2799. $page_string = ($page_string != '') ? $lang['Goto_page'] . ' ' . $page_string : '&nbsp;';
  2800. return $page_string;
  2801. }
  2802. /**
  2803. * Generate topic pagination
  2804. */
  2805. function generate_topic_pagination($forum_id, $topic_id, $replies, $per_page = 0)
  2806. {
  2807. global $config, $template, $images, $lang;
  2808. $per_page = (!empty($per_page) && intval($per_page)) ? intval($per_page) : $config['posts_per_page'];
  2809. $topic_pagination = array();
  2810. $topic_pagination['base'] = '';
  2811. $topic_pagination['full'] = '';
  2812. $url_append = '';
  2813. $url_append .= (empty($url_append) ? '' : '&amp;') . ((!empty($forum_id) ? (POST_FORUM_URL . '=' . $forum_id) : ''));
  2814. $url_append .= (empty($url_append) ? '' : '&amp;') . ((!empty($topic_id) ? (POST_TOPIC_URL . '=' . $topic_id) : ''));
  2815. if(($replies + 1) > $per_page)
  2816. {
  2817. $total_pages = ceil(($replies + 1) / $per_page);
  2818. $goto_page_prefix = ' [';
  2819. $goto_page = ' <img src="' . $images['icon_gotopage'] . '" alt="' . $lang['Goto_page'] . '" title="' . $lang['Goto_page'] . '" />&nbsp;';
  2820. $times = '1';
  2821. for($j = 0; $j < $replies + 1; $j += $per_page)
  2822. {
  2823. $goto_page .= '<a href="' . append_sid(CMS_PAGE_VIEWTOPIC . '?' . $url_append . '&amp;start=' . $j) . '" title="' . $lang['Goto_page'] . ' ' . $times . '"><b>' . $times . '</b></a>';
  2824. if(($times == 1) && ($total_pages > 4))
  2825. {
  2826. $goto_page .= ' ... ';
  2827. $times = $total_pages - 3;
  2828. $j += ($total_pages - 4) * $per_page;
  2829. }
  2830. elseif($times < $total_pages)
  2831. {
  2832. //$goto_page .= ', ';
  2833. $goto_page .= ' ';
  2834. }
  2835. $times++;
  2836. }
  2837. $goto_page_suffix = ' ]';
  2838. $goto_page .= ' ';
  2839. $topic_pagination['base'] = '<span class="gotopage">' . $goto_page . '</span>';
  2840. $topic_pagination['full'] = '<span class="gotopage">' . $goto_page_prefix . ' ' . $lang['Goto_page'] . $goto_page . $goto_page_suffix . '</span>';
  2841. }
  2842. else
  2843. {
  2844. $topic_pagination['base'] = '&nbsp;';
  2845. $topic_pagination['full'] = '&nbsp;';
  2846. }
  2847. return $topic_pagination;
  2848. }
  2849. /**
  2850. * Generate full pagination with template
  2851. */
  2852. function generate_full_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = true, $start = 'start')
  2853. {
  2854. global $template, $lang;
  2855. $template->assign_vars(array(
  2856. 'PAGINATION' => generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text, $start),
  2857. 'PAGE_NUMBER' => on_page($num_items, $per_page, $start_item),
  2858. 'L_GOTO_PAGE' => $lang['Goto_page']
  2859. )
  2860. );
  2861. return true;
  2862. }
  2863. /**
  2864. * Generate zebra rows
  2865. */
  2866. function ip_zebra_rows($row_class)
  2867. {
  2868. global $theme;
  2869. $row1_class = (!empty($theme['td_class1']) ? $theme['td_class1'] : 'row1');
  2870. $row2_class = (!empty($theme['td_class2']) ? $theme['td_class2'] : 'row2');
  2871. $row_class = (empty($row_class) || ($row_class == $row2_class)) ? $row1_class : $row2_class;
  2872. return $row_class;
  2873. }
  2874. /*
  2875. * This does exactly what preg_quote() does in PHP 4-ish
  2876. * If you just need the 1-parameter preg_quote call, then don't bother using this.
  2877. */
  2878. function phpbb_preg_quote($str, $delimiter)
  2879. {
  2880. $text = preg_quote($str);
  2881. $text = str_replace($delimiter, '\\' . $delimiter, $text);
  2882. return $text;
  2883. }
  2884. /**
  2885. * Censoring
  2886. */
  2887. function censor_text($text)
  2888. {
  2889. static $censors;
  2890. if (empty($text))
  2891. {
  2892. return $text;
  2893. }
  2894. // We moved the word censor checks in here because we call this function quite often - and then only need to do the check once
  2895. if (!isset($censors) || !is_array($censors))
  2896. {
  2897. global $user, $cache;
  2898. // We check here if the user is having viewing censors disabled (and also allowed to do so).
  2899. if ($user->data['user_allowswearywords'])
  2900. {
  2901. $censors = array();
  2902. }
  2903. else
  2904. {
  2905. $censors = $cache->obtain_word_list();
  2906. }
  2907. }
  2908. if (sizeof($censors))
  2909. {
  2910. return preg_replace($censors['match'], $censors['replace'], $text);
  2911. }
  2912. return $text;
  2913. }
  2914. /**
  2915. * Little helper for the build_hidden_fields function
  2916. */
  2917. function _build_hidden_fields($key, $value, $specialchar, $stripslashes)
  2918. {
  2919. $hidden_fields = '';
  2920. if (!is_array($value))
  2921. {
  2922. $value = ($stripslashes) ? stripslashes($value) : $value;
  2923. $value = ($specialchar) ? htmlspecialchars($value, ENT_COMPAT, 'UTF-8') : $value;
  2924. $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n";
  2925. }
  2926. else
  2927. {
  2928. foreach ($value as $_key => $_value)
  2929. {
  2930. $_key = ($stripslashes) ? stripslashes($_key) : $_key;
  2931. $_key = ($specialchar) ? htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') : $_key;
  2932. $hidden_fields .= _build_hidden_fields($key . '[' . $_key . ']', $_value, $specialchar, $stripslashes);
  2933. }
  2934. }
  2935. return $hidden_fields;
  2936. }
  2937. /**
  2938. * Build simple hidden fields from array
  2939. *
  2940. * @param array $field_ary an array of values to build the hidden field from
  2941. * @param bool $specialchar if true, keys and values get specialchared
  2942. * @param bool $stripslashes if true, keys and values get stripslashed
  2943. *
  2944. * @return string the hidden fields
  2945. */
  2946. function build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false)
  2947. {
  2948. $s_hidden_fields = '';
  2949. foreach ($field_ary as $name => $vars)
  2950. {
  2951. $name = ($stripslashes) ? stripslashes($name) : $name;
  2952. $name = ($specialchar) ? htmlspecialchars($name, ENT_COMPAT, 'UTF-8') : $name;
  2953. $s_hidden_fields .= _build_hidden_fields($name, $vars, $specialchar, $stripslashes);
  2954. }
  2955. return $s_hidden_fields;
  2956. }
  2957. // Mighty Gorgon - Full Album Pack - BEGIN
  2958. //--- FLAG operation functions
  2959. function setFlag($flags, $flag)
  2960. {
  2961. return $flags | $flag;
  2962. }
  2963. function clearFlag($flags, $flag)
  2964. {
  2965. return ($flags & ~$flag);
  2966. }
  2967. function checkFlag($flags, $flag)
  2968. {
  2969. return (($flags & $flag) == $flag) ? true : false;
  2970. }
  2971. // Mighty Gorgon - Full Album Pack - END
  2972. //--------------------------------------------------------------------------------------------------
  2973. // board_stats : update the board stats (topics, posts and users)
  2974. //--------------------------------------------------------------------------------------------------
  2975. function board_stats()
  2976. {
  2977. global $db, $cache, $config;
  2978. $config_updated = false;
  2979. // max users
  2980. $sql = "SELECT COUNT(user_id) AS user_total FROM " . USERS_TABLE . " WHERE user_id > 0";
  2981. $result = $db->sql_query($sql);
  2982. $row = $db->sql_fetchrow($result);
  2983. $db->sql_freeresult($result);
  2984. $max_users = (int) $row['user_total'];
  2985. // update
  2986. if ($config['max_users'] != $max_users)
  2987. {
  2988. set_config('max_users', $max_users);
  2989. }
  2990. // newest user
  2991. $sql_active_users = empty($config['inactive_users_memberlists']) ? ' AND user_active = 1 ' : '';
  2992. $sql = "SELECT user_id, username
  2993. FROM " . USERS_TABLE . "
  2994. WHERE user_id <> " . ANONYMOUS . "
  2995. $sql_active_users
  2996. ORDER BY user_id DESC
  2997. LIMIT 1";
  2998. $result = $db->sql_query($sql);
  2999. $row = $db->sql_fetchrow($result);
  3000. $db->sql_freeresult($result);
  3001. $newest_user_id = (int) $row['user_id'];
  3002. if ($config['last_user_id'] != $newest_user_id)
  3003. {
  3004. set_config('last_user_id', $newest_user_id);
  3005. $cache->destroy('newest_user');
  3006. $newest_user = $cache->obtain_newest_user();
  3007. }
  3008. // topics and posts
  3009. $sql = "SELECT SUM(forum_topics) AS topic_total, SUM(forum_posts) AS post_total FROM " . FORUMS_TABLE;
  3010. $result = $db->sql_query($sql);
  3011. $row = $db->sql_fetchrow($result);
  3012. $db->sql_freeresult($result);
  3013. $max_topics = (int) $row['topic_total'];
  3014. $max_posts = (int) $row['post_total'];
  3015. // update
  3016. if ($config['max_topics'] != $max_topics)
  3017. {
  3018. set_config('max_topics', $max_topics);
  3019. }
  3020. if ($config['max_posts'] != $max_posts)
  3021. {
  3022. set_config('max_posts', $max_posts);
  3023. }
  3024. }
  3025. /*
  3026. * Check if the browser is from a mobile device
  3027. */
  3028. function is_mobile()
  3029. {
  3030. global $config, $user;
  3031. if (!empty($config['mobile_style_disable']))
  3032. {
  3033. return false;
  3034. }
  3035. if (!empty($user) && !empty($user->data['is_mobile']))
  3036. {
  3037. return true;
  3038. }
  3039. if (!empty($user) && !empty($user->data['is_bot']))
  3040. {
  3041. $user->data['is_mobile'] = false;
  3042. return false;
  3043. }
  3044. if (!empty($user)) $user->data['is_mobile'] = false;
  3045. $browser = (!empty($user) && !empty($user->browser)) ? $user->browser : (!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
  3046. $browser_lc = strtolower($browser);
  3047. if (strpos($browser_lc, 'windows') !== false)
  3048. {
  3049. return false;
  3050. }
  3051. // Just a quick check on most common browsers...
  3052. if(preg_match('/(android|blackberry|fennec|htc_|iphone|ipod|mobile|midp|mmp|opera mini|opera mobi|phone|symbian|smartphone|up.browser|up.link|wap)/i', $browser_lc))
  3053. {
  3054. if (!empty($user)) $user->data['is_mobile'] = true;
  3055. return true;
  3056. }
  3057. if((strpos(strtolower($_SERVER['HTTP_ACCEPT']), 'application/vnd.wap.xhtml+xml') !== false) || ((isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE']))))
  3058. {
  3059. if (!empty($user)) $user->data['is_mobile'] = true;
  3060. return true;
  3061. }
  3062. $mobile_ua = substr($browser_lc, 0, 4);
  3063. $mobile_agents = array(
  3064. 'w3c ', 'acs-', 'alav', 'alca', 'amoi', 'audi', 'avan', 'benq', 'bird', 'blac',
  3065. 'blaz', 'brew', 'cell', 'cldc', 'cmd-', 'dang', 'doco', 'eric', 'hipt', 'inno',
  3066. 'ipaq', 'java', 'jigs', 'kddi', 'keji', 'leno', 'lg-c', 'lg-d', 'lg-g', 'lge-',
  3067. 'maui', 'maxo', 'midp', 'mits', 'mmef', 'mobi', 'mot-', 'moto', 'mwbp', 'nec-',
  3068. 'newt', 'noki', 'palm', 'pana', 'pant', 'phil', 'play', 'port', 'prox', 'qwap',
  3069. 'sage', 'sams', 'sany', 'sch-', 'sec-', 'send', 'seri', 'sgh-', 'shar', 'sie-',
  3070. 'siem', 'smal', 'smar', 'sony', 'sph-', 'symb', 't-mo', 'teli', 'tim-', 'tosh',
  3071. 'tsm-', 'upg1', 'upsi', 'vk-v', 'voda', 'wap-', 'wapa', 'wapi', 'wapp', 'wapr',
  3072. 'webc', 'winw', 'winw', 'xda', 'xda-'
  3073. );
  3074. if(in_array($mobile_ua, $mobile_agents))
  3075. {
  3076. if (!empty($user)) $user->data['is_mobile'] = true;
  3077. return true;
  3078. }
  3079. if (strpos(strtolower($_SERVER['ALL_HTTP']), 'OperaMini') !== false)
  3080. {
  3081. if (!empty($user)) $user->data['is_mobile'] = true;
  3082. return true;
  3083. }
  3084. // OLD Basic Code
  3085. /*
  3086. if ((strpos($browser, 'Mobile') !== false) || (strpos($browser, 'Symbian') !== false) || (strpos($browser, 'Opera M') !== false) || (strpos($browser, 'Android') !== false) || (stripos($browser, 'HTC_') !== false) || (strpos($browser, 'Fennec/') !== false) || (stripos($browser, 'Blackberry') !== false))
  3087. */
  3088. // Full big preg_match!
  3089. /*
  3090. if(preg_match('/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|htc_|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mobile|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $browser) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i', substr($browser, 0, 4)))
  3091. {
  3092. if (!empty($user)) $user->data['is_mobile'] = true;
  3093. return true;
  3094. }
  3095. */
  3096. return false;
  3097. }
  3098. /*
  3099. * MG BOTS Parsing Function
  3100. */
  3101. function bots_parse($ip_address, $bot_color = '#888888', $browser = false, $check_inactive = false)
  3102. {
  3103. global $db, $lang;
  3104. /*
  3105. // Testing!!!
  3106. $browser = 'mgbot/ 1.0';
  3107. $bot_name = 'MG';
  3108. return $bot_name;
  3109. */
  3110. $bot_name = false;
  3111. //return $bot_name;
  3112. $bot_color = empty($bot_color) ? '#888888' : $bot_color;
  3113. if ($browser != false)
  3114. {
  3115. if ((strpos($browser, 'Firefox') !== false) || (strpos($browser, 'MSIE') !== false) || (strpos($browser, 'Opera') !== false))
  3116. {
  3117. return array('name' => false, 'id' => 0);
  3118. }
  3119. }
  3120. $active_bots = array();
  3121. $sql = "SELECT bot_id, bot_name, bot_active, bot_agent, bot_ip, bot_color
  3122. FROM " . BOTS_TABLE . "
  3123. ORDER BY bot_id";
  3124. $result = $db->sql_query($sql, 0, 'bots_list_');
  3125. while($row = $db->sql_fetchrow($result))
  3126. {
  3127. $active_bots[] = $row;
  3128. }
  3129. $db->sql_freeresult($result);
  3130. for ($i = 0; $i < sizeof($active_bots); $i++)
  3131. {
  3132. if (!empty($active_bots[$i]['bot_agent']) && preg_match('#' . str_replace('\*', '.*?', preg_quote($active_bots[$i]['bot_agent'], '#')) . '#i', $browser))
  3133. {
  3134. $bot_name = (!empty($active_bots[$i]['bot_color']) ? $active_bots[$i]['bot_color'] : ('<b style="color:' . $bot_color . '">' . $active_bots[$i]['bot_name'] . '</b>'));
  3135. if (!empty($check_inactive) && ($active_bots[$i]['bot_active'] == 0))
  3136. {
  3137. if (!defined('STATUS_503')) define('STATUS_503', true);
  3138. message_die(GENERAL_ERROR, $lang['Not_Authorized']);
  3139. }
  3140. return array('name' => $bot_name, 'id' => $active_bots[$i]['bot_id']);
  3141. }
  3142. if (!empty($ip_address) && !empty($active_bots[$i]['bot_ip']))
  3143. {
  3144. foreach (explode(',', $active_bots[$i]['bot_ip']) as $bot_ip)
  3145. {
  3146. $bot_ip = trim($bot_ip);
  3147. if (!empty($bot_ip) && (strpos($ip_address, $bot_ip) === 0))
  3148. {
  3149. $bot_name = (!empty($active_bots[$i]['bot_color']) ? $active_bots[$i]['bot_color'] : ('<b style="color:' . $bot_color . '">' . $active_bots[$i]['bot_name'] . '</b>'));
  3150. if (!empty($check_inactive) && ($active_bots[$i]['bot_active'] == 0))
  3151. {
  3152. if (!defined('STATUS_503')) define('STATUS_503', true);
  3153. message_die(GENERAL_ERROR, $lang['Not_Authorized']);
  3154. }
  3155. return array('name' => $bot_name, 'id' => $active_bots[$i]['bot_id']);
  3156. }
  3157. }
  3158. }
  3159. }
  3160. return array('name' => false, 'id' => 0);
  3161. }
  3162. /*
  3163. * Update bots table
  3164. */
  3165. function bots_table_update($bot_id)
  3166. {
  3167. global $db, $config;
  3168. $sql = "UPDATE " . BOTS_TABLE . "
  3169. SET bot_visit_counter = (bot_visit_counter + 1),
  3170. bot_last_visit = '" . time() . "'
  3171. WHERE bot_id = '" . $bot_id . "'";
  3172. $result = $db->sql_query($sql);
  3173. return true;
  3174. }
  3175. // Ajaxed - BEGIN
  3176. function AJAX_headers($json = false)
  3177. {
  3178. //No caching whatsoever
  3179. if (empty($json))
  3180. {
  3181. header('Content-Type: application/xml');
  3182. }
  3183. header('Expires: Thu, 15 Aug 1984 13:30:00 GMT');
  3184. header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
  3185. header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
  3186. header('Pragma: no-cache'); // HTTP/1.0
  3187. }
  3188. function AJAX_message_die($data_ar, $json = false)
  3189. {
  3190. global $template, $db, $cache, $config;
  3191. if (!headers_sent())
  3192. {
  3193. AJAX_headers($json);
  3194. }
  3195. if (!empty($json))
  3196. {
  3197. echo(json_encode($data_ar));
  3198. }
  3199. else
  3200. {
  3201. $template->set_filenames(array('ajax_result' => 'ajax_result.tpl'));
  3202. foreach($data_ar as $key => $value)
  3203. {
  3204. if ($value !== '')
  3205. {
  3206. $value = utf8_encode(htmlspecialchars($value));
  3207. // Get special characters in posts back ;)
  3208. $value = preg_replace('#&amp;\#(\d{1,4});#i', '&#\1;', $value);
  3209. $template->assign_block_vars('tag', array(
  3210. 'TAGNAME' => $key,
  3211. 'VALUE' => $value
  3212. )
  3213. );
  3214. }
  3215. }
  3216. $template->pparse('ajax_result');
  3217. }
  3218. garbage_collection();
  3219. exit_handler();
  3220. exit;
  3221. }
  3222. // Ajaxed - END
  3223. /**
  3224. * @return valid color or false
  3225. * @param color as string
  3226. * @desc Checks for a valid color string in #rrggbb, rrggbb, #rgb, rgb, rgb(rrr,ggg,bbb) format or color name defined in constant RGB_COLORS_LIST.
  3227. */
  3228. function check_valid_color($color)
  3229. {
  3230. $color = strtolower($color);
  3231. // hex colors
  3232. if (preg_match('/#[0-9,a-f]{6}/', $color) || preg_match('/#[0-9,a-f]{3}/', $color))
  3233. {
  3234. return $color;
  3235. }
  3236. // hex colors
  3237. if (preg_match('/[0-9,a-f]{6}/', $color) || preg_match('/[0-9,a-f]{3}/', $color))
  3238. {
  3239. return '#' . $color;
  3240. }
  3241. // rgb color
  3242. if(substr($color, 0, 4) === 'rgb(' && preg_match('/^rgb\([0-9]+,[0-9]+,[0-9]+\)$/', $color))
  3243. {
  3244. $colors = explode(',', substr($color, 4, strlen($color) - 5));
  3245. for($i = 0; $i < 3; $i++)
  3246. {
  3247. if($colors[$i] > 255)
  3248. {
  3249. return false;
  3250. }
  3251. }
  3252. return sprintf('#%02X%02X%02X', $colors[0], $colors[1], $colors[2]);
  3253. }
  3254. // text color in array
  3255. if (in_array($color, explode(',', RGB_COLORS_LIST)))
  3256. {
  3257. return $color;
  3258. }
  3259. // text color
  3260. if(preg_match('/^[a-z]+$/', $color))
  3261. {
  3262. return $color;
  3263. }
  3264. return false;
  3265. }
  3266. /**
  3267. * Create the sql needed to query the color... this is used also to precisely locate the cache file!
  3268. */
  3269. function user_color_sql($user_id)
  3270. {
  3271. $sql = "SELECT u.username, u.user_active, u.user_mask, u.user_color, u.group_id
  3272. FROM " . USERS_TABLE . " u
  3273. WHERE u.user_id = '" . $user_id . "'
  3274. LIMIT 1";
  3275. return $sql;
  3276. }
  3277. /**
  3278. * Clear user color cache.
  3279. *
  3280. * @param => user_id
  3281. * @return => true on success
  3282. */
  3283. function clear_user_color_cache($user_id)
  3284. {
  3285. $dir = ((@file_exists(USERS_CACHE_FOLDER)) ? USERS_CACHE_FOLDER : @phpbb_realpath(USERS_CACHE_FOLDER));
  3286. @unlink($dir . 'sql_' . POST_USERS_URL . '_' . md5(user_color_sql($user_id)) . '.' . PHP_EXT);
  3287. return true;
  3288. }
  3289. /**
  3290. * Create a profile link for the user with his own color
  3291. */
  3292. function colorize_username($user_id, $username = '', $user_color = '', $user_active = true, $no_profile = false, $get_only_color_style = false, $from_db = false, $force_cache = false, $alt_link_url = '')
  3293. {
  3294. global $db, $config, $lang;
  3295. $user_id = empty($user_id) ? ANONYMOUS : $user_id;
  3296. $is_guest = ($user_id == ANONYMOUS) ? true : false;
  3297. if ((!$is_guest && $from_db) || (!$is_guest && empty($username) && empty($user_color)))
  3298. {
  3299. // Get the user info and see if they are assigned a color_group
  3300. $sql = user_color_sql($user_id);
  3301. $cache_cleared = (CACHE_COLORIZE && defined('IN_ADMIN')) ? clear_user_color_cache($user_id) : false;
  3302. $result = ((CACHE_COLORIZE || $force_cache) && !defined('IN_ADMIN')) ? $db->sql_query($sql, 0, POST_USERS_URL . '_', USERS_CACHE_FOLDER) : $db->sql_query($sql);
  3303. $sql_row = array();
  3304. $row = array();
  3305. while ($sql_row = $db->sql_fetchrow($result))
  3306. {
  3307. $row = $sql_row;
  3308. }
  3309. $db->sql_freeresult($result);
  3310. $user_mask = (empty($row['user_active']) && !empty($row['user_mask'])) ? true : false;
  3311. if (!empty($user_mask))
  3312. {
  3313. global $user;
  3314. $user_mask = ($user->data['user_level'] == ADMIN) ? false : true;
  3315. }
  3316. $user_id = $user_mask ? ANONYMOUS : $user_id;
  3317. $username = $user_mask ? $lang['INACTIVE_USER'] : $row['username'];
  3318. $user_color = $user_mask ? '' : $row['user_color'];
  3319. $user_active = $row['user_active'];
  3320. }
  3321. $username = (($user_id == ANONYMOUS) || empty($username)) ? $lang['Guest'] : str_replace('&amp;amp;', '&amp;', htmlspecialchars($username));
  3322. $user_link_url = !empty($alt_link_url) ? str_replace('$USER_ID', $user_id, $alt_link_url) : ((defined('USER_LINK_URL_OVERRIDE')) ? str_replace('$USER_ID', $user_id, USER_LINK_URL_OVERRIDE) : (CMS_PAGE_PROFILE . '?mode=viewprofile&amp;' . POST_USERS_URL . '=' . $user_id));
  3323. $user_link_style = '';
  3324. $user_link_begin = '<a href="' . append_sid(IP_ROOT_PATH . $user_link_url) . '"';
  3325. $user_link_end = '>' . $username . '</a>';
  3326. if (!$user_active || $is_guest)
  3327. {
  3328. $user_link = $user_link_begin . $user_link_style . $user_link_end;
  3329. $user_link = ($no_profile || $is_guest) ? $username : $user_link;
  3330. $user_link = ($get_only_color_style) ? '' : $user_link;
  3331. }
  3332. else
  3333. {
  3334. $user_color = check_valid_color($user_color);
  3335. $user_color = ($user_color != false) ? $user_color : $config['active_users_color'];
  3336. $user_link_style = ' style="font-weight: bold; text-decoration: none; color: ' . $user_color . ';"';
  3337. if ($no_profile)
  3338. {
  3339. $user_link = '<span' . $user_link_style . '>' . $username . '</span>';
  3340. }
  3341. else
  3342. {
  3343. $user_link = $user_link_begin . $user_link_style . $user_link_end;
  3344. }
  3345. $user_link = ($get_only_color_style) ? $user_link_style : $user_link;
  3346. }
  3347. return $user_link;
  3348. }
  3349. function user_get_avatar($user_id, $user_level, $user_avatar, $user_avatar_type, $user_allow_avatar, $path_prefix = '', $max_width = 0)
  3350. {
  3351. global $config;
  3352. $user_avatar_path = '';
  3353. $user_avatar_link = '';
  3354. $user_avatar_dim = '';
  3355. if ($user_avatar_type && ($user_id != ANONYMOUS) && $user_allow_avatar)
  3356. {
  3357. switch($user_avatar_type)
  3358. {
  3359. case USER_AVATAR_UPLOAD:
  3360. $user_avatar_path = ($config['allow_avatar_upload']) ? ($path_prefix . $config['avatar_path'] . '/' . $user_avatar) : '';
  3361. break;
  3362. case USER_AVATAR_REMOTE:
  3363. $user_avatar_path = $user_avatar;
  3364. if ($user_level != ADMIN)
  3365. {
  3366. // Set this to false if you want to force height as well
  3367. $force_width_only = true;
  3368. $avatar_width = $config['avatar_max_width'];
  3369. $avatar_height = $config['avatar_max_height'];
  3370. if (!empty($config['allow_avatar_remote']))
  3371. {
  3372. $user_avatar_dim = ' width="' . $avatar_width . '"' . (($force_width_only) ? '' : (' height="' . $avatar_height . '"'));
  3373. $user_avatar_path = $user_avatar;
  3374. }
  3375. else
  3376. {
  3377. $user_avatar_path = '';
  3378. }
  3379. }
  3380. break;
  3381. case USER_AVATAR_GALLERY:
  3382. $user_avatar_path = ($config['allow_avatar_local']) ? ($path_prefix . $config['avatar_gallery_path'] . '/' . $user_avatar) : '';
  3383. break;
  3384. case USER_GRAVATAR:
  3385. $user_avatar_path = ($config['enable_gravatars']) ? get_gravatar($user_avatar) : '';
  3386. break;
  3387. case USER_AVATAR_GENERATOR:
  3388. $user_avatar_path = ($config['allow_avatar_generator']) ? $user_avatar : '';
  3389. break;
  3390. default:
  3391. $user_avatar_path = '';
  3392. }
  3393. }
  3394. if (empty($user_avatar_path))
  3395. {
  3396. $user_avatar_path = get_default_avatar($user_id, $path_prefix);
  3397. }
  3398. if (!empty($max_width))
  3399. {
  3400. $max_width = (int) $max_width;
  3401. if (($max_width > 10) && ($max_width < 240))
  3402. {
  3403. $user_avatar_dim = ' style="width: ' . $max_width . 'px; max-width: ' . $max_width . 'px;"';
  3404. }
  3405. }
  3406. $avatar_class = (($max_width > 10) && ($max_width < 40)) ? '' : ' class="avatar"';
  3407. $user_avatar_link = (!empty($user_avatar_path)) ? '<img src="' . $user_avatar_path . '" alt="avatar"' . $avatar_class . $user_avatar_dim . ' />' : '&nbsp;';
  3408. return $user_avatar_link;
  3409. }
  3410. function get_default_avatar($user_id, $path_prefix = '')
  3411. {
  3412. global $config;
  3413. $avatar_img = '';
  3414. if ($config['default_avatar_set'] != 3)
  3415. {
  3416. if (($config['default_avatar_set'] == 0) && ($user_id == ANONYMOUS) && ($config['default_avatar_guests_url'] != ''))
  3417. {
  3418. $avatar_img = $config['default_avatar_guests_url'];
  3419. }
  3420. elseif (($config['default_avatar_set'] == 1) && ($user_id != ANONYMOUS) && ($config['default_avatar_users_url'] != ''))
  3421. {
  3422. $avatar_img = $config['default_avatar_users_url'];
  3423. }
  3424. elseif ($config['default_avatar_set'] == 2)
  3425. {
  3426. if (($user_id == ANONYMOUS) && ($config['default_avatar_guests_url'] != ''))
  3427. {
  3428. $avatar_img = $config['default_avatar_guests_url'];
  3429. }
  3430. elseif (($user_id != ANONYMOUS) && ($config['default_avatar_users_url'] != ''))
  3431. {
  3432. $avatar_img = $config['default_avatar_users_url'];
  3433. }
  3434. }
  3435. }
  3436. $avatar_img = $path_prefix . $avatar_img;
  3437. return $avatar_img;
  3438. }
  3439. function get_gravatar($email)
  3440. {
  3441. global $config;
  3442. $image = '';
  3443. if(!empty($email))
  3444. {
  3445. $image = 'http://www.gravatar.com/avatar.php?gravatar_id=' . md5($email);
  3446. if($config['gravatar_rating'])
  3447. {
  3448. $image .= '&amp;rating=' . $config['gravatar_rating'];
  3449. }
  3450. if($config['gravatar_default_image'])
  3451. {
  3452. $server_protocol = ($config['cookie_secure']) ? 'https://' : 'http://';
  3453. $server_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($config['server_name']));
  3454. $server_port = ($config['server_port'] <> 80) ? ':' . trim($config['server_port']) : '';
  3455. $script_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($config['script_path']));
  3456. $script_name = ($script_name == '') ? $script_name : '/' . $script_name;
  3457. $url = preg_replace('#^\/?(.*?)\/?$#', '/\1', trim($config['gravatar_default_image']));
  3458. $default_image = $server_protocol . $server_name . $server_port . $script_name . $url;
  3459. $image .= '&amp;default=' . urlencode($default_image);
  3460. }
  3461. $max_size = ($config['avatar_max_width'] <= $config['avatar_max_height']) ? $config['avatar_max_width'] : $config['avatar_max_height'];
  3462. $image .= ($max_size < 80) ? '&amp;size=' . $max_size : '';
  3463. }
  3464. return $image;
  3465. }
  3466. /*
  3467. * Gets all social networks and instant messaging (SN/IM) fields feeded only from profile table (doesn't get chat id...)
  3468. * This function should simplify adding/removing SN/IM fields to user profile
  3469. */
  3470. function get_user_sn_im_array()
  3471. {
  3472. $user_sn_im_array = array(
  3473. '500px' => array('field' => 'user_500px', 'lang' => '500PX', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => '500px', 'form' => 'f500px'),
  3474. 'aim' => array('field' => 'user_aim', 'lang' => 'AIM', 'icon_tpl' => 'icon_aim', 'icon_tpl_vt' => 'icon_aim2', 'url' => 'aim:goim?screenname={REF}&amp;message=Hello', 'alt_name' => 'aim', 'form' => 'aim'),
  3475. 'facebook' => array('field' => 'user_facebook', 'lang' => 'FACEBOOK', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'facebook', 'form' => 'facebook'),
  3476. 'flickr' => array('field' => 'user_flickr', 'lang' => 'FLICKR', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'flickr', 'form' => 'flickr'),
  3477. 'github' => array('field' => 'user_github', 'lang' => 'GITHUB', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'github', 'form' => 'github'),
  3478. 'googleplus' => array('field' => 'user_googleplus', 'lang' => 'GOOGLEPLUS', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'googleplus', 'form' => 'googleplus'),
  3479. 'icq' => array('field' => 'user_icq', 'lang' => 'ICQ', 'icon_tpl' => 'icon_icq', 'icon_tpl_vt' => 'icon_icq2', 'url' => 'http://www.icq.com/people/webmsg.php?to={REF}', 'alt_name' => 'icq', 'form' => 'icq'),
  3480. 'instagram' => array('field' => 'user_instagram', 'lang' => 'INSTAGRAM', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'instagram', 'form' => 'instagram'),
  3481. 'jabber' => array('field' => 'user_jabber', 'lang' => 'JABBER', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'jabber', 'form' => 'jabber'),
  3482. 'linkedin' => array('field' => 'user_linkedin', 'lang' => 'LINKEDIN', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'linkedin', 'form' => 'linkedin'),
  3483. 'msn' => array('field' => 'user_msnm', 'lang' => 'MSNM', 'icon_tpl' => 'icon_msnm', 'icon_tpl_vt' => 'icon_msnm2', 'url' => 'http://spaces.live.com/{REF}', 'alt_name' => 'msnm', 'form' => 'msn'),
  3484. 'pinterest' => array('field' => 'user_pinterest', 'lang' => 'PINTEREST', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'pinterest', 'form' => 'pinterest'),
  3485. 'skype' => array('field' => 'user_skype', 'lang' => 'SKYPE', 'icon_tpl' => 'icon_skype', 'icon_tpl_vt' => 'icon_skype2', 'url' => 'callto://{REF}', 'alt_name' => 'skype', 'form' => 'skype'),
  3486. 'twitter' => array('field' => 'user_twitter', 'lang' => 'TWITTER', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'twitter', 'form' => 'twitter'),
  3487. 'vimeo' => array('field' => 'user_vimeo', 'lang' => 'VIMEO', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'vimeo', 'form' => 'vimeo'),
  3488. 'yahoo' => array('field' => 'user_yim', 'lang' => 'YIM', 'icon_tpl' => 'icon_yim', 'icon_tpl_vt' => 'icon_yim2', 'url' => 'http://edit.yahoo.com/config/send_webmesg?.target={REF}&amp;.src=pg', 'alt_name' => 'yim', 'form' => 'yim'),
  3489. 'youtube' => array('field' => 'user_youtube', 'lang' => 'YOUTUBE', 'icon_tpl' => '', 'icon_tpl_vt' => '', 'url' => '{REF}', 'alt_name' => 'youtube', 'form' => 'youtube'),
  3490. );
  3491. return $user_sn_im_array;
  3492. }
  3493. /*
  3494. * This function will build a complete IM link with image and lang
  3495. */
  3496. function build_im_link($im_type, $user_data, $im_icon_type = false, $im_img = false, $im_url = false, $im_status = false, $im_lang = false)
  3497. {
  3498. global $config, $user, $lang, $images;
  3499. $available_im = get_user_sn_im_array();
  3500. $extra_im = array(
  3501. 'chat' => array('field' => 'user_id', 'lang' => 'AJAX_SHOUTBOX_PVT_LINK', 'icon_tpl' => 'icon_im_chat', 'icon_tpl_vt' => 'icon_im_chat', 'url' => '{REF}')
  3502. );
  3503. $available_im = array_merge($available_im, $extra_im);
  3504. // Default values
  3505. $im_icon = '';
  3506. $im_icon_append = '';
  3507. if (!empty($user_data[$available_im[$im_type]['field']]))
  3508. {
  3509. $im_id = $user_data[$available_im[$im_type]['field']];
  3510. $im_ref = $im_id;
  3511. }
  3512. else
  3513. {
  3514. return '';
  3515. }
  3516. if (!empty($im_status) && in_array($im_type, array('chat')) && in_array($im_status, array('online', 'offline', 'hidden')))
  3517. {
  3518. $im_icon_append = '_' . $im_status;
  3519. }
  3520. if (!empty($available_im[$im_type]))
  3521. {
  3522. if (!empty($im_icon_type) && in_array($im_icon_type, array('icon', 'icon_tpl', 'icon_tpl_vt')))
  3523. {
  3524. if ($im_icon_type == 'icon')
  3525. {
  3526. $im_icon = $images['icon_im_' . $im_type . $im_icon_append];
  3527. }
  3528. else
  3529. {
  3530. $im_icon = $images[$available_im[$im_type][$im_icon_type]];
  3531. }
  3532. }
  3533. $im_ref = str_replace('{REF}', $im_ref, $available_im[$im_type]['url']);
  3534. if ($im_type == 'chat')
  3535. {
  3536. // JHL: No chat icon if the user is anonymous, or the profiled user is offline
  3537. if (empty($user->data['session_logged_in']) || empty($user_data['user_session_time']) || ($user_data['user_session_time'] < (time() - $config['online_time'])))
  3538. {
  3539. return '';
  3540. }
  3541. $ajax_chat_page = !empty($config['ajax_chat_link_type']) ? CMS_PAGE_AJAX_CHAT : CMS_PAGE_AJAX_SHOUTBOX;
  3542. $ajax_chat_room = 'chat_room=' . (min($user->data['user_id'], $user_data['user_id']) . '|' . max($user->data['user_id'], $user_data['user_id']));
  3543. $ajax_chat_link = append_sid($ajax_chat_page . '?' . $ajax_chat_room);
  3544. $im_ref = !empty($config['ajax_chat_link_type']) ? ($ajax_chat_link . '" target="_chat') : ('#" onclick="window.open(\'' . $ajax_chat_link . '\', \'_chat\', \'width=720,height=600,resizable=yes\'); return false;');
  3545. }
  3546. $im_img = (!empty($im_img) && !empty($im_icon)) ? $im_icon : false;
  3547. $im_lang = !empty($im_lang) ? $im_lang : (!empty($available_im[$im_type]['lang']) ? $lang[$available_im[$im_type]['lang']] : '');
  3548. }
  3549. $link_title = ($im_type == 'chat') ? '' : (' - ' . $im_id);
  3550. $link_title = $im_lang . $link_title;
  3551. $link_content = !empty($im_img) ? ('<img src="' . $im_img . '" alt="' . $im_lang . '"' . (empty($im_url) ? '' : (' title="' . $im_id . '"')) . ' />') : $im_lang;
  3552. $im_link = !empty($im_url) ? $im_ref : ('<a href="' . $im_ref . '" title="' . $link_title . '">' . $link_content . '</a>');
  3553. return $im_link;
  3554. }
  3555. /*
  3556. * Get AD
  3557. */
  3558. function get_ad($ad_position)
  3559. {
  3560. global $db, $config, $user;
  3561. $ad_text = '';
  3562. if (!$config['ads_' . $ad_position])
  3563. {
  3564. return $ad_text;
  3565. }
  3566. $user_auth = AUTH_ALL;
  3567. $user_level = ($user->data['user_id'] == ANONYMOUS) ? ANONYMOUS : $user->data['user_level'];
  3568. switch ($user_level)
  3569. {
  3570. case ADMIN:
  3571. $user_auth = AUTH_ADMIN;
  3572. break;
  3573. case MOD:
  3574. $user_auth = AUTH_MOD;
  3575. break;
  3576. case USER:
  3577. $user_auth = AUTH_REG;
  3578. break;
  3579. }
  3580. $sql = "SELECT *
  3581. FROM " . ADS_TABLE . "
  3582. WHERE ad_position = '" . $ad_position . "'
  3583. AND ad_active = 1
  3584. AND ad_auth >= " . $user_auth . "
  3585. ORDER BY ad_id";
  3586. $result = $db->sql_query($sql, 0, 'ads_');
  3587. $active_ads = array();
  3588. while($row = $db->sql_fetchrow($result))
  3589. {
  3590. $active_ads[] = $row;
  3591. }
  3592. $db->sql_freeresult($result);
  3593. $total_ads = sizeof($active_ads);
  3594. if ($total_ads > 0)
  3595. {
  3596. $selected_ad = rand(0, $total_ads - 1);
  3597. $ad_text = $active_ads[$selected_ad]['ad_text'];
  3598. if ($active_ads[$selected_ad]['ad_format'])
  3599. {
  3600. global $bbcode;
  3601. @include_once(IP_ROOT_PATH . 'includes/bbcode.' . PHP_EXT);
  3602. $bbcode->allow_html = false;
  3603. $bbcode->allow_bbcode = true;
  3604. $bbcode->allow_smilies = true;
  3605. $ad_text = $bbcode->parse($ad_text);
  3606. }
  3607. }
  3608. return $ad_text;
  3609. }
  3610. function files_remove($files_to_remove)
  3611. {
  3612. for ($i = 0; $i < sizeof($files_to_remove); $i++)
  3613. {
  3614. if (file_exists($files_to_remove[$i]))
  3615. {
  3616. @unlink($files_to_remove[$i]);
  3617. }
  3618. }
  3619. return true;
  3620. }
  3621. function empty_cache_folders_admin()
  3622. {
  3623. global $cache;
  3624. $cache->destroy_datafiles(array('_hooks', '_moderators'), MAIN_CACHE_FOLDER, 'data', false);
  3625. $cache->destroy_datafiles(array('_birthdays_list', '_lang', '_today_visitors'), MAIN_CACHE_FOLDER, 'data', true);
  3626. $cache->destroy_datafiles(array('_'), CMS_CACHE_FOLDER, 'sql', true);
  3627. $cache->destroy_datafiles(array('_'), FORUMS_CACHE_FOLDER, 'sql', true);
  3628. $cache->destroy_datafiles(array('_'), SQL_CACHE_FOLDER, 'sql', true);
  3629. return true;
  3630. }
  3631. function empty_cache_folders_cms()
  3632. {
  3633. global $cache;
  3634. $cache->destroy_datafiles(array('_cms_config', '_cms_layouts_config'), MAIN_CACHE_FOLDER, 'data', false);
  3635. $cache->destroy_datafiles(array('_cms_global_blocks_config'), MAIN_CACHE_FOLDER, 'data', true);
  3636. $cache->destroy_datafiles(array('_'), CMS_CACHE_FOLDER, 'sql', true);
  3637. $cache->destroy_datafiles(array('_'), SQL_CACHE_FOLDER, 'sql', true);
  3638. return true;
  3639. }
  3640. function empty_cache_folders($cache_folder = '', $files_per_step = 0)
  3641. {
  3642. $skip_files = array(
  3643. '.',
  3644. '..',
  3645. '.htaccess',
  3646. 'index.htm',
  3647. 'index.html',
  3648. 'index.' . PHP_EXT,
  3649. 'empty_cache.bat',
  3650. );
  3651. $sql_prefix = 'sql_';
  3652. $tpl_prefix = 'tpl_';
  3653. // Make sure the forum tree is deleted...
  3654. @unlink(MAIN_CACHE_FOLDER . CACHE_TREE_FILE);
  3655. $cache_dirs_array = array(MAIN_CACHE_FOLDER, CMS_CACHE_FOLDER, FORUMS_CACHE_FOLDER, POSTS_CACHE_FOLDER, SQL_CACHE_FOLDER, TOPICS_CACHE_FOLDER, USERS_CACHE_FOLDER);
  3656. $cache_dirs_array = ((empty($cache_folder) || !in_array($cache_folder, $cache_dirs_array)) ? $cache_dirs_array : array($cache_folder));
  3657. $files_counter = 0;
  3658. for ($i = 0; $i < sizeof($cache_dirs_array); $i++)
  3659. {
  3660. $dir = $cache_dirs_array[$i];
  3661. $dir = ((is_dir($dir)) ? $dir : @phpbb_realpath($dir));
  3662. $res = opendir($dir);
  3663. while(($file = readdir($res)) !== false)
  3664. {
  3665. $file_full_path = $dir . $file;
  3666. if (!in_array($file, $skip_files) && !is_dir($file_full_path))
  3667. {
  3668. @chmod($file_full_path, 0777);
  3669. $res2 = @unlink($file_full_path);
  3670. $files_counter++;
  3671. }
  3672. if (($files_per_step > 0) && ($files_counter >= $files_per_step))
  3673. {
  3674. closedir($res);
  3675. return $files_per_step;
  3676. }
  3677. }
  3678. closedir($res);
  3679. }
  3680. return true;
  3681. }
  3682. function empty_images_cache_folders($files_per_step = 0)
  3683. {
  3684. global $config;
  3685. $skip_files = array(
  3686. '.',
  3687. '..',
  3688. '.htaccess',
  3689. 'index.htm',
  3690. 'index.html',
  3691. 'index.' . PHP_EXT,
  3692. );
  3693. $cache_dirs_array = array(POSTED_IMAGES_THUMBS_PATH);
  3694. if (!empty($config['plugins']['album']['enabled']))
  3695. {
  3696. $cache_dirs_array = array_merge($cache_dirs_array, array(
  3697. IP_ROOT_PATH . ALBUM_CACHE_PATH,
  3698. IP_ROOT_PATH . ALBUM_MED_CACHE_PATH,
  3699. IP_ROOT_PATH . ALBUM_WM_CACHE_PATH
  3700. ));
  3701. }
  3702. $files_counter = 0;
  3703. for ($i = 0; $i < sizeof($cache_dirs_array); $i++)
  3704. {
  3705. $dir = $cache_dirs_array[$i];
  3706. $dir = ((is_dir($dir)) ? $dir : @phpbb_realpath($dir));
  3707. $res = opendir($dir);
  3708. while(($file = readdir($res)) !== false)
  3709. {
  3710. $file_full_path = $dir . $file;
  3711. if (!in_array($file, $skip_files))
  3712. {
  3713. if (is_dir($file_full_path))
  3714. {
  3715. $subres = @opendir($file_full_path);
  3716. while(($subfile = readdir($subres)) !== false)
  3717. {
  3718. $subfile_full_path = $file_full_path . '/' . $subfile;
  3719. if (!in_array($subfile, $skip_files) && !is_dir($subfile_full_path))
  3720. {
  3721. if(preg_match('/(\.gif$|\.png$|\.jpg|\.jpeg)$/is', $subfile))
  3722. {
  3723. @chmod($subfile_full_path, 0777);
  3724. $res2 = @unlink($subfile_full_path);
  3725. $files_counter++;
  3726. }
  3727. if (($files_per_step > 0) && ($files_counter >= $files_per_step))
  3728. {
  3729. closedir($subres);
  3730. return $files_per_step;
  3731. }
  3732. }
  3733. }
  3734. closedir($subres);
  3735. }
  3736. elseif(preg_match('/(\.gif$|\.png$|\.jpg|\.jpeg)$/is', $file))
  3737. {
  3738. @chmod($file_full_path, 0777);
  3739. $res2 = @unlink($file_full_path);
  3740. $files_counter++;
  3741. }
  3742. }
  3743. if (($files_per_step > 0) && ($files_counter >= $files_per_step))
  3744. {
  3745. closedir($res);
  3746. return $files_per_step;
  3747. }
  3748. }
  3749. closedir($res);
  3750. if ($cg == true)
  3751. {
  3752. return true;
  3753. }
  3754. }
  3755. return true;
  3756. }
  3757. // Handler, header and footer
  3758. /**
  3759. * Page Header
  3760. */
  3761. function page_header($title = '', $parse_template = false)
  3762. {
  3763. global $db, $cache, $config, $user, $template, $images, $theme, $lang, $tree;
  3764. global $table_prefix, $SID, $_SID;
  3765. global $ip_cms, $cms_config_vars, $cms_config_global_blocks, $cms_config_layouts, $cms_page;
  3766. global $starttime, $base_memory_usage, $do_gzip_compress, $start;
  3767. global $gen_simple_header, $meta_content, $nav_separator, $nav_links, $nav_pgm, $nav_add_page_title, $skip_nav_cat;
  3768. global $breadcrumbs;
  3769. global $forum_id, $topic_id;
  3770. if (defined('HEADER_INC'))
  3771. {
  3772. return;
  3773. }
  3774. define('HEADER_INC', true);
  3775. // gzip_compression
  3776. $config['gzip_compress_runtime'] = (isset($config['gzip_compress_runtime']) ? $config['gzip_compress_runtime'] : $config['gzip_compress']);
  3777. $config['url_rw_runtime'] = ($config['url_rw'] || ($config['url_rw_guests'] && ($user->data['user_id'] == ANONYMOUS))) ? true : false;
  3778. if ($config['gzip_compress_runtime'])
  3779. {
  3780. if (@extension_loaded('zlib') && !headers_sent())
  3781. {
  3782. ob_start('ob_gzhandler');
  3783. }
  3784. }
  3785. else
  3786. {
  3787. // We need to enable this otherwise URL Rewrite will not work without output buffering
  3788. if ($config['url_rw_runtime'] && !headers_sent())
  3789. {
  3790. ob_start();
  3791. }
  3792. }
  3793. // CMS
  3794. if(!defined('CMS_INIT'))
  3795. {
  3796. define('CMS_INIT', true);
  3797. $cms_config_vars = $cache->obtain_cms_config();
  3798. $cms_config_global_blocks = $cache->obtain_cms_global_blocks_config(false);
  3799. }
  3800. $server_url = create_server_url();
  3801. $page_url = pathinfo($_SERVER['SCRIPT_NAME']);
  3802. $page_query = $_SERVER['QUERY_STRING'];
  3803. $meta_content['page_title'] = !empty($title) ? $title : $meta_content['page_title'];
  3804. $meta_content['page_title'] = empty($meta_content['page_title']) ? $config['sitename'] : strip_tags($meta_content['page_title']);
  3805. $meta_content['page_title_clean'] = empty($meta_content['page_title_clean']) ? strip_tags($meta_content['page_title']) : $meta_content['page_title_clean'];
  3806. // DYNAMIC META TAGS - BEGIN
  3807. // Reset some defaults... to be sure some values are taken from DB properly
  3808. $lang['Default_META_Keywords'] = (!empty($config['site_meta_keywords_switch']) && !empty($config['site_meta_keywords'])) ? $config['site_meta_keywords'] : (!empty($lang['Default_META_Keywords']) ? $lang['Default_META_Keywords'] : strtolower(htmlspecialchars(strip_tags($config['sitename']))));
  3809. $lang['Default_META_Description'] = (!empty($config['site_meta_description_switch']) && !empty($config['site_meta_description'])) ? $config['site_meta_description'] : (!empty($lang['Default_META_Description']) ? $lang['Default_META_Description'] : htmlspecialchars(strip_tags($config['site_desc'])));
  3810. $lang['Default_META_Author'] = (!empty($config['site_meta_author_switch']) && !empty($config['site_meta_author'])) ? $config['site_meta_author'] : (!empty($lang['Default_META_Author']) ? $lang['Default_META_Author'] : htmlspecialchars(strip_tags($config['sitename'])));
  3811. $lang['Default_META_Copyright'] = (!empty($config['site_meta_copyright_switch']) && !empty($config['site_meta_copyright'])) ? $config['site_meta_copyright'] : (!empty($lang['Default_META_Copyright']) ? $lang['Default_META_Copyright'] : htmlspecialchars(strip_tags($config['sitename'])));
  3812. $meta_content_pages_array = array(CMS_PAGE_VIEWFORUM, CMS_PAGE_VIEWFORUMLIST, CMS_PAGE_VIEWTOPIC);
  3813. if (!in_array($page_url['basename'], $meta_content_pages_array))
  3814. {
  3815. $meta_content['cat_id'] = request_var(POST_CAT_URL, 0);
  3816. $meta_content['forum_id'] = request_var(POST_FORUM_URL, 0);
  3817. $meta_content['topic_id'] = request_var(POST_TOPIC_URL, 0);
  3818. $meta_content['post_id'] = request_var(POST_POST_URL, 0);
  3819. $no_meta_pages_array = array(CMS_PAGE_LOGIN, CMS_PAGE_PRIVMSG, CMS_PAGE_POSTING, 'kb.' . PHP_EXT);
  3820. if (!in_array($page_url['basename'], $no_meta_pages_array) && (!empty($meta_content['post_id']) || !empty($meta_content['topic_id']) || !empty($meta_content['forum_id']) || !empty($meta_content['cat_id'])))
  3821. {
  3822. @include_once(IP_ROOT_PATH . 'includes/functions_meta.' . PHP_EXT);
  3823. create_meta_content();
  3824. }
  3825. else
  3826. {
  3827. $meta_content['page_title'] = (defined('IN_LOGIN') ? $lang['Login'] : $meta_content['page_title']);
  3828. $meta_content['description'] = (defined('IN_LOGIN') ? $lang['Default_META_Description'] : $meta_content['description']);
  3829. $meta_content['keywords'] = (defined('IN_LOGIN') ? $lang['Default_META_Keywords'] : $meta_content['keywords']);
  3830. }
  3831. }
  3832. $meta_content['description'] = !empty($meta_content['description']) ? ($meta_content['description'] . (META_TAGS_ATTACH ? (' - ' . $lang['Default_META_Description']) : '')) : $lang['Default_META_Description'];
  3833. $meta_content['keywords'] = !empty($meta_content['keywords']) ? ($meta_content['keywords'] . (META_TAGS_ATTACH ? (' - ' . $lang['Default_META_Keywords']) : '')) : $lang['Default_META_Keywords'];
  3834. $meta_content['description'] = strip_tags($meta_content['description']);
  3835. $meta_content['keywords'] = strip_tags($meta_content['keywords']);
  3836. $meta_content['keywords'] = (substr($meta_content['keywords'], -2) == ', ') ? substr($meta_content['keywords'], 0, -2) : $meta_content['keywords'];
  3837. $phpbb_meta = '';
  3838. $phpbb_meta .= '<meta name="author" content="' . $lang['Default_META_Author'] . '" />' . "\n";
  3839. $phpbb_meta .= '<meta name="description" content="' . str_replace('"', '', $meta_content['description']) . '" />' . "\n";
  3840. $phpbb_meta .= '<meta name="keywords" content="' . str_replace('"', '', $meta_content['keywords']) . '" />' . "\n";
  3841. // These META are not valid and needed anymore by SEO and HTML 5
  3842. /*
  3843. $phpbb_meta .= '<meta name="title" content="' . $meta_content['page_title'] . '" />' . "\n";
  3844. $phpbb_meta .= '<meta name="copyright" content="' . $lang['Default_META_Copyright'] . '" />' . "\n";
  3845. $phpbb_meta .= '<meta name="category" content="general" />' . "\n";
  3846. $phpbb_meta .= '<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9" />' . "\n";
  3847. */
  3848. if (defined('IN_ADMIN') || defined('IN_CMS') || defined('IN_SEARCH') || defined('IN_POSTING'))
  3849. {
  3850. $phpbb_meta_content = 'noindex,nofollow';
  3851. }
  3852. else
  3853. {
  3854. if (defined('ROBOTS_NOINDEX'))
  3855. {
  3856. $phpbb_meta_content = 'noindex';
  3857. }
  3858. else
  3859. {
  3860. $phpbb_meta_content = 'index,follow';
  3861. }
  3862. }
  3863. $phpbb_meta .= '<meta name="robots" content="' . $phpbb_meta_content . '" />' . "\n";
  3864. $phpbb_meta .= !empty($lang['Extra_Meta']) ? ($lang['Extra_Meta'] . "\n\n") : "\n";
  3865. // Mighty Gorgon - Smart Header - Begin
  3866. $encoding_charset = !empty($lang['ENCODING']) ? $lang['ENCODING'] : 'UTF-8';
  3867. $lang_dir = !empty($lang['DIRECTION']) ? $lang['DIRECTION'] : 'ltr';
  3868. $header_lang = !empty($lang['HEADER_LANG']) ? $lang['HEADER_LANG'] : 'en-gb';
  3869. $xml_header_lang = !empty($lang['HEADER_LANG_XML']) ? $lang['HEADER_LANG_XML'] : 'en-gb';
  3870. $og_header_lang = !empty($lang['HEADER_OG_LANG']) ? $lang['HEADER_OG_LANG'] : 'en_GB';
  3871. $doctype_html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
  3872. //$doctype_html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n";
  3873. $doctype_html .= '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $lang_dir . '" lang="' . $header_lang . '" xml:lang="' . $xml_header_lang . '">' . "\n";
  3874. if ($page_url['basename'] == CMS_PAGE_VIEWONLINE)
  3875. {
  3876. $phpbb_meta .= '<meta http-equiv="refresh" content="180;url=viewonline.' . PHP_EXT . '" />' . "\n";
  3877. }
  3878. // Mighty Gorgon - Smart Header - End
  3879. $canonical_pages_array = array(CMS_PAGE_FORUM, CMS_PAGE_VIEWFORUM, CMS_PAGE_VIEWTOPIC);
  3880. if (in_array($page_url['basename'], $canonical_pages_array))
  3881. {
  3882. $canonical_append = '';
  3883. if ($page_url['basename'] == CMS_PAGE_FORUM)
  3884. {
  3885. $canonical_append .= (!empty($meta_content['cat_id']) ? ((empty($canonical_append) ? '' : '&amp;') . POST_CAT_URL . '=' . $meta_content['cat_id']) : '');
  3886. }
  3887. $canonical_append .= (!empty($meta_content['forum_id']) ? ((empty($canonical_append) ? '' : '&amp;') . POST_FORUM_URL . '=' . $meta_content['forum_id']) : '');
  3888. $canonical_append .= (!empty($meta_content['topic_id']) ? ((empty($canonical_append) ? '' : '&amp;') . POST_TOPIC_URL . '=' . $meta_content['topic_id']) : '');
  3889. $canonical_append .= (!empty($meta_content['post_id']) ? ((empty($canonical_append) ? '' : '&amp;') . POST_POST_URL . '=' . $meta_content['post_id']) : '');
  3890. $canonical_append .= (!empty($start) ? ((empty($canonical_append) ? '' : '&amp;') . 'start=' . $start) : '');
  3891. $canonical_url = $server_url . $page_url['basename'] . (empty($canonical_append) ? '' : '?') . $canonical_append;
  3892. // Mighty Gorgon - OpenGraph - BEGIN
  3893. $phpbb_meta .= '<meta property="og:locale" content="' . $og_header_lang . '" />' . "\n";
  3894. $phpbb_meta .= '<meta property="og:title" content="' . $meta_content['page_title'] . '" />' . "\n";
  3895. $phpbb_meta .= '<meta property="og:type" content="article" />' . "\n";
  3896. $phpbb_meta .= (!empty($canonical_url) ? ('<meta property="og:url" content="' . $canonical_url . '" />' . "\n") : '');
  3897. $phpbb_meta .= '<meta property="og:site_name" content="' . $config['sitename'] . '" />' . "\n";
  3898. $phpbb_meta .= '<meta property="og:description" content="' . $meta_content['description'] . '" />' . "\n";
  3899. if (!empty($meta_content['og_img']))
  3900. {
  3901. foreach ($meta_content['og_img'] as $og_img_src)
  3902. {
  3903. $phpbb_meta .= '<meta property="og:image" content="' . $og_img_src . '" />' . "\n";
  3904. }
  3905. }
  3906. $phpbb_meta .= "\n";
  3907. // Mighty Gorgon - OpenGraph - END
  3908. $phpbb_meta .= (!empty($canonical_url) ? ('<link rel="canonical" href="' . $canonical_url . '" />' . "\n") : '');
  3909. }
  3910. // DYNAMIC META TAGS - END
  3911. // Mighty Gorgon - AJAX Features - Begin
  3912. $ajax_user_check = '';
  3913. $ajax_user_check_alt = '';
  3914. if (!empty($config['ajax_features']))
  3915. {
  3916. $ajax_user_check = 'onkeyup="AJAXUsernameSearch(this.value, 0);"';
  3917. $ajax_user_check_alt = 'onkeyup="AJAXUsernameSearch(this.value, 1);"';
  3918. }
  3919. // Mighty Gorgon - AJAX Features - End
  3920. // Generate HTML required for Mozilla Navigation bar
  3921. $nav_base_url = $server_url;
  3922. // Mozilla navigation bar - Default items that should be valid on all pages.
  3923. // Defined here to correctly assign the Language Variables and be able to change the variables within code.
  3924. /*
  3925. // TOP and FORUM are not allowed on HTML 5
  3926. $nav_links['top'] = array (
  3927. 'url' => append_sid(CMS_PAGE_HOME),
  3928. 'title' => $config['sitename']
  3929. );
  3930. $nav_links['forum'] = array (
  3931. 'url' => append_sid(CMS_PAGE_FORUM),
  3932. 'title' => sprintf($lang['Forum_Index'], $config['sitename'])
  3933. );
  3934. */
  3935. $nav_links['search'] = array (
  3936. 'url' => append_sid(CMS_PAGE_SEARCH),
  3937. 'title' => $lang['Search']
  3938. );
  3939. $nav_links['help'] = array (
  3940. 'url' => append_sid(CMS_PAGE_FAQ),
  3941. 'title' => $lang['FAQ']
  3942. );
  3943. $nav_links['author'] = array (
  3944. 'url' => append_sid(CMS_PAGE_MEMBERLIST),
  3945. 'title' => $lang['Memberlist']
  3946. );
  3947. $nav_links_html = '';
  3948. while(list($nav_item, $nav_array) = @each($nav_links))
  3949. {
  3950. if (!empty($nav_array['url']))
  3951. {
  3952. $nav_links_html .= '<link rel="' . $nav_item . '" type="text/html" title="' . strip_tags($nav_array['title']) . '" href="' . $nav_base_url . $nav_array['url'] . '" />' . "\n";
  3953. }
  3954. else
  3955. {
  3956. // We have a nested array, used for items like <link rel='chapter'> that can occur more than once.
  3957. while(list(,$nested_array) = each($nav_array))
  3958. {
  3959. $nav_links_html .= '<link rel="' . $nav_item . '" type="text/html" title="' . strip_tags($nested_array['title']) . '" href="' . $nav_base_url . $nested_array['url'] . '" />' . "\n";
  3960. }
  3961. }
  3962. }
  3963. // RSS Autodiscovery - BEGIN
  3964. $rss_url = $nav_base_url . 'rss.' . PHP_EXT;
  3965. $rss_forum_id = request_var(POST_FORUM_URL, 0);
  3966. $rss_url_append = '';
  3967. $rss_a_url_append = '';
  3968. if($rss_forum_id != 0)
  3969. {
  3970. $rss_url_append = '?' . POST_FORUM_URL . '=' . $rss_forum_id;
  3971. $rss_a_url_append = '&amp;' . POST_FORUM_URL . '=' . $rss_forum_id;
  3972. }
  3973. $nav_links_html .= '<link rel="alternate" type="application/rss+xml" title="RSS" href="' . $rss_url . $rss_url_append . '" />' . "\n";
  3974. $nav_links_html .= '<link rel="alternate" type="application/atom+xml" title="Atom" href="' . $rss_url . '?atom' . $rss_a_url_append . '" />' . "\n";
  3975. // RSS Autodiscovery - END
  3976. // Time Management - BEGIN
  3977. // Format Timezone. We are unable to use array_pop here, because of PHP3 compatibility
  3978. $s_timezone = str_replace('.0', '', sprintf('%.1f', number_format($config['board_timezone'], 1)));
  3979. $l_timezone = $lang['tz'][$s_timezone];
  3980. if (!$user->data['session_logged_in'])
  3981. {
  3982. $user->data['user_time_mode'] = $config['default_time_mode'];
  3983. }
  3984. switch ($user->data['user_time_mode'])
  3985. {
  3986. case MANUAL_DST:
  3987. $time_message = sprintf($lang['All_times'], $l_timezone) . $lang['dst_enabled_mode'];
  3988. break;
  3989. case SERVER_SWITCH:
  3990. $time_message = sprintf($lang['All_times'], $l_timezone);
  3991. if (@date('I'))
  3992. {
  3993. $time_message = $time_message . $lang['dst_enabled_mode'];
  3994. }
  3995. break;
  3996. default:
  3997. $time_message = sprintf($lang['All_times'], $l_timezone);
  3998. break;
  3999. }
  4000. $time_message = str_replace('GMT', 'UTC', $time_message);
  4001. // Time Management - END
  4002. // Mighty Gorgon - Advanced Switches - BEGIN
  4003. $new_pm_switch = false;
  4004. $new_private_chat_switch = false;
  4005. // LOGGED IN CHECK - BEGIN
  4006. if (!$user->data['session_logged_in'])
  4007. {
  4008. // Allow autologin?
  4009. if (!isset($config['allow_autologin']) || $config['allow_autologin'])
  4010. {
  4011. $template->assign_block_vars('switch_allow_autologin', array());
  4012. }
  4013. $smart_redirect = strrchr($_SERVER['SCRIPT_NAME'], '/');
  4014. $smart_redirect = substr($smart_redirect, 1, strlen($smart_redirect));
  4015. if(($smart_redirect == (CMS_PAGE_PROFILE)) || ($smart_redirect == (CMS_PAGE_LOGIN)))
  4016. {
  4017. $smart_redirect = '';
  4018. }
  4019. if(isset($_GET) && !empty($smart_redirect))
  4020. {
  4021. $smart_get_keys = array_keys($_GET);
  4022. for ($i = 0; $i < sizeof($_GET); $i++)
  4023. {
  4024. //Better sanitize each key...
  4025. $smart_get_keys[$i] = htmlspecialchars($smart_get_keys[$i]);
  4026. if ($smart_get_keys[$i] != 'sid')
  4027. {
  4028. $smart_redirect .= '&amp;' . $smart_get_keys[$i] . '=' . urlencode(ip_utf8_decode($_GET[$smart_get_keys[$i]]));
  4029. }
  4030. }
  4031. }
  4032. $u_login_logout = CMS_PAGE_LOGIN;
  4033. $u_login_logout .= (!empty($smart_redirect)) ? '?redirect=' . $smart_redirect : '';
  4034. $l_login_logout = $lang['Login'];
  4035. $l_login_logout2 = $lang['Login'];
  4036. $s_last_visit = '';
  4037. $icon_pm = $images['pm_no_new_msg'];
  4038. $l_privmsgs_text = $lang['Login_check_pm'];
  4039. $l_privmsgs_text_unread = '';
  4040. $s_privmsg_new = 0;
  4041. $icon_private_chat = $images['private_chat'];
  4042. $u_private_chat = '#';
  4043. }
  4044. else
  4045. {
  4046. if (!empty($user->data['user_popup_pm']))
  4047. {
  4048. $template->assign_block_vars('switch_enable_pm_popup', array());
  4049. }
  4050. $u_login_logout = CMS_PAGE_LOGIN . '?logout=true&amp;sid=' . $user->data['session_id'];
  4051. $l_login_logout = $lang['Logout'] . ' (' . $user->data['username'] . ')';
  4052. $l_login_logout2 = $lang['Logout'];
  4053. $s_last_visit = create_date($config['default_dateformat'], $user->data['user_lastvisit'], $config['board_timezone']);
  4054. // DOWNLOADS ADV - BEGIN
  4055. //@include(IP_ROOT_PATH . PLUGINS_PATH . $config['plugins']['downloads']['dir'] . 'includes/dl_page_header_inc.' . PHP_EXT);
  4056. // DOWNLOADS ADV - END
  4057. // Obtain number of new private messages
  4058. if (empty($gen_simple_header))
  4059. {
  4060. // Birthday - BEGIN
  4061. // see if user has or have had birthday, also see if greeting are enabled
  4062. if (($user->data['user_birthday'] != 999999) && $config['birthday_greeting'] && (create_date('Ymd', time(), $config['board_timezone']) >= $user->data['user_next_birthday_greeting'] . realdate('md', $user->data['user_birthday'])))
  4063. {
  4064. if (!function_exists('birthday_pm_send'))
  4065. {
  4066. include_once(IP_ROOT_PATH . 'includes/functions_users.' . PHP_EXT);
  4067. }
  4068. birthday_pm_send();
  4069. }
  4070. // Birthday - END
  4071. if ($user->data['user_profile_view'] && $user->data['user_profile_view_popup'])
  4072. {
  4073. $template->assign_vars(array(
  4074. 'PROFILE_VIEW' => true,
  4075. 'U_PROFILE_VIEW' => append_sid('profile_view_popup.' . PHP_EXT),
  4076. )
  4077. );
  4078. }
  4079. if ($user->data['user_new_privmsg'] && !$config['privmsg_disable'])
  4080. {
  4081. $new_pm_switch = true;
  4082. $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $lang['New_pm'] : $lang['New_pms'];
  4083. $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']);
  4084. if ($user->data['user_last_privmsg'] > $user->data['user_lastvisit'])
  4085. {
  4086. $sql = "UPDATE " . USERS_TABLE . "
  4087. SET user_last_privmsg = '" . $user->data['user_lastvisit'] . "'
  4088. WHERE user_id = " . $user->data['user_id'];
  4089. $db->sql_query($sql);
  4090. $s_privmsg_new = 1;
  4091. $icon_pm = $images['pm_new_msg'];
  4092. }
  4093. else
  4094. {
  4095. $s_privmsg_new = 0;
  4096. $icon_pm = $images['pm_new_msg'];
  4097. }
  4098. }
  4099. else
  4100. {
  4101. $l_privmsgs_text = $lang['No_new_pm'];
  4102. $s_privmsg_new = 0;
  4103. $icon_pm = $images['pm_no_new_msg'];
  4104. }
  4105. $icon_private_chat = $images['private_chat'];
  4106. if (!empty($user->data['user_private_chat_alert']))
  4107. {
  4108. $new_private_chat_switch = true;
  4109. $icon_private_chat = $images['private_chat_alert'];
  4110. $ajax_chat_page = !empty($config['ajax_chat_link_type']) ? CMS_PAGE_AJAX_CHAT : CMS_PAGE_AJAX_SHOUTBOX;
  4111. $ajax_chat_room = 'chat_room=' . $user->data['user_private_chat_alert'];
  4112. $ajax_chat_link = append_sid($ajax_chat_page . '?' . $ajax_chat_room);
  4113. $ajax_chat_ref = !empty($config['ajax_chat_link_type']) ? ($ajax_chat_link . '" target="_chat') : ('#" onclick="window.open(\'' . $ajax_chat_link . '\', \'_chat\', \'width=720,height=600,resizable=yes\'); $(\'#shoutbox_pvt_alert\').css(\'display\', \'none\'); return false;');
  4114. $u_private_chat = $ajax_chat_ref;
  4115. }
  4116. if ($user->data['user_unread_privmsg'])
  4117. {
  4118. $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $lang['Unread_pm'] : $lang['Unread_pms'];
  4119. $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']);
  4120. }
  4121. else
  4122. {
  4123. $l_privmsgs_text_unread = $lang['No_unread_pm'];
  4124. }
  4125. }
  4126. else
  4127. {
  4128. $icon_pm = $images['pm_no_new_msg'];
  4129. $l_privmsgs_text = $lang['Login_check_pm'];
  4130. $l_privmsgs_text_unread = '';
  4131. $s_privmsg_new = 0;
  4132. }
  4133. // We don't want this SQL being too expensive... so we will allow the number of new messages only for some pages... (you can add here other pages if you wish!)
  4134. // We will also allow the number of new messages only for users which log on frequently
  4135. $new_messages_counter_pages_array = array(CMS_PAGE_FORUM, CMS_PAGE_VIEWFORUM);
  4136. $display_counter = ($config['enable_new_messages_number'] && !$user->data['is_bot'] && in_array($page_url['basename'], $new_messages_counter_pages_array) && ($user->data['user_lastvisit'] > (time() - (LAST_LOGIN_DAYS_NEW_POSTS_RESET * 60 * 60 * 24)))) ? true : false;
  4137. if ($display_counter)
  4138. {
  4139. $auth_forum = '';
  4140. if ($user->data['user_level'] != ADMIN)
  4141. {
  4142. if (!function_exists('auth_forum_read'))
  4143. {
  4144. include_once(IP_ROOT_PATH . 'includes/functions_upi2db.' . PHP_EXT);
  4145. }
  4146. $user->data['auth_forum_id'] = isset($user->data['auth_forum_id']) ? $user->data['auth_forum_id'] : auth_forum_read($user->data);
  4147. $auth_forum = (!empty($user->data['auth_forum_id'])) ? ' AND p.forum_id IN (' . $user->data['auth_forum_id'] . ') ' : '';
  4148. }
  4149. $sql = "SELECT p.forum_id, t.topic_poster
  4150. FROM " . POSTS_TABLE . " p, " . TOPICS_TABLE . " t
  4151. WHERE t.topic_id = p.topic_id
  4152. AND p.post_time >= " . $user->data['user_lastvisit'] . $auth_forum . "
  4153. AND p.poster_id != " . $user->data['user_id'];
  4154. $db->sql_return_on_error(true);
  4155. $result = $db->sql_query($sql);
  4156. $db->sql_return_on_error(false);
  4157. if ($result)
  4158. {
  4159. $is_auth_ary = auth(AUTH_READ, AUTH_LIST_ALL, $user->data);
  4160. $new_posts = 0;
  4161. while ($row = $db->sql_fetchrow($result))
  4162. {
  4163. if ((intval($is_auth_ary[$row['forum_id']]['auth_read']) != AUTH_SELF) || $user->data['user_level'] == ADMIN || ($user->data['user_level'] == MOD && $config['allow_mods_view_self'] == true) || ($row['topic_poster'] == $user->data['user_id']))
  4164. {
  4165. $new_posts++;
  4166. }
  4167. }
  4168. $lang['Search_new'] = $lang['Search_new'] . ' (' . $new_posts . ')';
  4169. $lang['New'] = $lang['New'] . ' (' . $new_posts . ')';
  4170. $lang['NEW_POSTS_SHORT'] = $lang['New_Label'] . ' (' . $new_posts . ')';
  4171. $lang['NEW_POSTS_LONG'] = $lang['New_Messages_Label'] . ' (' . $new_posts . ')';
  4172. $lang['Search_new2'] = $lang['Search_new2'] . ' (' . $new_posts . ')';
  4173. $lang['Search_new_p'] = $lang['Search_new_p'] . ' (' . $new_posts . ')';
  4174. $db->sql_freeresult($result);
  4175. }
  4176. }
  4177. else
  4178. {
  4179. $lang['NEW_POSTS_SHORT'] = $lang['New_Label'];
  4180. $lang['NEW_POSTS_LONG'] = $lang['New_Messages_Label'];
  4181. }
  4182. }
  4183. // LOGGED IN CHECK - END
  4184. if (!defined('IN_CMS'))
  4185. {
  4186. // UPI2DB - BEGIN
  4187. $upi2db_first_use = '';
  4188. $u_display_new = array();
  4189. if($user->data['upi2db_access'])
  4190. {
  4191. $u_display_new = index_display_new($user->data['upi2db_unread']);
  4192. $template->assign_block_vars('switch_upi2db_on', array());
  4193. $template->assign_var('IS_UPI2DB', true);
  4194. $upi2db_first_use = ($user->data['user_upi2db_datasync'] == '0') ? ('<script type="text/javascript">' . "\n" . '// <![CDATA[' . "\n" . 'alert ("' . $lang['upi2db_first_use_txt'] . '");' . "\n" . '// ]]>' . "\n" . '</script>') : '';
  4195. }
  4196. else
  4197. {
  4198. if ($user->data['session_logged_in'])
  4199. {
  4200. $template->assign_block_vars('switch_upi2db_off', array());
  4201. }
  4202. }
  4203. // UPI2DB - END
  4204. // Digests - BEGIN
  4205. if (!empty($config['cron_digests_interval']) && ($config['cron_digests_interval'] > 0))
  4206. {
  4207. if (!defined('DIGEST_SITE_URL'))
  4208. {
  4209. $digest_server_url = create_server_url();
  4210. define('DIGEST_SITE_URL', $digest_server_url);
  4211. }
  4212. setup_extra_lang(array('lang_digests'));
  4213. if ($user->data['session_logged_in'])
  4214. {
  4215. $template->assign_block_vars('switch_show_digests', array());
  4216. }
  4217. }
  4218. // Digests - END
  4219. // Visit Counter - BEGIN
  4220. if ($config['visit_counter_switch'])
  4221. {
  4222. $sql = "UPDATE " . CONFIG_TABLE . "
  4223. SET config_value = (config_value + 1)
  4224. WHERE config_name = 'visit_counter'";
  4225. $result = $db->sql_query($sql);
  4226. }
  4227. // Visit Counter - END
  4228. // Mighty Gorgon - Random Quote - Begin
  4229. $randomquote_phrase = '';
  4230. if ($config['show_random_quote'])
  4231. {
  4232. @include_once(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/lang_randomquote.' . PHP_EXT);
  4233. $randomquote_phrase = $randomquote[rand(0, sizeof($randomquote) - 1)];
  4234. }
  4235. // Mighty Gorgon - Random Quote - End
  4236. // Mighty Gorgon - Advanced Switches - END
  4237. // Show Online Block - BEGIN
  4238. // Get basic (usernames + totals) online situation
  4239. $online_userlist = '';
  4240. $l_online_users = '';
  4241. $ac_online_users = array('reg' => 0, 'guests' => 0, 'tot' => 0, 'list' => '', 'text' => '');
  4242. if (defined('SHOW_ONLINE') && !$user->data['is_bot'])
  4243. {
  4244. include(IP_ROOT_PATH . 'includes/users_online_block.' . PHP_EXT);
  4245. }
  4246. // Show Online Block - END
  4247. // CrackerTracker v5.x
  4248. /*
  4249. * CrackerTracker IP Range Scanner
  4250. */
  4251. $marknow = request_var('marknow', '');
  4252. if (($marknow == 'ipfeature') && $user->data['session_logged_in'])
  4253. {
  4254. // Mark IP Feature Read
  4255. $user->data['ct_last_ip'] = $user->data['ct_last_used_ip'];
  4256. $sql = 'UPDATE ' . USERS_TABLE . ' SET ct_last_ip = ct_last_used_ip WHERE user_id=' . $user->data['user_id'];
  4257. $result = $db->sql_query($sql);
  4258. if (!empty($_SERVER['HTTP_REFERER']))
  4259. {
  4260. preg_match('#/([^/]*?)$#', $_SERVER['HTTP_REFERER'], $backlink);
  4261. redirect($backlink[1]);
  4262. }
  4263. }
  4264. if (($config['ctracker_login_ip_check'] == 1) && ($user->data['ct_enable_ip_warn'] == 1) && $user->data['session_logged_in'])
  4265. {
  4266. include_once(IP_ROOT_PATH . 'includes/ctracker/classes/class_ct_userfunctions.' . PHP_EXT);
  4267. $ctracker_user = new ct_userfunctions();
  4268. $check_ip_range = $ctracker_user->check_ip_range();
  4269. if ($check_ip_range != 'allclear')
  4270. {
  4271. $template->assign_block_vars('ctracker_message', array(
  4272. 'ROW_COLOR' => 'ffdfdf',
  4273. 'ICON_GLOB' => $images['ctracker_note'],
  4274. 'L_MESSAGE_TEXT' => $check_ip_range,
  4275. 'L_MARK_MESSAGE' => $lang['ctracker_gmb_markip'],
  4276. 'U_MARK_MESSAGE' => append_sid('index.' . PHP_EXT . '?marknow=ipfeature')
  4277. )
  4278. );
  4279. }
  4280. }
  4281. /*
  4282. * CrackerTracker Global Message Function
  4283. */
  4284. if (($marknow == 'globmsg') && $user->data['session_logged_in'])
  4285. {
  4286. // Mark Global Message as read
  4287. $user->data['ct_global_msg_read'] = 0;
  4288. $sql = 'UPDATE ' . USERS_TABLE . ' SET ct_global_msg_read = 0 WHERE user_id=' . $user->data['user_id'];
  4289. $result = $db->sql_query($sql);
  4290. if (!empty($_SERVER['HTTP_REFERER']))
  4291. {
  4292. preg_match('#/([^/]*?)$#', $_SERVER['HTTP_REFERER'], $backlink);
  4293. redirect($backlink[1]);
  4294. }
  4295. }
  4296. if (($user->data['ct_global_msg_read'] == 1) && $user->data['session_logged_in'] && ($config['ctracker_global_message'] != ''))
  4297. {
  4298. // Output Global Message
  4299. $global_message_output = '';
  4300. if ($config['ctracker_global_message_type'] == 1)
  4301. {
  4302. $global_message_output = $config['ctracker_global_message'];
  4303. }
  4304. else
  4305. {
  4306. $global_message_output = sprintf($lang['ctracker_gmb_link'], $config['ctracker_global_message'], $config['ctracker_global_message']);
  4307. }
  4308. $template->assign_block_vars('ctracker_message', array(
  4309. 'ROW_COLOR' => 'e1ffdf',
  4310. 'ICON_GLOB' => $images['ctracker_note'],
  4311. 'L_MESSAGE_TEXT' => $global_message_output,
  4312. 'L_MARK_MESSAGE' => $lang['ctracker_gmb_mark'],
  4313. 'U_MARK_MESSAGE' => append_sid('index.' . PHP_EXT . '?marknow=globmsg')
  4314. )
  4315. );
  4316. }
  4317. if (((($config['login_history'] == 1) || ($config['login_ip_check'] == 1)) && ($user->data['session_logged_in'])))
  4318. {
  4319. $template->assign_block_vars('login_sec_link', array());
  4320. }
  4321. /*
  4322. * CrackerTracker Password Expiry Check
  4323. */
  4324. if ($user->data['session_logged_in'] && ($config['ctracker_pw_control'] == 1))
  4325. {
  4326. $pwd_expiry_time = $user->data['user_passchg'] + (!empty($config['ctracker_pw_validity']) ? (int) $config['ctracker_pw_validity'] : 365) * 24 * 60 * 60;
  4327. if (time() > $pwd_expiry_time)
  4328. {
  4329. $template->assign_block_vars('ctracker_message', array(
  4330. 'ROW_COLOR' => 'ffdfdf',
  4331. 'ICON_GLOB' => $images['ctracker_note'],
  4332. 'L_MESSAGE_TEXT' => sprintf($lang['ctracker_info_pw_expired'], $config['ctracker_pw_validity'], $user->data['user_id']),
  4333. 'L_MARK_MESSAGE' => '',
  4334. 'U_MARK_MESSAGE' => ''
  4335. )
  4336. );
  4337. }
  4338. }
  4339. /*
  4340. * CrackerTracker Debug Mode Check
  4341. */
  4342. if (defined('CT_DEBUG_MODE') && (CT_DEBUG_MODE === true) && ($user->data['user_level'] == ADMIN))
  4343. {
  4344. $template->assign_block_vars('ctracker_message', array(
  4345. 'ROW_COLOR' => 'ffdfdf',
  4346. 'ICON_GLOB' => $images['ctracker_note'],
  4347. 'L_MESSAGE_TEXT' => $lang['ctracker_dbg_mode'],
  4348. 'L_MARK_MESSAGE' => '',
  4349. 'U_MARK_MESSAGE' => ''
  4350. )
  4351. );
  4352. }
  4353. // CrackerTracker v5.x
  4354. if ($config['switch_header_table'])
  4355. {
  4356. $template->assign_block_vars('switch_header_table', array(
  4357. 'HEADER_TEXT' => $config['header_table_text'],
  4358. 'L_STAFF_MESSAGE' => $lang['staff_message'],
  4359. )
  4360. );
  4361. }
  4362. if ($config['show_calendar_box_index'])
  4363. {
  4364. $path_parts = pathinfo($_SERVER['SCRIPT_NAME']);
  4365. if ($path_parts['basename'] != CMS_PAGE_LOGIN)
  4366. {
  4367. if (!defined('IN_CALENDAR'))
  4368. {
  4369. if (intval($config['calendar_header_cells']) > 0)
  4370. {
  4371. $template->assign_block_vars('switch_calendar_box', array());
  4372. include_once(IP_ROOT_PATH . 'includes/functions_calendar.' . PHP_EXT);
  4373. display_calendar('CALENDAR_BOX', intval($config['calendar_header_cells']));
  4374. }
  4375. }
  4376. }
  4377. }
  4378. $top_html_block_text = get_ad('glt');
  4379. $header_banner_text = get_ad('glh');
  4380. $nav_menu_ads_top = get_ad('nmt');
  4381. $nav_menu_ads_bottom = get_ad('nmb');
  4382. $social_connect_buttons = '';
  4383. if (!empty($config['enable_social_connect']))
  4384. {
  4385. include_once(IP_ROOT_PATH . 'includes/class_social_connect.' . PHP_EXT);
  4386. $available_networks = SocialConnect::get_available_networks();
  4387. foreach ($available_networks as $social_network)
  4388. {
  4389. $social_connect_url = append_sid(CMS_PAGE_LOGIN . '?social_network=' . $social_network->get_name_clean());
  4390. $social_connect_img = '<img src="' . IP_ROOT_PATH . 'images/social_connect/' . $social_network->get_name_clean() . '_button_connect.png" alt="" title="' . $social_network->get_name() . '" />';
  4391. $social_connect_buttons .= '<a href="' . $social_connect_url . '">' . $social_connect_img . '</a>';
  4392. }
  4393. }
  4394. // The following assigns all _common_ variables that may be used at any point in a template.
  4395. $template->assign_vars(array(
  4396. 'TOTAL_USERS_ONLINE' => $l_online_users,
  4397. 'LOGGED_IN_USER_LIST' => $online_userlist,
  4398. 'BOT_LIST' => !empty($online_botlist) ? $online_botlist : '',
  4399. 'AC_LIST_TEXT' => $ac_online_users['text'],
  4400. 'AC_LIST' => $ac_online_users['list'],
  4401. 'RECORD_USERS' => sprintf($lang['Record_online_users'], $config['record_online_users'], create_date($config['default_dateformat'], $config['record_online_date'], $config['board_timezone'])),
  4402. 'TOP_HTML_BLOCK' => $top_html_block_text,
  4403. 'S_HEADER_BANNER' => (empty($header_banner_text) ? false : true),
  4404. 'HEADER_BANNER_CODE' => $header_banner_text,
  4405. 'NAV_MENU_ADS_TOP' => $nav_menu_ads_top,
  4406. 'NAV_MENU_ADS_BOTTOM' => $nav_menu_ads_bottom,
  4407. 'L_SEARCH_NEW' => $lang['Search_new'],
  4408. 'L_SEARCH_NEW2' => $lang['Search_new2'],
  4409. 'L_NEW' => $lang['New'],
  4410. 'L_NEW2' => (empty($lang['NEW_POSTS_SHORT']) ? $lang['New_Label'] : $lang['NEW_POSTS_SHORT']),
  4411. 'L_NEW3' => (empty($lang['NEW_POSTS_LONG']) ? $lang['New_Messages_Label'] : $lang['NEW_POSTS_LONG']),
  4412. 'L_POSTS' => $lang['Posts'],
  4413. // UPI2DB - BEGIN
  4414. 'L_DISPLAY_ALL' => (!empty($u_display_new) ? $u_display_new['all'] : ''),
  4415. 'L_DISPLAY_U' => (!empty($u_display_new) ? $u_display_new['u'] : ''),
  4416. 'L_DISPLAY_M' => (!empty($u_display_new) ? $u_display_new['m'] : ''),
  4417. 'L_DISPLAY_P' => (!empty($u_display_new) ? $u_display_new['p'] : ''),
  4418. 'L_DISPLAY_UNREAD' => (!empty($u_display_new) ? $u_display_new['unread'] : ''),
  4419. 'L_DISPLAY_MARKED' => (!empty($u_display_new) ? $u_display_new['marked'] : ''),
  4420. 'L_DISPLAY_PERMANENT' => (!empty($u_display_new) ? $u_display_new['permanent'] : ''),
  4421. 'L_DISPLAY_U_S' => (!empty($u_display_new) ? $u_display_new['u_string_full'] : ''),
  4422. 'L_DISPLAY_M_S' => (!empty($u_display_new) ? $u_display_new['m_string_full'] : ''),
  4423. 'L_DISPLAY_P_S' => (!empty($u_display_new) ? $u_display_new['p_string_full'] : ''),
  4424. 'L_DISPLAY_UNREAD_S' => (!empty($u_display_new) ? $u_display_new['unread_string'] : ''),
  4425. 'L_DISPLAY_MARKED_S' => (!empty($u_display_new) ? $u_display_new['marked_string'] : ''),
  4426. 'L_DISPLAY_PERMANENT_S' => (!empty($u_display_new) ? $u_display_new['permanent_string'] : ''),
  4427. 'UPI2DB_U_COUNTER' => (!empty($u_display_new) ? $u_display_new['counter_unread'] : 0),
  4428. 'UPI2DB_M_COUNTER' => (!empty($u_display_new) ? $u_display_new['counter_marked'] : 0),
  4429. 'UPI2DB_P_COUNTER' => (!empty($u_display_new) ? $u_display_new['counter_permanent'] : 0),
  4430. 'U_DISPLAY_U' => (!empty($u_display_new) ? $u_display_new['u_url'] : ''),
  4431. 'U_DISPLAY_M' => (!empty($u_display_new) ? $u_display_new['m_url'] : ''),
  4432. 'U_DISPLAY_P' => (!empty($u_display_new) ? $u_display_new['p_url'] : ''),
  4433. // UPI2DB - END
  4434. 'L_SEARCH_UNANSWERED' => $lang['Search_unanswered'],
  4435. 'L_SEARCH_SELF' => $lang['Search_your_posts'],
  4436. 'L_RECENT' => $lang['Recent_topics'],
  4437. 'L_WATCHED_TOPICS' => $lang['Watched_Topics'],
  4438. 'L_BOOKMARKS' => $lang['Bookmarks'],
  4439. 'L_DIGESTS' => $lang['DIGESTS'],
  4440. 'L_DRAFTS' => $lang['Drafts'],
  4441. // Mighty Gorgon - Random Quote - Begin
  4442. 'RANDOM_QUOTE' => $randomquote_phrase,
  4443. // Mighty Gorgon - Random Quote - End
  4444. // CrackerTracker v5.x
  4445. 'L_LOGIN_SEC' => $lang['ctracker_gmb_loginlink'],
  4446. 'U_LOGIN_SEC' => append_sid('ct_login_history.' . PHP_EXT),
  4447. // CrackerTracker v5.x
  4448. // Mighty Gorgon - CPL - BEGIN
  4449. 'L_VIEWER' => $lang['Username'],
  4450. 'L_NUMBER' => $lang['Views'],
  4451. 'L_STAMP' => $lang['Last_updated'],
  4452. 'L_YOUR_ACTIVITY' => $lang['Cpl_Personal_Profile'],
  4453. 'L_PROFILE_EXPLAIN' => $lang['profile_explain'],
  4454. 'L_PROFILE_MAIN' => $lang['profile_main'],
  4455. 'L_CPL_NAV' => $lang['Profile'],
  4456. 'L_CPL_REG_INFO' => $lang['Registration_info'],
  4457. 'L_CPL_DELETE_ACCOUNT' => $lang['Delete_My_Account'],
  4458. 'L_CPL_PROFILE_INFO' => $lang['Profile_info'],
  4459. 'L_CPL_PROFILE_VIEWED' => $lang['Profile_viewed'],
  4460. 'L_CPL_AVATAR_PANEL' => $lang['Avatar_panel'],
  4461. 'L_CPL_SIG_EDIT' => $lang['sig_edit_link'],
  4462. 'L_CPL_PREFERENCES' => $lang['Preferences'],
  4463. 'L_CPL_SETTINGS_OPTIONS' => $lang['Cpl_Settings_Options'],
  4464. 'L_CPL_BOARD_SETTINGS' => $lang['Cpl_Board_Settings'],
  4465. 'L_CPL_MORE_INFO' => $lang['Cpl_More_info'],
  4466. 'L_CPL_NEWMSG' => $lang['Cpl_NewMSG'],
  4467. 'L_CPL_PERSONAL_PROFILE' => $lang['Cpl_Personal_Profile'],
  4468. 'L_CPL_OWN_POSTS' => $lang['Search_your_posts'],
  4469. 'L_CPL_OWN_PICTURES' => $lang['Personal_Gallery'],
  4470. 'L_CPL_BOOKMARKS' => $lang['Bookmarks'],
  4471. 'L_CPL_SUBSCFORUMS' => $lang['UCP_SubscForums'],
  4472. 'L_CPL_PRIVATE_MESSAGES' => $lang['Private_Messages'],
  4473. 'L_CPL_INBOX' => $lang['Inbox'],
  4474. 'L_CPL_OUTBOX' => $lang['Outbox'],
  4475. 'L_CPL_SAVEBOX' => $lang['Savebox'],
  4476. 'L_CPL_SENTBOX' => $lang['Sentbox'],
  4477. 'L_CPL_DRAFTS' => $lang['Drafts'],
  4478. 'L_CPL_ZEBRA' => $lang['UCP_ZEBRA'],
  4479. 'L_CPL_ZEBRA_EXPLAIN' => $lang['FRIENDS_EXPLAIN'],
  4480. 'U_CPL_PROFILE_VIEWED' => append_sid('profile_view_user.' . PHP_EXT . '?' . POST_USERS_URL . '=' . $user->data['user_id']),
  4481. 'U_CPL_NEWMSG' => append_sid(CMS_PAGE_PRIVMSG . '?mode=post'),
  4482. 'U_CPL_REGISTRATION_INFO' => append_sid(CMS_PAGE_PROFILE . '?mode=editprofile&amp;cpl_mode=reg_info'),
  4483. 'U_CPL_DELETE_ACCOUNT' => append_sid('contact_us.' . PHP_EXT . '?account_delete=' . $user->data['user_id']),
  4484. 'U_CPL_PROFILE_INFO' => append_sid(CMS_PAGE_PROFILE . '?mode=editprofile&amp;cpl_mode=profile_info'),
  4485. 'U_CPL_PREFERENCES' => append_sid(CMS_PAGE_PROFILE . '?mode=editprofile&amp;cpl_mode=preferences'),
  4486. 'U_CPL_BOARD_SETTINGS' => append_sid(CMS_PAGE_PROFILE . '?mode=editprofile&amp;cpl_mode=board_settings'),
  4487. 'U_CPL_AVATAR_PANEL' => append_sid(CMS_PAGE_PROFILE . '?mode=editprofile&amp;cpl_mode=avatar'),
  4488. 'U_CPL_SIGNATURE' => append_sid(CMS_PAGE_PROFILE . '?mode=signature'),
  4489. 'U_CPL_OWN_POSTS' => append_sid(CMS_PAGE_SEARCH. '?search_author=' . urlencode($user->data['username']) . '&amp;showresults=posts'),
  4490. 'U_CPL_OWN_PICTURES' => append_sid('album.' . PHP_EXT . '?user_id=' . $user->data['user_id']),
  4491. 'U_CPL_CALENDAR_SETTINGS' => append_sid('profile_options.' . PHP_EXT . '?sub=preferences&amp;module=calendar_settings&amp;' . POST_USERS_URL . '=' . $user->data['user_id']),
  4492. 'U_CPL_SUBFORUM_SETTINGS' => append_sid('profile_options.' . PHP_EXT . '?sub=preferences&amp;module=forums_settings&amp;' . POST_USERS_URL . '=' . $user->data['user_id']),
  4493. 'U_CPL_SUBSCFORUMS' => append_sid('subsc_forums.' . PHP_EXT),
  4494. 'U_CPL_BOOKMARKS' => append_sid(CMS_PAGE_SEARCH . '?search_id=bookmarks'),
  4495. 'U_CPL_INBOX' => append_sid(CMS_PAGE_PRIVMSG . '?folder=inbox'),
  4496. 'U_CPL_OUTBOX' => append_sid(CMS_PAGE_PRIVMSG . '?folder=outbox'),
  4497. 'U_CPL_SAVEBOX' => append_sid(CMS_PAGE_PRIVMSG . '?folder=savebox'),
  4498. 'U_CPL_SENTBOX' => append_sid(CMS_PAGE_PRIVMSG . '?folder=sentbox'),
  4499. 'U_CPL_DRAFTS' => append_sid('drafts.' . PHP_EXT),
  4500. 'U_CPL_ZEBRA' => append_sid(CMS_PAGE_PROFILE . '?mode=zebra&amp;zmode=friends'),
  4501. // Mighty Gorgon - CPL - END
  4502. 'SOCIAL_CONNECT_BUTTONS' => $social_connect_buttons,
  4503. // Activity - BEGIN
  4504. /*
  4505. 'L_WHOSONLINE_GAMES' => '<a href="'. append_sid('activity.' . PHP_EXT) .'"><span style="color:#'. str_replace('#', '', $config['ina_online_list_color']) . ';">' . $config['ina_online_list_text'] . '</span></a>',
  4506. */
  4507. 'P_ACTIVITY_MOD_PATH' => PLUGINS_PATH . $config['plugins']['activity']['dir'],
  4508. 'U_ACTIVITY' => append_sid('activity.' . PHP_EXT),
  4509. 'L_ACTIVITY' => $lang['Activity'],
  4510. // Activity - END
  4511. )
  4512. );
  4513. }
  4514. foreach ($config['plugins'] as $plugin_name => $plugin_config)
  4515. {
  4516. if ($plugin_config['enabled'])
  4517. {
  4518. $template->assign_var('PLUGIN_' . strtoupper($plugin_name), true);
  4519. $template->assign_block_vars('plugins', array(
  4520. 'NAME' => $plugin_name,
  4521. )
  4522. );
  4523. }
  4524. }
  4525. // The following assigns all _common_ variables that may be used at any point in a template.
  4526. $current_time = create_date($config['default_dateformat'], time(), $config['board_timezone']);
  4527. $template->assign_vars(array(
  4528. 'DOCTYPE_HTML' => $doctype_html,
  4529. 'HEADER_LANG' => $header_lang,
  4530. 'NAV_LINKS' => $nav_links_html,
  4531. 'S_HIGHSLIDE' => (!empty($config['thumbnail_highslide']) ? true : false),
  4532. 'S_COOKIE_LAW' => (!empty($config['cookie_law']) ? true : false),
  4533. // AJAX Features - BEGIN
  4534. 'S_AJAX_FEATURES' => (!empty($config['ajax_features']) ? true : false),
  4535. 'S_AJAX_USER_CHECK' => $ajax_user_check,
  4536. 'S_AJAX_USER_CHECK_ALT' => $ajax_user_check_alt,
  4537. // AJAX Features - END
  4538. 'U_LOGIN_LOGOUT' => append_sid(IP_ROOT_PATH . $u_login_logout),
  4539. 'USER_USERNAME' => $user->data['session_logged_in'] ? htmlspecialchars($user->data['username']) : $lang['Guest'],
  4540. // UPI2DB - BEGIN
  4541. 'UPI2DB_FIRST_USE' => $upi2db_first_use,
  4542. // UPI2DB - END
  4543. 'L_PAGE_TITLE' => $meta_content['page_title_clean'],
  4544. 'PAGE_TITLE' => ($config['page_title_simple'] ? $meta_content['page_title_clean'] : $meta_content['page_title']),
  4545. 'META_TAG' => $phpbb_meta,
  4546. 'LAST_VISIT_DATE' => sprintf($lang['You_last_visit'], $s_last_visit),
  4547. 'CURRENT_TIME' => sprintf($lang['Current_time'], $current_time),
  4548. 'CURRENT_TIME_ONLY' => $current_time,
  4549. 'S_TIMEZONE' => $time_message,
  4550. 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text,
  4551. 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
  4552. 'PRIVATE_MESSAGE_NEW_FLAG' => $s_privmsg_new,
  4553. 'PRIVMSG_IMG' => $icon_pm,
  4554. 'NEW_PM_SWITCH' => $new_pm_switch,
  4555. 'PRIVATE_CHAT_IMG' => $icon_private_chat,
  4556. 'U_PRIVATE_CHAT' => $u_private_chat,
  4557. 'NEW_PRIVATE_CHAT_SWITCH' => $new_private_chat_switch,
  4558. 'L_USERNAME' => $lang['Username'],
  4559. 'L_PASSWORD' => $lang['Password'],
  4560. 'L_LOGIN_LOGOUT' => $l_login_logout,
  4561. 'L_LOGIN_LOGOUT2' => $l_login_logout2,
  4562. 'L_LOGIN' => $lang['Login'],
  4563. 'L_HOME' => $lang['Home'],
  4564. 'L_INDEX' => sprintf($lang['Forum_Index'], $config['sitename']),
  4565. 'L_REGISTER' => $lang['Register'],
  4566. 'L_BOARDRULES' => $lang['BoardRules'],
  4567. 'L_PROFILE' => $lang['Profile'],
  4568. 'L_CPL_NAV' => $lang['Profile'],
  4569. 'L_SEARCH' => $lang['Search'],
  4570. 'L_PRIVATEMSGS' => $lang['Private_Messages'],
  4571. 'L_WHO_IS_ONLINE' => $lang['Who_is_Online'],
  4572. 'L_MEMBERLIST' => $lang['Memberlist'],
  4573. 'L_FAQ' => $lang['FAQ'],
  4574. 'L_ADV_SEARCH' => $lang['Adv_Search'],
  4575. 'L_SEARCH_EXPLAIN' => $lang['Search_Explain'],
  4576. 'L_KB' => $lang['KB_title'],
  4577. 'L_NEWS' => $lang['News_Cmx'],
  4578. 'L_USERGROUPS' => $lang['Usergroups'],
  4579. 'L_BOARD_DISABLE' => $lang['Board_disabled'],
  4580. // Ajax Shoutbox - BEGIN
  4581. 'L_AJAX_SHOUTBOX' => $lang['Ajax_Chat'],
  4582. // Ajax Shoutbox - END
  4583. 'L_BACK_TOP' => $lang['Back_to_top'],
  4584. 'L_BACK_BOTTOM' => $lang['Back_to_bottom'],
  4585. // Mighty Gorgon - Nav Links - BEGIN
  4586. 'L_CALENDAR' => $lang['Calendar'],
  4587. 'L_DOWNLOADS' => $lang['Downloads'],
  4588. 'L_DOWNLOADS_ADV' => $lang['Downloads_ADV'],
  4589. 'L_HACKS_LIST' => $lang['Hacks_List'],
  4590. 'L_AVATAR_GEN' => $lang['AvatarGenerator'],
  4591. 'L_LINKS' => $lang['Links'],
  4592. 'L_WORDGRAPH' => $lang['Wordgraph'],
  4593. 'L_ACRONYMS' => $lang['Acronyms'],
  4594. 'L_SITEMAP' => $lang['Sitemap'],
  4595. //'L_' => $lang[''],
  4596. // Mighty Gorgon - Nav Links - END
  4597. // Mighty Gorgon - Multiple Ranks - BEGIN
  4598. 'L_RANKS' => $lang['Rank_Header'],
  4599. 'L_STAFF' => $lang['Staff'],
  4600. // Mighty Gorgon - Multiple Ranks - END
  4601. //'U_STAFF' => append_sid('staff.' . PHP_EXT),
  4602. 'L_CONTACT_US' => $lang['Contact_us'],
  4603. 'L_UPLOAD_IMAGE' => $lang['Upload_Image_Local'],
  4604. 'L_UPLOADED_IMAGES' => $lang['Uploaded_Images_Local'],
  4605. // Mighty Gorgon - Full Album Pack - BEGIN
  4606. 'L_ALBUM' => $lang['Album'],
  4607. 'L_PIC_NAME' => $lang['Pic_Name'],
  4608. 'L_DESCRIPTION' => $lang['Description'],
  4609. 'L_GO' => $lang['Go'],
  4610. 'L_SEARCH_CONTENTS' => $lang['Search_Contents'],
  4611. 'L_SEARCH_MATCHES' => $lang['Search_Matches'],
  4612. // Mighty Gorgon - Full Album Pack - END
  4613. 'U_PREFERENCES' => append_sid('profile_options.' . PHP_EXT),
  4614. 'L_PREFERENCES' => $lang['Preferences'],
  4615. )
  4616. );
  4617. // get the nav sentence
  4618. $nav_key = '';
  4619. $nav_key = (!empty($meta_content['cat_id']) ? (POST_CAT_URL . $meta_content['cat_id']) : $nav_key);
  4620. $nav_key = (!empty($meta_content['forum_id']) ? (POST_FORUM_URL . $meta_content['forum_id']) : $nav_key);
  4621. $nav_key = (!empty($meta_content['topic_id']) ? (POST_TOPIC_URL . $meta_content['topic_id']) : $nav_key);
  4622. $nav_key = (!empty($meta_content['post_id']) ? (POST_POST_URL . $meta_content['post_id']) : $nav_key);
  4623. if (empty($nav_key))
  4624. {
  4625. $selected_id = request_var('selected_id', 0);
  4626. $nav_key = ($selected_id < 0) ? 0 : $selected_id;
  4627. $nav_key = empty($nav_key) ? 'Root' : $nav_key;
  4628. }
  4629. $nav_separator = empty($nav_separator) ? (empty($lang['Nav_Separator']) ? '&nbsp;&raquo;&nbsp;' : $lang['Nav_Separator']) : $nav_separator;
  4630. $nav_cat_desc = '';
  4631. if (!isset($skip_nav_cat))
  4632. {
  4633. $nav_pgm = empty($nav_pgm) ? '' : $nav_pgm;
  4634. $nav_cat_desc = make_cat_nav_tree($nav_key, $nav_pgm, $meta_content);
  4635. }
  4636. if (!empty($nav_cat_desc))
  4637. {
  4638. $nav_server_url = create_server_url();
  4639. $nav_cat_desc = $nav_separator . $nav_cat_desc;
  4640. $breadcrumbs['address'] = $nav_separator . '<a href="' . $nav_server_url . append_sid(CMS_PAGE_FORUM) . '">' . $lang['Forum'] . '</a>' . $nav_cat_desc;
  4641. if (isset($nav_add_page_title) && ($nav_add_page_title == true))
  4642. {
  4643. $breadcrumbs['address'] = $breadcrumbs['address'] . $nav_separator . '<a href="#" class="nav-current">' . $meta_content['page_title'] . '</a>';
  4644. }
  4645. }
  4646. // send to template
  4647. $template->assign_vars(array(
  4648. //'SPACER' => $images['spacer'],
  4649. 'S_PAGE_NAV' => (isset($cms_page['page_nav']) ? $cms_page['page_nav'] : true),
  4650. 'NAV_SEPARATOR' => $nav_separator,
  4651. 'NAV_CAT_DESC' => $nav_cat_desc,
  4652. 'BREADCRUMBS_ADDRESS' => (empty($breadcrumbs['address']) ? (($meta_content['page_title_clean'] != $config['sitename']) ? ($lang['Nav_Separator'] . '<a href="#" class="nav-current">' . $meta_content['page_title_clean'] . '</a>') : '') : $breadcrumbs['address']),
  4653. 'S_BREADCRUMBS_BOTTOM_LEFT_LINKS' => (empty($breadcrumbs['bottom_left_links']) ? false : true),
  4654. 'BREADCRUMBS_BOTTOM_LEFT_LINKS' => (empty($breadcrumbs['bottom_left_links']) ? '&nbsp;' : $breadcrumbs['bottom_left_links']),
  4655. 'S_BREADCRUMBS_BOTTOM_RIGHT_LINKS' => (empty($breadcrumbs['bottom_right_links']) ? false : true),
  4656. 'BREADCRUMBS_BOTTOM_RIGHT_LINKS' => (empty($breadcrumbs['bottom_right_links']) ? '&nbsp;' : $breadcrumbs['bottom_right_links']),
  4657. )
  4658. );
  4659. if ($config['board_disable'] && ($user->data['user_level'] == ADMIN))
  4660. {
  4661. $template->assign_block_vars('switch_admin_disable_board', array());
  4662. }
  4663. if (!defined('IN_CMS'))
  4664. {
  4665. $cms_page['global_blocks'] = (empty($cms_page['global_blocks']) ? false : true);
  4666. //$cms_page['global_blocks'] = ((!isset($cms_page['page_id']) || !$cms_page['global_blocks']) ? false : true);
  4667. $cms_page_blocks = ((empty($cms_page['page_id']) || empty($cms_config_layouts[$cms_page['page_id']])) ? false : true);
  4668. if(empty($gen_simple_header) && !defined('HAS_DIED') && !defined('IN_LOGIN') && ($cms_page['global_blocks'] || $cms_page_blocks) && (!$config['board_disable'] || ($user->data['user_level'] == ADMIN)))
  4669. {
  4670. $template->assign_var('SWITCH_CMS_GLOBAL_BLOCKS', true);
  4671. $ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'header');
  4672. if ($ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'headerleft'))
  4673. {
  4674. $template->assign_vars(array(
  4675. 'HEADER_WIDTH' => $cms_config_vars['header_width'],
  4676. 'HL_BLOCK' => true,
  4677. )
  4678. );
  4679. }
  4680. if ($ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'headercenter'))
  4681. {
  4682. $template->assign_var('HC_BLOCK', true);
  4683. }
  4684. }
  4685. if(empty($gen_simple_header))
  4686. {
  4687. if ($ip_cms->cms_parse_blocks(0, true, true, 'gheader'))
  4688. {
  4689. $template->assign_var('GH_BLOCK', true);
  4690. }
  4691. if ($ip_cms->cms_parse_blocks(0, true, true, 'ghtop'))
  4692. {
  4693. $template->assign_var('GT_BLOCK', true);
  4694. }
  4695. if ($ip_cms->cms_parse_blocks(0, true, true, 'ghbottom'))
  4696. {
  4697. $template->assign_var('GB_BLOCK', true);
  4698. }
  4699. if ($ip_cms->cms_parse_blocks(0, true, true, 'ghleft'))
  4700. {
  4701. $template->assign_var('GL_BLOCK', true);
  4702. }
  4703. if ($ip_cms->cms_parse_blocks(0, true, true, 'ghright'))
  4704. {
  4705. $template->assign_var('GR_BLOCK', true);
  4706. }
  4707. }
  4708. if (defined('PARSE_CPL_NAV'))
  4709. {
  4710. $template->set_filenames(array('cpl_menu_output' => 'profile_cpl_menu.tpl'));
  4711. $template->assign_var_from_handle('CPL_MENU_OUTPUT', 'cpl_menu_output');
  4712. }
  4713. }
  4714. if (($user->data['user_level'] != ADMIN) && $config['board_disable'] && !defined('HAS_DIED') && !defined('IN_ADMIN') && !defined('IN_LOGIN'))
  4715. {
  4716. if (!defined('STATUS_503')) define('STATUS_503', true);
  4717. if($config['board_disable_mess_st'])
  4718. {
  4719. message_die(GENERAL_MESSAGE, $config['board_disable_message']);
  4720. }
  4721. else
  4722. {
  4723. message_die(GENERAL_MESSAGE, $lang['Board_disabled']);
  4724. }
  4725. }
  4726. if (!defined('AJAX_HEADERS'))
  4727. {
  4728. // application/xhtml+xml not used because of IE
  4729. $encoding_charset = !empty($lang['ENCODING']) ? $lang['ENCODING'] : 'UTF-8';
  4730. header('Content-type: text/html; charset=' . $encoding_charset);
  4731. header('Cache-Control: private, no-cache="set-cookie"');
  4732. header('Expires: 0');
  4733. header('Pragma: no-cache');
  4734. }
  4735. if ($parse_template)
  4736. {
  4737. $header_tpl = empty($gen_simple_header) ? 'overall_header.tpl' : 'simple_header.tpl';
  4738. $template->set_filenames(array('overall_header' => $header_tpl));
  4739. $template->pparse('overall_header');
  4740. }
  4741. define('HEADER_INC_COMPLETED', true);
  4742. return;
  4743. }
  4744. /**
  4745. * Page Footer
  4746. */
  4747. function page_footer($exit = true, $template_to_parse = 'body', $parse_template = false)
  4748. {
  4749. global $db, $cache, $config, $user, $template, $images, $theme, $lang, $tree;
  4750. global $table_prefix, $SID, $_SID;
  4751. global $ip_cms, $cms_config_vars, $cms_config_global_blocks, $cms_config_layouts, $cms_page;
  4752. global $starttime, $base_memory_usage, $do_gzip_compress, $start;
  4753. global $gen_simple_header, $meta_content, $nav_separator, $nav_links, $nav_pgm, $nav_add_page_title, $skip_nav_cat;
  4754. global $breadcrumbs;
  4755. global $cms_acp_url;
  4756. $config['gzip_compress_runtime'] = (isset($config['gzip_compress_runtime']) ? $config['gzip_compress_runtime'] : $config['gzip_compress']);
  4757. $config['url_rw_runtime'] = (isset($config['url_rw_runtime']) ? $config['url_rw_runtime'] : (($config['url_rw'] || ($config['url_rw_guests'] && ($user->data['user_id'] == ANONYMOUS))) ? true : false));
  4758. if (!defined('IN_CMS'))
  4759. {
  4760. $cms_page['global_blocks'] = (empty($cms_page['global_blocks']) ? false : true);
  4761. //$cms_page['global_blocks'] = ((!isset($cms_page['page_id']) || !$cms_page['global_blocks']) ? false : true);
  4762. $cms_page_blocks = ((empty($cms_page['page_id']) || empty($cms_config_layouts[$cms_page['page_id']])) ? false : true);
  4763. if(empty($gen_simple_header) && !defined('HAS_DIED') && !defined('IN_LOGIN') && ($cms_page['global_blocks'] || $cms_page_blocks) && (!$config['board_disable'] || ($user->data['user_level'] == ADMIN)))
  4764. {
  4765. $template->assign_var('SWITCH_CMS_GLOBAL_BLOCKS', true);
  4766. if ($ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'tailcenter'))
  4767. {
  4768. $template->assign_var('TC_BLOCK', true);
  4769. }
  4770. if ($ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'tailright'))
  4771. {
  4772. $template->assign_vars(array(
  4773. 'FOOTER_WIDTH' => $cms_config_vars['footer_width'],
  4774. 'TR_BLOCK' => true,
  4775. )
  4776. );
  4777. }
  4778. $ip_cms->cms_parse_blocks($cms_page['page_id'], !empty($cms_page['page_id']), $cms_page['global_blocks'], 'tail');
  4779. /*
  4780. */
  4781. }
  4782. if(empty($gen_simple_header))
  4783. {
  4784. if ($ip_cms->cms_parse_blocks(0, true, true, 'gfooter'))
  4785. {
  4786. $template->assign_var('GF_BLOCK', true);
  4787. }
  4788. }
  4789. $bottom_html_block_text = get_ad('glb');
  4790. $footer_banner_text = get_ad('glf');
  4791. // CrackerTracker v5.x
  4792. /*
  4793. include_once(IP_ROOT_PATH . 'includes/ctracker/engines/ct_footer.' . PHP_EXT);
  4794. $output_login_status = ($user->data['ct_enable_ip_warn'] ? $lang['ctracker_ma_on'] : $lang['ctracker_ma_off']);
  4795. $template->assign_vars(array(
  4796. 'CRACKER_TRACKER_FOOTER' => create_footer_layout($config['ctracker_footer_layout']),
  4797. 'L_STATUS_LOGIN' => ($config['ctracker_login_ip_check'] ? sprintf($lang['ctracker_ipwarn_info'], $output_login_status) : ''),
  4798. )
  4799. );
  4800. */
  4801. // CrackerTracker v5.x
  4802. }
  4803. include_once(IP_ROOT_PATH . 'includes/functions_jr_admin.' . PHP_EXT);
  4804. $admin_link = jr_admin_make_admin_link();
  4805. //Begin Lo-Fi Mod
  4806. $path_parts = pathinfo($_SERVER['SCRIPT_NAME']);
  4807. $lofi = '<a href="' . append_sid(IP_ROOT_PATH . $path_parts['basename'] . '?' . htmlspecialchars(str_replace(array('&lofi=0', '&lofi=1', 'lofi=0', 'lofi=1'), array('', '', '', ''), $_SERVER['QUERY_STRING'])) . '&amp;lofi=' . (empty($_COOKIE[$config['cookie_name'] . '_lofi']) ? '1' : '0')) . '">' . (empty($_COOKIE[$config['cookie_name'] . '_lofi']) ? ($lang['Lofi']) : ($lang['Full_Version'])) . '</a>';
  4808. $mobile_style = '<a href="' . append_sid(IP_ROOT_PATH . $path_parts['basename'] . '?' . htmlspecialchars(str_replace(array('&mob=0', '&mob=1', 'mob=0', 'mob=1'), array('', '', '', ''), $_SERVER['QUERY_STRING'])) . '&amp;mob=' . (!empty($_COOKIE[$config['cookie_name'] . '_mob']) ? '0' : '1')) . '">' . (!empty($_COOKIE[$config['cookie_name'] . '_mob']) ? ($lang['MOBILE_STYLE_DISABLE']) : ($lang['MOBILE_STYLE_ENABLE'])) . '</a>';
  4809. $template->assign_vars(array(
  4810. 'L_LOFI' => $lang['Lofi'],
  4811. 'L_FULL_VERSION' => $lang['Full_Version'],
  4812. 'LOFI' => $lofi . ($user->data['is_mobile'] ? ('&nbsp;&bull;&nbsp;' . $mobile_style) : ''),
  4813. 'MOBILE_STYLE' => $mobile_style
  4814. )
  4815. );
  4816. //End Lo-Fi Mod
  4817. $template->assign_vars(array(
  4818. 'TRANSLATION_INFO' => ((isset($lang['TRANSLATION_INFO'])) && ($lang['TRANSLATION_INFO'] != '')) ? ('<br />&nbsp;' . $lang['TRANSLATION_INFO']) : (((isset($lang['TRANSLATION'])) && ($lang['TRANSLATION'] != '')) ? ('<br />&nbsp;' . $lang['TRANSLATION']) : ''),
  4819. 'BOTTOM_HTML_BLOCK' => $bottom_html_block_text,
  4820. 'FOOTER_BANNER_BLOCK' => $footer_banner_text,
  4821. 'GOOGLE_ANALYTICS' => $config['google_analytics'],
  4822. 'CMS_ACP' => (!empty($cms_acp_url) ? $cms_acp_url : ''),
  4823. 'ADMIN_LINK' => $admin_link
  4824. )
  4825. );
  4826. // Mighty Gorgon - CRON - BEGIN
  4827. if ($config['cron_global_switch'] && !defined('IN_CRON') && !defined('IN_ADMIN') && !defined('IN_CMS') && empty($config['board_disable']))
  4828. {
  4829. $cron_time = time();
  4830. $cron_append = '';
  4831. $cron_types = array('files', 'database', 'cache', 'sql', 'users', 'topics', 'sessions');
  4832. for ($i = 0; $i < sizeof($cron_types); $i++)
  4833. {
  4834. $cron_trigger = $cron_time - $config['cron_' . $cron_types[$i] . '_interval'];
  4835. if (($config['cron_' . $cron_types[$i] . '_interval'] > 0) && ($cron_trigger > $config['cron_' . $cron_types[$i] . '_last_run']))
  4836. {
  4837. $cron_append .= (empty($cron_append) ? '?' : '&amp;') . $cron_types[$i] . '=1';
  4838. }
  4839. }
  4840. // We can force hours crons as all checks are performed by the function
  4841. $hour_cron_types = array('digests', 'birthdays');
  4842. $cur_time = @getdate();
  4843. foreach ($hour_cron_types as $hour_cron_type)
  4844. {
  4845. $config['cron_' . $hour_cron_type . '_last_run'] = !empty($config['cron_' . $hour_cron_type . '_last_run']) ? $config['cron_' . $hour_cron_type . '_last_run'] : (time() - 3600);
  4846. $last_send_time = @getdate($config['cron_' . $hour_cron_type . '_last_run']);
  4847. if (!empty($config['cron_' . $hour_cron_type . '_interval']) && ($config['cron_' . $hour_cron_type . '_interval'] > 0) && ($cur_time['hours'] != $last_send_time['hours']))
  4848. {
  4849. $cron_append .= (empty($cron_append) ? '?' : '&amp;') . $hour_cron_type . '=1';
  4850. }
  4851. }
  4852. if (!empty($cron_append))
  4853. {
  4854. $template->assign_var('RUN_CRON_TASK', '<img src="' . append_sid(IP_ROOT_PATH . 'cron.' . PHP_EXT . $cron_append) . '" width="1" height="1" alt="cron" />');
  4855. }
  4856. }
  4857. // Mighty Gorgon - CRON - END
  4858. if ($config['page_gen'])
  4859. {
  4860. // Page generation time - BEGIN
  4861. /* Set $page_gen_allowed to FALSE if you want only Admins to view page generation info */
  4862. $page_gen_allowed = true;
  4863. if (($user->data['user_level'] == ADMIN) || $page_gen_allowed)
  4864. {
  4865. $gzip_text = ($config['gzip_compress_runtime']) ? 'GZIP ' . $lang['Enabled']: 'GZIP ' . $lang['Disabled'];
  4866. $debug_text = (DEBUG == true) ? $lang['Debug_On'] : $lang['Debug_Off'];
  4867. $memory_usage_text = '';
  4868. //$excuted_queries = $db->num_queries['total'];
  4869. $excuted_queries = $db->num_queries['normal'];
  4870. $endtime = explode(' ', microtime());
  4871. $endtime = $endtime[1] + $endtime[0];
  4872. $gentime = round(($endtime - $starttime), 4); // You can adjust the number 6
  4873. $sql_time = round($db->sql_time, 4);
  4874. $sql_part = round($sql_time / $gentime * 100);
  4875. $php_part = 100 - $sql_part;
  4876. // Mighty Gorgon - Extra Debug - BEGIN
  4877. if (defined('DEBUG_EXTRA') && DEBUG_EXTRA && ($user->data['user_level'] == ADMIN))
  4878. {
  4879. if (function_exists('memory_get_usage'))
  4880. {
  4881. if ($memory_usage = memory_get_usage())
  4882. {
  4883. global $base_memory_usage;
  4884. $memory_usage -= $base_memory_usage;
  4885. $memory_usage = ($memory_usage >= 1048576) ? round((round($memory_usage / 1048576 * 100) / 100), 2) . ' ' . 'MB' : (($memory_usage >= 1024) ? round((round($memory_usage / 1024 * 100) / 100), 2) . ' ' . 'KB' : $memory_usage . ' ' . 'BYTES');
  4886. $memory_usage_text = ' - ' . $lang['Memory_Usage'] . ': ' . $memory_usage;
  4887. }
  4888. }
  4889. if (defined('DEBUG_EXTRA') && DEBUG_EXTRA)
  4890. {
  4891. $tmp_query_string = htmlspecialchars(str_replace(array('&explain=1', 'explain=1'), array('', ''), $_SERVER['QUERY_STRING']));
  4892. $gzip_text .= ' - <a href="' . append_sid(IP_ROOT_PATH . $path_parts['basename'] . (!empty($tmp_query_string) ? ('?' . $tmp_query_string . '&amp;explain=1') : '?explain=1')) . '">Extra ' . $lang['Debug_On'] . '</a>';
  4893. }
  4894. }
  4895. //if (defined('DEBUG_EXTRA') && DEBUG_EXTRA && ($user->data['user_level'] == ADMIN))
  4896. if (defined('DEBUG_EXTRA') && DEBUG_EXTRA && !empty($_REQUEST['explain']) && ($user->data['user_level'] == ADMIN) && method_exists($db, 'sql_report'))
  4897. {
  4898. $db->sql_report('display');
  4899. }
  4900. // Mighty Gorgon - Extra Debug - END
  4901. $template->assign_vars(array(
  4902. 'SPACER' => $images['spacer'],
  4903. 'S_GENERATION_TIME' => true,
  4904. 'PAGE_GEN_TIME' => $lang['Page_Generation_Time'] . ':',
  4905. 'GENERATION_TIME' => $gentime,
  4906. 'NUMBER_QUERIES' => $excuted_queries,
  4907. 'MEMORY_USAGE' => $memory_usage_text,
  4908. 'GZIP_TEXT' => $gzip_text,
  4909. 'SQL_QUERIES' => $lang['SQL_Queries'],
  4910. 'SQL_PART' => $sql_part,
  4911. 'PHP_PART' => $php_part,
  4912. 'DEBUG_TEXT' => $debug_text,
  4913. )
  4914. );
  4915. /*
  4916. $gen_log_file = IP_ROOT_PATH . MAIN_CACHE_FOLDER . '/gen_log.txt';
  4917. $fp = fopen ($gen_log_file, "a+");
  4918. fwrite($fp, (!empty($gentime) ? $gentime : '0') . "\t" . (!empty($memory_usage) ? $memory_usage : '0') . "\t" . $user->page['page'] . "\n");
  4919. fclose($fp);
  4920. */
  4921. }
  4922. // Page generation time - END
  4923. }
  4924. // Check for some switches here, in case we have changed/reset these swiches somewhere through the code or CMS blocks!
  4925. $template->assign_vars(array(
  4926. 'S_PRINT_SIZE' => (!empty($config['display_print_size']) ? true : false),
  4927. 'S_JQUERY_UI' => (!empty($config['jquery_ui']) ? true : false),
  4928. 'S_JQUERY_UI_TP' => (!empty($config['jquery_ui_tp']) ? true : false),
  4929. 'S_JQUERY_UI_BA' => (!empty($config['jquery_ui_ba']) ? true : false),
  4930. 'S_JQUERY_UI_STYLE' => (!empty($config['jquery_ui_style']) ? $config['jquery_ui_style'] : 'cupertino'),
  4931. 'S_JQUERY_TAGS' => (!empty($config['jquery_tags']) ? true : false),
  4932. )
  4933. );
  4934. if ($parse_template || empty($template_to_parse))
  4935. {
  4936. $footer_tpl = empty($gen_simple_header) ? 'overall_footer.tpl' : 'simple_footer.tpl';
  4937. $template->set_filenames(array('overall_footer' => $footer_tpl));
  4938. $template->pparse('overall_footer');
  4939. }
  4940. else
  4941. {
  4942. //$template_to_parse = empty($template_to_parse) ? 'body' : $template_to_parse;
  4943. $template->pparse($template_to_parse);
  4944. }
  4945. if ($exit)
  4946. {
  4947. garbage_collection();
  4948. exit_handler();
  4949. exit;
  4950. }
  4951. return;
  4952. }
  4953. /**
  4954. * Closing the cache object and the database
  4955. */
  4956. function garbage_collection()
  4957. {
  4958. global $db, $cache;
  4959. // If we are in ACP it is better to clear some files in cache to make sure all options are updated
  4960. if (defined('IN_ADMIN') && !defined('ACP_MODULES'))
  4961. {
  4962. empty_cache_folders_admin();
  4963. }
  4964. // If we are in ACP it is better to clear some files in cache to make sure all options are updated
  4965. if (defined('IN_CMS'))
  4966. {
  4967. empty_cache_folders_cms();
  4968. }
  4969. // Unload cache, must be done before the DB connection if closed
  4970. if (!empty($cache))
  4971. {
  4972. $cache->unload();
  4973. }
  4974. // Close our DB connection.
  4975. if (!empty($db))
  4976. {
  4977. $db->sql_close();
  4978. }
  4979. }
  4980. /**
  4981. * Handler for exit calls in phpBB.
  4982. *
  4983. * Note: This function is called after the template has been outputted.
  4984. */
  4985. function exit_handler()
  4986. {
  4987. global $phpbb_hook, $config;
  4988. if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
  4989. {
  4990. if ($phpbb_hook->hook_return(__FUNCTION__))
  4991. {
  4992. return $phpbb_hook->hook_return_result(__FUNCTION__);
  4993. }
  4994. }
  4995. // URL Rewrite - BEGIN
  4996. // Compress buffered output if required and send to browser
  4997. if (!empty($config['url_rw_runtime']))
  4998. {
  4999. $contents = rewrite_urls(ob_get_contents());
  5000. ob_end_clean();
  5001. (@extension_loaded('zlib') && !empty($config['gzip_compress_runtime'])) ? ob_start('ob_gzhandler') : ob_start();
  5002. echo $contents;
  5003. }
  5004. // URL Rewrite - END
  5005. // As a pre-caution... some setups display a blank page if the flush() is not there.
  5006. (empty($config['gzip_compress_runtime']) && empty($config['url_rw_runtime'])) ? @flush() : @ob_flush();
  5007. exit;
  5008. }
  5009. /**
  5010. * Full page generation
  5011. */
  5012. function full_page_generation($page_template, $page_title = '', $page_description = '', $page_keywords = '')
  5013. {
  5014. global $template, $meta_content;
  5015. $meta_content['page_title'] = (!empty($page_title) ? $page_title : (!empty($meta_content['page_title']) ? $meta_content['page_title'] : ''));
  5016. $meta_content['description'] = (!empty($page_description) ? $page_description : (!empty($meta_content['description']) ? $meta_content['description'] : ''));
  5017. $meta_content['keywords'] = (!empty($page_keywords) ? $page_keywords : (!empty($meta_content['keywords']) ? $meta_content['keywords'] : ''));
  5018. page_header();
  5019. $template->set_filenames(array('body' => $page_template));
  5020. page_footer();
  5021. }
  5022. /**
  5023. * Add log event
  5024. */
  5025. function add_log()
  5026. {
  5027. global $db, $user;
  5028. // In phpBB 3.1.x i want to have logging in a class to be able to control it
  5029. // For now, we need a quite hakish approach to circumvent logging for some actions
  5030. // @todo implement cleanly
  5031. if (!empty($GLOBALS['skip_add_log']))
  5032. {
  5033. return false;
  5034. }
  5035. $args = func_get_args();
  5036. $mode = array_shift($args);
  5037. $reportee_id = ($mode == 'user') ? intval(array_shift($args)) : '';
  5038. $forum_id = ($mode == 'mod') ? intval(array_shift($args)) : '';
  5039. $topic_id = ($mode == 'mod') ? intval(array_shift($args)) : '';
  5040. $action = array_shift($args);
  5041. $data = (!sizeof($args)) ? '' : serialize($args);
  5042. $sql_ary = array(
  5043. 'user_id' => (empty($user->data)) ? ANONYMOUS : $user->data['user_id'],
  5044. 'log_ip' => $user->ip,
  5045. 'log_time' => time(),
  5046. 'log_operation' => $action,
  5047. 'log_data' => $data,
  5048. );
  5049. switch ($mode)
  5050. {
  5051. case 'admin':
  5052. $sql_ary['log_type'] = LOG_ADMIN;
  5053. break;
  5054. case 'mod':
  5055. $sql_ary += array(
  5056. 'log_type' => LOG_MOD,
  5057. 'forum_id' => $forum_id,
  5058. 'topic_id' => $topic_id
  5059. );
  5060. break;
  5061. case 'user':
  5062. $sql_ary += array(
  5063. 'log_type' => LOG_USERS,
  5064. 'reportee_id' => $reportee_id
  5065. );
  5066. break;
  5067. case 'critical':
  5068. $sql_ary['log_type'] = LOG_CRITICAL;
  5069. break;
  5070. default:
  5071. return false;
  5072. }
  5073. $db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
  5074. return $db->sql_nextid();
  5075. }
  5076. /**
  5077. * Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com)
  5078. */
  5079. function get_backtrace()
  5080. {
  5081. $output = '<div style="font-family: monospace;">';
  5082. $backtrace = debug_backtrace();
  5083. $path = phpbb_realpath(IP_ROOT_PATH);
  5084. foreach ($backtrace as $number => $trace)
  5085. {
  5086. // We skip the first one, because it only shows this file/function
  5087. if ($number == 0)
  5088. {
  5089. continue;
  5090. }
  5091. // Strip the current directory from path
  5092. if (empty($trace['file']))
  5093. {
  5094. $trace['file'] = '';
  5095. }
  5096. else
  5097. {
  5098. $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']);
  5099. $trace['file'] = substr($trace['file'], 1);
  5100. }
  5101. $args = array();
  5102. // If include/require/include_once is not called, do not show arguments - they may contain sensible information
  5103. if (!in_array($trace['function'], array('include', 'require', 'include_once')))
  5104. {
  5105. unset($trace['args']);
  5106. }
  5107. else
  5108. {
  5109. // Path...
  5110. if (!empty($trace['args'][0]))
  5111. {
  5112. $argument = htmlspecialchars($trace['args'][0]);
  5113. $argument = str_replace(array($path, '\\'), array('', '/'), $argument);
  5114. $argument = substr($argument, 1);
  5115. $args[] = "'{$argument}'";
  5116. }
  5117. }
  5118. $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class'];
  5119. $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type'];
  5120. $output .= '<br />';
  5121. $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />';
  5122. $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />';
  5123. $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />';
  5124. }
  5125. $output .= '</div>';
  5126. return $output;
  5127. }
  5128. /**
  5129. * This function returns a regular expression pattern for commonly used expressions
  5130. * Use with / as delimiter for email mode and # for url modes
  5131. * mode can be: ipv4|ipv6
  5132. */
  5133. function get_preg_expression($mode)
  5134. {
  5135. switch ($mode)
  5136. {
  5137. // Whoa these look impressive!
  5138. // The code to generate the following two regular expressions which match valid IPv4/IPv6 addresses can be found in the develop directory
  5139. case 'ipv4':
  5140. return '#^(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$#';
  5141. break;
  5142. case 'ipv6':
  5143. return '#^(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))$#i';
  5144. break;
  5145. }
  5146. return '';
  5147. }
  5148. /**
  5149. * Returns the first block of the specified IPv6 address and as many additional
  5150. * ones as specified in the length paramater.
  5151. * If length is zero, then an empty string is returned.
  5152. * If length is greater than 3 the complete IP will be returned
  5153. */
  5154. function short_ipv6($ip, $length)
  5155. {
  5156. if ($length < 1)
  5157. {
  5158. return '';
  5159. }
  5160. // extend IPv6 addresses
  5161. $blocks = substr_count($ip, ':') + 1;
  5162. if ($blocks < 9)
  5163. {
  5164. $ip = str_replace('::', ':' . str_repeat('0000:', 9 - $blocks), $ip);
  5165. }
  5166. if ($ip[0] == ':')
  5167. {
  5168. $ip = '0000' . $ip;
  5169. }
  5170. if ($length < 4)
  5171. {
  5172. $ip = implode(':', array_slice(explode(':', $ip), 0, 1 + $length));
  5173. }
  5174. return $ip;
  5175. }
  5176. /**
  5177. * Wrapper for php's checkdnsrr function.
  5178. *
  5179. * @param string $host:Fully-Qualified Domain Name
  5180. * @param string $type: Resource record type to lookup
  5181. * Supported types are: MX (default), A, AAAA, NS, TXT, CNAME
  5182. * Other types may work or may not work
  5183. *
  5184. * @return mixed: true if entry found,
  5185. * false if entry not found,
  5186. * null if this function is not supported by this environment
  5187. *
  5188. * Since null can also be returned, you probably want to compare the result
  5189. * with === true or === false,
  5190. *
  5191. * @author bantu
  5192. */
  5193. function phpbb_checkdnsrr($host, $type = 'MX')
  5194. {
  5195. // The dot indicates to search the DNS root (helps those having DNS prefixes on the same domain)
  5196. if (substr($host, -1) == '.')
  5197. {
  5198. $host_fqdn = $host;
  5199. $host = substr($host, 0, -1);
  5200. }
  5201. else
  5202. {
  5203. $host_fqdn = $host . '.';
  5204. }
  5205. // $host: has format some.host.example.com
  5206. // $host_fqdn: has format some.host.example.com.
  5207. // If we're looking for an A record we can use gethostbyname()
  5208. if (($type == 'A') && function_exists('gethostbyname'))
  5209. {
  5210. return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true;
  5211. }
  5212. // checkdnsrr() is available on Windows since PHP 5.3,
  5213. // but until 5.3.3 it only works for MX records
  5214. // See: http://bugs.php.net/bug.php?id=51844
  5215. // Call checkdnsrr() if
  5216. // we're looking for an MX record or
  5217. // we're not on Windows or
  5218. // we're running a PHP version where #51844 has been fixed
  5219. // checkdnsrr() supports AAAA since 5.0.0
  5220. // checkdnsrr() supports TXT since 5.2.4
  5221. if ((($type == 'MX') || (DIRECTORY_SEPARATOR != '\\') || version_compare(PHP_VERSION, '5.3.3', '>=')) && (($type != 'AAAA') || version_compare(PHP_VERSION, '5.0.0', '>=')) && (($type != 'TXT') || version_compare(PHP_VERSION, '5.2.4', '>=')) && function_exists('checkdnsrr')
  5222. )
  5223. {
  5224. return checkdnsrr($host_fqdn, $type);
  5225. }
  5226. // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows,
  5227. // but on Windows it does not work reliable for AAAA records before PHP 5.3.1
  5228. // Call dns_get_record() if
  5229. // we're not looking for an AAAA record or
  5230. // we're not on Windows or
  5231. // we're running a PHP version where AAAA lookups work reliable
  5232. if ((($type != 'AAAA') || (DIRECTORY_SEPARATOR != '\\') || version_compare(PHP_VERSION, '5.3.1', '>=')) && function_exists('dns_get_record'))
  5233. {
  5234. // dns_get_record() expects an integer as second parameter
  5235. // We have to convert the string $type to the corresponding integer constant.
  5236. $type_constant = 'DNS_' . $type;
  5237. $type_param = (defined($type_constant)) ? constant($type_constant) : DNS_ANY;
  5238. // dns_get_record() might throw E_WARNING and return false for records that do not exist
  5239. $resultset = @dns_get_record($host_fqdn, $type_param);
  5240. if (empty($resultset) || !is_array($resultset))
  5241. {
  5242. return false;
  5243. }
  5244. elseif ($type_param == DNS_ANY)
  5245. {
  5246. // $resultset is a non-empty array
  5247. return true;
  5248. }
  5249. foreach ($resultset as $result)
  5250. {
  5251. if (isset($result['host']) && ($result['host'] == $host) && isset($result['type']) && ($result['type'] == $type))
  5252. {
  5253. return true;
  5254. }
  5255. }
  5256. return false;
  5257. }
  5258. // If we're on Windows we can still try to call nslookup via exec() as a last resort
  5259. if ((DIRECTORY_SEPARATOR == '\\') && function_exists('exec'))
  5260. {
  5261. @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host_fqdn), $output);
  5262. // If output is empty, the nslookup failed
  5263. if (empty($output))
  5264. {
  5265. return NULL;
  5266. }
  5267. foreach ($output as $line)
  5268. {
  5269. $line = trim($line);
  5270. if (empty($line))
  5271. {
  5272. continue;
  5273. }
  5274. // Squash tabs and multiple whitespaces to a single whitespace.
  5275. $line = preg_replace('/\s+/', ' ', $line);
  5276. switch ($type)
  5277. {
  5278. case 'MX':
  5279. if (stripos($line, "$host MX") === 0)
  5280. {
  5281. return true;
  5282. }
  5283. break;
  5284. case 'NS':
  5285. if (stripos($line, "$host nameserver") === 0)
  5286. {
  5287. return true;
  5288. }
  5289. break;
  5290. case 'TXT':
  5291. if (stripos($line, "$host text") === 0)
  5292. {
  5293. return true;
  5294. }
  5295. break;
  5296. case 'CNAME':
  5297. if (stripos($line, "$host canonical name") === 0)
  5298. {
  5299. return true;
  5300. }
  5301. default:
  5302. case 'A':
  5303. case 'AAAA':
  5304. if (!empty($host_matches))
  5305. {
  5306. // Second line
  5307. if (stripos($line, "Address: ") === 0)
  5308. {
  5309. return true;
  5310. }
  5311. else
  5312. {
  5313. $host_matches = false;
  5314. }
  5315. }
  5316. else if (stripos($line, "Name: $host") === 0)
  5317. {
  5318. // First line
  5319. $host_matches = true;
  5320. }
  5321. break;
  5322. }
  5323. }
  5324. return false;
  5325. }
  5326. return NULL;
  5327. }
  5328. /**
  5329. * Handler for init calls in phpBB. This function is called in user::setup();
  5330. * This function supports hooks.
  5331. */
  5332. function phpbb_user_session_handler()
  5333. {
  5334. global $phpbb_hook;
  5335. if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__))
  5336. {
  5337. if ($phpbb_hook->hook_return(__FUNCTION__))
  5338. {
  5339. return $phpbb_hook->hook_return_result(__FUNCTION__);
  5340. }
  5341. }
  5342. return;
  5343. }
  5344. /**
  5345. * Error and message handler, call with trigger_error if reqd
  5346. */
  5347. function msg_handler($errno, $msg_text, $errfile, $errline)
  5348. {
  5349. global $config, $lang;
  5350. global $msg_code, $msg_title, $msg_long_text;
  5351. // Do not display notices if we suppress them via @
  5352. if (error_reporting() == 0)
  5353. {
  5354. return;
  5355. }
  5356. // Message handler is stripping text. In case we need it, we are possible to define long text...
  5357. if (isset($msg_long_text) && $msg_long_text && !$msg_text)
  5358. {
  5359. $msg_text = $msg_long_text;
  5360. }
  5361. $msg_code = empty($msg_code) ? GENERAL_MESSAGE : $msg_code;
  5362. switch ($errno)
  5363. {
  5364. case E_NOTICE:
  5365. // Mighty Gorgon: if you want to report uninitialized variables, comment the "BREAK" below...
  5366. break;
  5367. case E_WARNING:
  5368. // Check the error reporting level and return if the error level does not match
  5369. // If DEBUG is defined to FALSE then return
  5370. if (defined('DEBUG') && !DEBUG)
  5371. {
  5372. return;
  5373. }
  5374. // If DEBUG is defined the default level is E_ALL
  5375. if (($errno & ((defined('DEBUG')) ? E_ALL : error_reporting())) == 0)
  5376. {
  5377. return;
  5378. }
  5379. if ((strpos($errfile, 'cache') === false) && (strpos($errfile, 'template.') === false))
  5380. {
  5381. // flush the content, else we get a white page if output buffering is on
  5382. if ((int) @ini_get('output_buffering') === 1 || strtolower(@ini_get('output_buffering')) === 'on')
  5383. {
  5384. @ob_flush();
  5385. }
  5386. // Another quick fix for those having gzip compression enabled, but do not flush if the coder wants to catch "something". ;)
  5387. $config['gzip_compress_runtime'] = (isset($config['gzip_compress_runtime']) ? $config['gzip_compress_runtime'] : $config['gzip_compress']);
  5388. if (!empty($config['gzip_compress_runtime']))
  5389. {
  5390. if (@extension_loaded('zlib') && !headers_sent() && !ob_get_level())
  5391. {
  5392. @ob_flush();
  5393. }
  5394. }
  5395. // remove complete path to installation, with the risk of changing backslashes meant to be there
  5396. $errfile = str_replace(array(phpbb_realpath(IP_ROOT_PATH), '\\'), array('', '/'), $errfile);
  5397. $msg_text = str_replace(array(phpbb_realpath(IP_ROOT_PATH), '\\'), array('', '/'), $msg_text);
  5398. echo '<b>[Icy Phoenix Debug] PHP Notice</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n";
  5399. }
  5400. return;
  5401. break;
  5402. case E_USER_ERROR:
  5403. $msg_text = (!empty($lang[$msg_text])) ? $lang[$msg_text] : $msg_text;
  5404. $msg_title_default = (!empty($lang['General_Error'])) ? $lang['General_Error'] : 'General Error';
  5405. $msg_title = (!empty($lang[$msg_title])) ? $lang[$msg_title] : $msg_title_default;
  5406. $return_url = (!empty($lang['CLICK_RETURN_HOME'])) ? sprintf($lang['CLICK_RETURN_HOME'], '<a href="' . IP_ROOT_PATH . '">', '</a>') : ('<a href="' . IP_ROOT_PATH . '">Return to home page</a>');
  5407. garbage_collection();
  5408. html_message($msg_title, $msg_text, $return_url);
  5409. exit_handler();
  5410. // On a fatal error (and E_USER_ERROR *is* fatal) we never want other scripts to continue and force an exit here.
  5411. exit;
  5412. break;
  5413. case E_USER_WARNING:
  5414. case E_USER_NOTICE:
  5415. define('IN_ERROR_HANDLER', true);
  5416. $status_not_found_array = array('ERROR_NO_ATTACHMENT', 'NO_FORUM', 'NO_TOPIC', 'NO_USER');
  5417. if (in_array($msg_text, $status_not_found_array))
  5418. {
  5419. if (!defined('STATUS_404')) define('STATUS_404', true);
  5420. }
  5421. message_die($msg_code, $msg_text, $msg_title, $errline, $errfile, '');
  5422. }
  5423. }
  5424. /**
  5425. * HTML Message
  5426. */
  5427. function html_message($msg_title, $msg_text, $return_url)
  5428. {
  5429. global $lang;
  5430. $encoding_charset = !empty($lang['ENCODING']) ? $lang['ENCODING'] : 'UTF-8';
  5431. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
  5432. echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">';
  5433. echo '<head>';
  5434. echo '<meta http-equiv="content-type" content="text/html; charset=' . $encoding_charset . '" />';
  5435. echo '<title>' . $msg_title . '</title>';
  5436. echo '<style type="text/css">';
  5437. echo "\n" . '/* <![CDATA[ */' . "\n";
  5438. echo '* { margin: 0; padding: 0; } html { font-size: 100%; height: 100%; margin-bottom: 1px; background-color: #e8eef8; } body { font-family: "Trebuchet MS", "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; color: #225599; background: #e8eef8; font-size: 62.5%; margin: 0; } ';
  5439. echo 'a:link, a:active, a:visited { color: #336699; text-decoration: none; } a:hover { color: #dd2222; text-decoration: underline; } ';
  5440. echo '#wrap { padding: 0 20px 15px 20px; min-width: 615px; } #page-header { text-align: right; height: 40px; } #page-footer { clear: both; font-size: 1em; text-align: center; } ';
  5441. echo '.panel { margin: 4px 0; background-color: #ffffff; border: solid 1px #dde8ee; } ';
  5442. echo '#errorpage #page-header a { font-weight: bold; line-height: 6em; } #errorpage #content { padding: 10px; } #errorpage #content h1 { line-height: 1.2em; margin-bottom: 0; color: #dd2222; } ';
  5443. echo '#errorpage #content div { margin-top: 20px; margin-bottom: 5px; border-bottom: 1px solid #dddddd; padding-bottom: 5px; color: #333333; font: bold 1.2em "Trebuchet MS", "Lucida Grande", Arial, Helvetica, sans-serif; text-decoration: none; line-height: 120%; text-align: left; } ';
  5444. echo "\n" . '/* ]]> */' . "\n";
  5445. echo '</style>';
  5446. echo '</head>';
  5447. echo '<body id="errorpage">';
  5448. echo '<div id="wrap">';
  5449. echo ' <div id="page-header">';
  5450. echo ' ' . $return_url;
  5451. echo ' </div>';
  5452. echo ' <div class="panel">';
  5453. echo ' <div id="content">';
  5454. echo ' <h1>' . $msg_title . '</h1>';
  5455. echo ' <div>' . $msg_text . '</div>';
  5456. echo ' </div>';
  5457. echo ' </div>';
  5458. echo ' <div id="page-footer">';
  5459. echo ' Powered by <a href="http://www.icyphoenix.com/" target="_blank">Icy Phoenix</a> based on <a href="http://www.phpbb.com/" target="_blank">phpBB</a>';
  5460. echo ' </div>';
  5461. echo '</div>';
  5462. echo '</body>';
  5463. echo '</html>';
  5464. }
  5465. //
  5466. // This is general replacement for die(), allows templated
  5467. // output in users (or default) language, etc.
  5468. //
  5469. // $msg_code can be one of these constants:
  5470. //
  5471. // GENERAL_MESSAGE : Use for any simple text message, eg. results of an operation, authorization failures, etc.
  5472. // GENERAL ERROR : Use for any error which occurs _AFTER_ the common.php include and session code, ie. most errors in pages/functions
  5473. // CRITICAL_MESSAGE : Used when basic config data is available but a session may not exist, eg. banned users
  5474. // CRITICAL_ERROR : Used when config data cannot be obtained, eg no database connection. Should _not_ be used in 99.5% of cases
  5475. //
  5476. function message_die($msg_code, $msg_text = '', $msg_title = '', $err_line = '', $err_file = '', $sql = '')
  5477. {
  5478. global $db, $cache, $config, $auth, $user, $lang, $template, $images, $theme, $tree;
  5479. global $table_prefix, $SID, $_SID;
  5480. global $gen_simple_header, $starttime, $base_memory_usage, $do_gzip_compress;
  5481. global $ip_cms, $cms_config_vars, $cms_config_global_blocks, $cms_config_layouts, $cms_page;
  5482. global $nav_separator, $nav_links;
  5483. // Global vars needed by page header, but since we are in message_die better use default values instead of the assigned ones in case we are dying before including page_header.php
  5484. /*
  5485. global $meta_content;
  5486. global $nav_pgm, $nav_add_page_title, $skip_nav_cat, $start;
  5487. global $breadcrumbs;
  5488. */
  5489. //+MOD: Fix message_die for multiple errors MOD
  5490. static $msg_history;
  5491. if(!isset($msg_history))
  5492. {
  5493. $msg_history = array();
  5494. }
  5495. $msg_history[] = array(
  5496. 'msg_code' => $msg_code,
  5497. 'msg_text' => $msg_text,
  5498. 'msg_title' => $msg_title,
  5499. 'err_line' => $err_line,
  5500. 'err_file' => $err_file,
  5501. 'sql' => htmlspecialchars($sql)
  5502. );
  5503. //-MOD: Fix message_die for multiple errors MOD
  5504. if(defined('HAS_DIED'))
  5505. {
  5506. //+MOD: Fix message_die for multiple errors MOD
  5507. //
  5508. // This message is printed at the end of the report.
  5509. // Of course, you can change it to suit your own needs. ;-)
  5510. //
  5511. $custom_error_message = 'Please, contact the %swebmaster%s. Thank you.';
  5512. if (!empty($config) && !empty($config['board_email']))
  5513. {
  5514. $custom_error_message = sprintf($custom_error_message, '<a href="mailto:' . $config['board_email'] . '">', '</a>');
  5515. }
  5516. else
  5517. {
  5518. $custom_error_message = sprintf($custom_error_message, '', '');
  5519. }
  5520. echo "<html>\n<body>\n<b>Critical Error!</b><br />\nmessage_die() was called multiple times.<br />&nbsp;<hr />";
  5521. for($i = 0; $i < sizeof($msg_history); $i++)
  5522. {
  5523. echo '<b>Error #' . ($i+1) . "</b>\n<br />\n";
  5524. if(!empty($msg_history[$i]['msg_title']))
  5525. {
  5526. echo '<b>' . $msg_history[$i]['msg_title'] . "</b>\n<br />\n";
  5527. }
  5528. echo $msg_history[$i]['msg_text'] . "\n<br /><br />\n";
  5529. if(!empty($msg_history[$i]['err_line']))
  5530. {
  5531. echo '<b>Line :</b> ' . $msg_history[$i]['err_line'] . '<br /><b>File :</b> ' . $msg_history[$i]['err_file'] . "</b>\n<br />\n";
  5532. }
  5533. if(!empty($msg_history[$i]['sql']))
  5534. {
  5535. echo '<b>SQL :</b> ' . $msg_history[$i]['sql'] . "\n<br />\n";
  5536. }
  5537. echo "&nbsp;<hr />\n";
  5538. }
  5539. echo $custom_error_message . '<hr /><br clear="all">';
  5540. die("</body>\n</html>");
  5541. //-MOD: Fix message_die for multiple errors MOD
  5542. }
  5543. define('HAS_DIED', 1);
  5544. $sql_store = $sql;
  5545. // Get SQL error if we are debugging. Do this as soon as possible to prevent subsequent queries from overwriting the status of sql_error()
  5546. if (DEBUG && (($msg_code == GENERAL_ERROR) || ($msg_code == CRITICAL_ERROR)))
  5547. {
  5548. $sql_error = $db->sql_error();
  5549. $debug_text = '';
  5550. if ($sql_error['message'] != '')
  5551. {
  5552. $debug_text .= '<br /><br />SQL Error : ' . $sql_error['code'] . ' ' . $sql_error['message'];
  5553. }
  5554. if ($sql_store != '')
  5555. {
  5556. $debug_text .= '<br /><br />' . htmlspecialchars($sql_store);
  5557. }
  5558. if ($err_line != '' && $err_file != '')
  5559. {
  5560. $debug_text .= '<br /><br />Line : ' . $err_line . '<br />File : ' . basename($err_file);
  5561. }
  5562. }
  5563. if(empty($user->data) && (($msg_code == GENERAL_MESSAGE) || ($msg_code == GENERAL_ERROR)))
  5564. {
  5565. // Start session management
  5566. $user->session_begin();
  5567. $auth->acl($user->data);
  5568. $user->setup();
  5569. // End session management
  5570. }
  5571. // If the header hasn't been parsed yet... then do it!
  5572. if (!defined('HEADER_INC') && ($msg_code != CRITICAL_ERROR))
  5573. {
  5574. setup_basic_lang();
  5575. if (empty($template) || empty($theme))
  5576. {
  5577. $theme = setup_style($config['default_style'], $current_default_style);
  5578. }
  5579. $template->assign_var('HAS_DIED', true);
  5580. define('TPL_HAS_DIED', true);
  5581. // Load the Page Header
  5582. if (!defined('IN_ADMIN'))
  5583. {
  5584. $parse_template = defined('IN_CMS') ? false : true;
  5585. page_header('', $parse_template);
  5586. }
  5587. else
  5588. {
  5589. include(IP_ROOT_PATH . ADM . '/page_header_admin.' . PHP_EXT);
  5590. }
  5591. }
  5592. if (!defined('IN_ADMIN') && !defined('IN_CMS') && !defined('HEADER_INC_COMPLETED') && ($msg_code != CRITICAL_ERROR))
  5593. {
  5594. if (!defined('TPL_HAS_DIED'))
  5595. {
  5596. $template->assign_var('HAS_DIED', true);
  5597. define('TPL_HAS_DIED', true);
  5598. }
  5599. $header_tpl = empty($gen_simple_header) ? 'overall_header.tpl' : 'simple_header.tpl';
  5600. $template->set_filenames(array('overall_header' => $header_tpl));
  5601. $template->pparse('overall_header');
  5602. }
  5603. switch($msg_code)
  5604. {
  5605. case GENERAL_MESSAGE:
  5606. if ($msg_title == '')
  5607. {
  5608. $msg_title = $lang['Information'];
  5609. }
  5610. break;
  5611. case CRITICAL_MESSAGE:
  5612. if ($msg_title == '')
  5613. {
  5614. $msg_title = $lang['Critical_Information'];
  5615. }
  5616. break;
  5617. case GENERAL_ERROR:
  5618. if ($msg_text == '')
  5619. {
  5620. $msg_text = $lang['An_error_occured'];
  5621. }
  5622. if ($msg_title == '')
  5623. {
  5624. $msg_title = $lang['General_Error'];
  5625. }
  5626. break;
  5627. case CRITICAL_ERROR:
  5628. // Critical errors mean we cannot rely on _ANY_ DB information being available so we're going to dump out a simple echo'd statement
  5629. // We force english to make sure we have at least the default language
  5630. $config['default_lang'] = 'english';
  5631. setup_basic_lang();
  5632. if ($msg_text == '')
  5633. {
  5634. $msg_text = $lang['A_critical_error'];
  5635. }
  5636. if ($msg_title == '')
  5637. {
  5638. $msg_title = '<b>' . $lang['Critical_Error'] . '</b>';
  5639. }
  5640. break;
  5641. }
  5642. //
  5643. // Add on DEBUG info if we've enabled debug mode and this is an error. This
  5644. // prevents debug info being output for general messages should DEBUG be
  5645. // set TRUE by accident (preventing confusion for the end user!)
  5646. //
  5647. if (DEBUG && (($msg_code == GENERAL_ERROR) || ($msg_code == CRITICAL_ERROR)))
  5648. {
  5649. if ($debug_text != '')
  5650. {
  5651. $msg_text = $msg_text . '<br /><br /><b><u>DEBUG MODE</u></b>' . $debug_text;
  5652. }
  5653. }
  5654. // MG Logs - BEGIN
  5655. //if (($config['mg_log_actions'] == true) && ($msg_code == GENERAL_ERROR || $msg_code == CRITICAL_ERROR))
  5656. if ($msg_code != GENERAL_MESSAGE)
  5657. {
  5658. if ($config['mg_log_actions'] || !empty($config['db_log_actions']))
  5659. {
  5660. $db_log = array(
  5661. 'action' => 'MESSAGE',
  5662. //'desc' => $msg_code . ',' . $msg_title . ',' . substr($msg_text,0,20) . '...',
  5663. 'desc' => $msg_code,
  5664. 'target' => '',
  5665. );
  5666. $error_log = array(
  5667. 'code' => $msg_code,
  5668. 'title' => $msg_title,
  5669. 'text' => $msg_text,
  5670. );
  5671. if (!function_exists('ip_log'))
  5672. {
  5673. @include(IP_ROOT_PATH . 'includes/functions_mg_log.' . PHP_EXT);
  5674. }
  5675. ip_log('[MSG_CODE: ' . $msg_code . '] - [MSG_TITLE: ' . $msg_title . '] - [MSG_TEXT: ' . $msg_text . ']', $db_log, $error_log);
  5676. }
  5677. }
  5678. // MG Logs - END
  5679. if ($msg_code != CRITICAL_ERROR)
  5680. {
  5681. if (defined('STATUS_404'))
  5682. {
  5683. send_status_line(404, 'Not Found');
  5684. }
  5685. if (defined('STATUS_503'))
  5686. {
  5687. send_status_line(503, 'Service Unavailable');
  5688. }
  5689. if (!empty($lang[$msg_text]))
  5690. {
  5691. $msg_text = $lang[$msg_text];
  5692. }
  5693. if (defined('IN_ADMIN'))
  5694. {
  5695. $template->set_filenames(array('message_body' => ADM_TPL . 'admin_message_body.tpl'));
  5696. }
  5697. elseif (defined('IN_CMS'))
  5698. {
  5699. $template->set_filenames(array('message_body' => COMMON_TPL . 'cms/message_body.tpl'));
  5700. }
  5701. else
  5702. {
  5703. $template->set_filenames(array('message_body' => 'message_body.tpl'));
  5704. }
  5705. //echo('<br />' . htmlspecialchars($template->vars['META']));
  5706. $template->assign_vars(array(
  5707. 'MESSAGE_TITLE' => $msg_title,
  5708. 'MESSAGE_TEXT' => $msg_text
  5709. )
  5710. );
  5711. if (!defined('IN_CMS'))
  5712. {
  5713. $template->pparse('message_body');
  5714. }
  5715. // If we have already defined the var in header, let's output it in footer as well
  5716. if(defined('TPL_HAS_DIED'))
  5717. {
  5718. $template->assign_var('HAS_DIED', true);
  5719. }
  5720. if (!defined('IN_ADMIN'))
  5721. {
  5722. $template_to_parse = defined('IN_CMS') ? 'message_body' : '';
  5723. $parse_template = defined('IN_CMS') ? false : true;
  5724. page_footer(true, $template_to_parse, $parse_template);
  5725. }
  5726. else
  5727. {
  5728. include(IP_ROOT_PATH . ADM . '/page_footer_admin.' . PHP_EXT);
  5729. }
  5730. }
  5731. else
  5732. {
  5733. echo "<html>\n<body>\n" . $msg_title . "\n<br /><br />\n" . $msg_text . "</body>\n</html>";
  5734. }
  5735. garbage_collection();
  5736. exit_handler();
  5737. exit;
  5738. }
  5739. //
  5740. // Truncates HTML strings cleanly
  5741. // Taken from code in http://stackoverflow.com/questions/1193500/php-truncate-html-ignoring-tags
  5742. //
  5743. function truncate_html_string($text, $length, $ellipsis = '...')
  5744. {
  5745. if (strlen(preg_replace(array('/<.*?>/', '/&#?[a-zA-Z0-9]+;/'), array('', ' '), $text)) <= $length)
  5746. {
  5747. return $text;
  5748. }
  5749. $printed_length = 0;
  5750. $position = 0;
  5751. $tags = array();
  5752. $clean_text = '';
  5753. while ($printed_length < $length && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $text, $match, PREG_OFFSET_CAPTURE, $position))
  5754. {
  5755. list($tag, $tag_position) = $match[0];
  5756. // append text leading up to the tag.
  5757. $str = substr($text, $position, $tag_position - $position);
  5758. if ($printed_length + strlen($str) > $length)
  5759. {
  5760. break;
  5761. }
  5762. $clean_text .= $str;
  5763. $printed_length += strlen($str);
  5764. if ($tag[0] == '&')
  5765. {
  5766. // Handle the entity.
  5767. $clean_text .= $tag;
  5768. $printed_length++;
  5769. }
  5770. else
  5771. {
  5772. // Handle the tag.
  5773. $tag_name = $match[1][0];
  5774. if ($tag[1] == '/')
  5775. {
  5776. // This is a closing tag.
  5777. $opening_tag = array_pop($tags);
  5778. assert($opening_tag == $tag_name); // check that tags are properly nested.
  5779. $clean_text .= $tag;
  5780. }
  5781. else if ($tag[strlen($tag) - 2] == '/')
  5782. {
  5783. // Self-closing tag.
  5784. $clean_text .= $tag;
  5785. }
  5786. else
  5787. {
  5788. // Opening tag.
  5789. $clean_text .= $tag;
  5790. $tags[] = $tag_name;
  5791. }
  5792. }
  5793. // Continue after the tag.
  5794. $position = $tag_position + strlen($tag);
  5795. }
  5796. // Print any remaining text.
  5797. if ($printed_length < $length && $position < strlen($text))
  5798. {
  5799. $max_length = $length - $printed_length;
  5800. $utf8_length = 0;
  5801. while ($utf8_length < $max_length)
  5802. {
  5803. $char = substr($text, $position + $utf8_length, 1);
  5804. // UTF-8 character encoding - BEGIN
  5805. $code = ord($char);
  5806. if ($code >= 0x80)
  5807. {
  5808. if ($code < 0xE0)
  5809. {
  5810. // Two byte
  5811. if (($max_length - $utf8_length) >= 2)
  5812. {
  5813. $utf8_length = $utf8_length + 2;
  5814. }
  5815. else
  5816. {
  5817. break;
  5818. }
  5819. }
  5820. elseif ($code1 < 0xF0)
  5821. {
  5822. // Three byte
  5823. if (($max_length - $utf8_length) >= 3)
  5824. {
  5825. $utf8_length = $utf8_length + 3;
  5826. }
  5827. else
  5828. {
  5829. break;
  5830. }
  5831. }
  5832. }
  5833. else
  5834. {
  5835. $utf8_length = $utf8_length + 1;
  5836. }
  5837. // UTF-8 character encoding - END
  5838. }
  5839. $clean_text .= substr($text, $position, $utf8_length);
  5840. }
  5841. $clean_text .= $ellipsis;
  5842. // Close any open tags.
  5843. while (!empty($tags))
  5844. {
  5845. $clean_text .= '</' . array_pop($tags) . '>';
  5846. }
  5847. return $clean_text;
  5848. }
  5849. ?>