PageRenderTime 52ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/php/Sources/Load.php

https://github.com/dekoza/openshift-smf-2.0.7
PHP | 2750 lines | 2007 code | 334 blank | 409 comment | 676 complexity | d38355207cc36ae1d28e4d1df1e8f92b MD5 | raw file
Possible License(s): BSD-3-Clause

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

  1. <?php
  2. /**
  3. * Simple Machines Forum (SMF)
  4. *
  5. * @package SMF
  6. * @author Simple Machines http://www.simplemachines.org
  7. * @copyright 2011 Simple Machines
  8. * @license http://www.simplemachines.org/about/smf/license.php BSD
  9. *
  10. * @version 2.0.7
  11. */
  12. if (!defined('SMF'))
  13. die('Hacking attempt...');
  14. /* This file has the hefty job of loading information for the forum. It uses
  15. the following functions:
  16. void reloadSettings()
  17. - loads or reloads the $modSettings array.
  18. - loads any integration settings, SMF_INTEGRATION_SETTINGS, etc.
  19. void loadUserSettings()
  20. - sets up the $user_info array
  21. - assigns $user_info['query_wanna_see_board'] for what boards the user can see.
  22. - first checks for cookie or intergration validation.
  23. - uses the current session if no integration function or cookie is found.
  24. - checks password length, if member is activated and the login span isn't over.
  25. - if validation fails for the user, $id_member is set to 0.
  26. - updates the last visit time when needed.
  27. void loadBoard()
  28. - sets up the $board_info array for current board information.
  29. - if cache is enabled, the $board_info array is stored in cache.
  30. - redirects to appropriate post if only message id is requested.
  31. - is only used when inside a topic or board.
  32. - determines the local moderators for the board.
  33. - adds group id 3 if the user is a local moderator for the board they are in.
  34. - prevents access if user is not in proper group nor a local moderator of the board.
  35. void loadPermissions()
  36. // !!!
  37. array loadMemberData(array members, bool is_name = false, string set = 'normal')
  38. // !!!
  39. bool loadMemberContext(int id_member)
  40. // !!!
  41. void loadTheme(int id_theme = auto_detect)
  42. // !!!
  43. void loadTemplate(string template_name, array style_sheets = array(), bool fatal = true)
  44. - loads a template file with the name template_name from the current,
  45. default, or base theme.
  46. - uses the template_include() function to include the file.
  47. - detects a wrong default theme directory and tries to work around it.
  48. - if fatal is true, dies with an error message if the template cannot
  49. be found.
  50. void loadSubTemplate(string sub_template_name, bool fatal = false)
  51. - loads the sub template specified by sub_template_name, which must be
  52. in an already-loaded template.
  53. - if ?debug is in the query string, shows administrators a marker after
  54. every sub template for debugging purposes.
  55. string loadLanguage(string template_name, string language = default, bool fatal = true, bool force_reload = false)
  56. // !!!
  57. array getBoardParents(int id_parent)
  58. - finds all the parents of id_parent, and that board itself.
  59. - additionally detects the moderators of said boards.
  60. - returns an array of information about the boards found.
  61. string &censorText(string &text, bool force = false)
  62. - censors the passed string.
  63. - if the theme setting allow_no_censored is on, and the theme option
  64. show_no_censored is enabled, does not censor - unless force is set.
  65. - caches the list of censored words to reduce parsing.
  66. void template_include(string filename, bool only_once = false)
  67. - loads the template or language file specified by filename.
  68. - if once is true, only includes the file once (like include_once.)
  69. - uses eval unless disableTemplateEval is enabled.
  70. - outputs a parse error if the file did not exist or contained errors.
  71. - attempts to detect the error and line, and show detailed information.
  72. void loadSession()
  73. // !!!
  74. void loadDatabase()
  75. - takes care of mysql_set_mode, if set.
  76. // !!!
  77. bool sessionOpen(string session_save_path, string session_name)
  78. bool sessionClose()
  79. bool sessionRead(string session_id)
  80. bool sessionWrite(string session_id, string data)
  81. bool sessionDestroy(string session_id)
  82. bool sessionGC(int max_lifetime)
  83. - implementations of PHP's session API.
  84. - handle the session data in the database (more scalable.)
  85. - use the databaseSession_lifetime setting for garbage collection.
  86. - set by loadSession().
  87. void cache_put_data(string key, mixed value, int ttl = 120)
  88. - puts value in the cache under key for ttl seconds.
  89. - may "miss" so shouldn't be depended on, and may go to any of many
  90. various caching servers.
  91. - supports eAccelerator, Turck MMCache, ZPS, and memcached.
  92. mixed cache_get_data(string key, int ttl = 120)
  93. - gets the value from the cache specified by key, so long as it is not
  94. older than ttl seconds.
  95. - may often "miss", so shouldn't be depended on.
  96. - supports the same as cache_put_data().
  97. void get_memcached_server(int recursion_level = 3)
  98. - used by cache_get_data() and cache_put_data().
  99. - attempts to connect to a random server in the cache_memcached
  100. setting.
  101. - recursively calls itself up to recursion_level times.
  102. */
  103. // Load the $modSettings array.
  104. function reloadSettings()
  105. {
  106. global $modSettings, $boarddir, $smcFunc, $txt, $db_character_set, $context, $sourcedir;
  107. // Most database systems have not set UTF-8 as their default input charset.
  108. if (!empty($db_character_set))
  109. $smcFunc['db_query']('set_character_set', '
  110. SET NAMES ' . $db_character_set,
  111. array(
  112. )
  113. );
  114. // Try to load it from the cache first; it'll never get cached if the setting is off.
  115. if (($modSettings = cache_get_data('modSettings', 90)) == null)
  116. {
  117. $request = $smcFunc['db_query']('', '
  118. SELECT variable, value
  119. FROM {db_prefix}settings',
  120. array(
  121. )
  122. );
  123. $modSettings = array();
  124. if (!$request)
  125. db_fatal_error();
  126. while ($row = $smcFunc['db_fetch_row']($request))
  127. $modSettings[$row[0]] = $row[1];
  128. $smcFunc['db_free_result']($request);
  129. // Do a few things to protect against missing settings or settings with invalid values...
  130. if (empty($modSettings['defaultMaxTopics']) || $modSettings['defaultMaxTopics'] <= 0 || $modSettings['defaultMaxTopics'] > 999)
  131. $modSettings['defaultMaxTopics'] = 20;
  132. if (empty($modSettings['defaultMaxMessages']) || $modSettings['defaultMaxMessages'] <= 0 || $modSettings['defaultMaxMessages'] > 999)
  133. $modSettings['defaultMaxMessages'] = 15;
  134. if (empty($modSettings['defaultMaxMembers']) || $modSettings['defaultMaxMembers'] <= 0 || $modSettings['defaultMaxMembers'] > 999)
  135. $modSettings['defaultMaxMembers'] = 30;
  136. if (!empty($modSettings['cache_enable']))
  137. cache_put_data('modSettings', $modSettings, 90);
  138. }
  139. // UTF-8 in regular expressions is unsupported on PHP(win) versions < 4.2.3.
  140. $utf8 = (empty($modSettings['global_character_set']) ? $txt['lang_character_set'] : $modSettings['global_character_set']) === 'UTF-8' && (strpos(strtolower(PHP_OS), 'win') === false || @version_compare(PHP_VERSION, '4.2.3') != -1);
  141. // Set a list of common functions.
  142. $ent_list = empty($modSettings['disableEntityCheck']) ? '&(#\d{1,7}|quot|amp|lt|gt|nbsp);' : '&(#021|quot|amp|lt|gt|nbsp);';
  143. $ent_check = empty($modSettings['disableEntityCheck']) ? array('preg_replace_callback(\'~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~\', \'entity_fix__callback\', ', ')') : array('', '');
  144. // Preg_replace can handle complex characters only for higher PHP versions.
  145. $space_chars = $utf8 ? (@version_compare(PHP_VERSION, '4.3.3') != -1 ? '\x{A0}\x{AD}\x{2000}-\x{200F}\x{201F}\x{202F}\x{3000}\x{FEFF}' : "\xC2\xA0\xC2\xAD\xE2\x80\x80-\xE2\x80\x8F\xE2\x80\x9F\xE2\x80\xAF\xE2\x80\x9F\xE3\x80\x80\xEF\xBB\xBF") : '\x00-\x08\x0B\x0C\x0E-\x19\xA0';
  146. $smcFunc += array(
  147. 'entity_fix' => create_function('$string', '
  148. $num = substr($string, 0, 1) === \'x\' ? hexdec(substr($string, 1)) : (int) $string;
  149. return $num < 0x20 || $num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) || $num === 0x202E || $num === 0x202D ? \'\' : \'&#\' . $num . \';\';'),
  150. 'htmlspecialchars' => create_function('$string, $quote_style = ENT_COMPAT, $charset = \'ISO-8859-1\'', '
  151. global $smcFunc;
  152. return ' . strtr($ent_check[0], array('&' => '&amp;')) . 'htmlspecialchars($string, $quote_style, ' . ($utf8 ? '\'UTF-8\'' : '$charset') . ')' . $ent_check[1] . ';'),
  153. 'htmltrim' => create_function('$string', '
  154. global $smcFunc;
  155. return preg_replace(\'~^(?:[ \t\n\r\x0B\x00' . $space_chars . ']|&nbsp;)+|(?:[ \t\n\r\x0B\x00' . $space_chars . ']|&nbsp;)+$~' . ($utf8 ? 'u' : '') . '\', \'\', ' . implode('$string', $ent_check) . ');'),
  156. 'strlen' => create_function('$string', '
  157. global $smcFunc;
  158. return strlen(preg_replace(\'~' . $ent_list . ($utf8 ? '|.~u' : '~') . '\', \'_\', ' . implode('$string', $ent_check) . '));'),
  159. 'strpos' => create_function('$haystack, $needle, $offset = 0', '
  160. global $smcFunc;
  161. $haystack_arr = preg_split(\'~(&#' . (empty($modSettings['disableEntityCheck']) ? '\d{1,7}' : '021') . ';|&quot;|&amp;|&lt;|&gt;|&nbsp;|.)~' . ($utf8 ? 'u' : '') . '\', ' . implode('$haystack', $ent_check) . ', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  162. $haystack_size = count($haystack_arr);
  163. if (strlen($needle) === 1)
  164. {
  165. $result = array_search($needle, array_slice($haystack_arr, $offset));
  166. return is_int($result) ? $result + $offset : false;
  167. }
  168. else
  169. {
  170. $needle_arr = preg_split(\'~(&#' . (empty($modSettings['disableEntityCheck']) ? '\d{1,7}' : '021') . ';|&quot;|&amp;|&lt;|&gt;|&nbsp;|.)~' . ($utf8 ? 'u' : '') . '\', ' . implode('$needle', $ent_check) . ', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  171. $needle_size = count($needle_arr);
  172. $result = array_search($needle_arr[0], array_slice($haystack_arr, $offset));
  173. while (is_int($result))
  174. {
  175. $offset += $result;
  176. if (array_slice($haystack_arr, $offset, $needle_size) === $needle_arr)
  177. return $offset;
  178. $result = array_search($needle_arr[0], array_slice($haystack_arr, ++$offset));
  179. }
  180. return false;
  181. }'),
  182. 'substr' => create_function('$string, $start, $length = null', '
  183. global $smcFunc;
  184. $ent_arr = preg_split(\'~(&#' . (empty($modSettings['disableEntityCheck']) ? '\d{1,7}' : '021') . ';|&quot;|&amp;|&lt;|&gt;|&nbsp;|.)~' . ($utf8 ? 'u' : '') . '\', ' . implode('$string', $ent_check) . ', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  185. return $length === null ? implode(\'\', array_slice($ent_arr, $start)) : implode(\'\', array_slice($ent_arr, $start, $length));'),
  186. 'strtolower' => $utf8 ? (function_exists('mb_strtolower') ? create_function('$string', '
  187. return mb_strtolower($string, \'UTF-8\');') : create_function('$string', '
  188. global $sourcedir;
  189. require_once($sourcedir . \'/Subs-Charset.php\');
  190. return utf8_strtolower($string);')) : 'strtolower',
  191. 'strtoupper' => $utf8 ? (function_exists('mb_strtoupper') ? create_function('$string', '
  192. return mb_strtoupper($string, \'UTF-8\');') : create_function('$string', '
  193. global $sourcedir;
  194. require_once($sourcedir . \'/Subs-Charset.php\');
  195. return utf8_strtoupper($string);')) : 'strtoupper',
  196. 'truncate' => create_function('$string, $length', (empty($modSettings['disableEntityCheck']) ? '
  197. global $smcFunc;
  198. $string = ' . implode('$string', $ent_check) . ';' : '') . '
  199. preg_match(\'~^(' . $ent_list . '|.){\' . $smcFunc[\'strlen\'](substr($string, 0, $length)) . \'}~'. ($utf8 ? 'u' : '') . '\', $string, $matches);
  200. $string = $matches[0];
  201. while (strlen($string) > $length)
  202. $string = preg_replace(\'~(?:' . $ent_list . '|.)$~'. ($utf8 ? 'u' : '') . '\', \'\', $string);
  203. return $string;'),
  204. 'ucfirst' => $utf8 ? create_function('$string', '
  205. global $smcFunc;
  206. return $smcFunc[\'strtoupper\']($smcFunc[\'substr\']($string, 0, 1)) . $smcFunc[\'substr\']($string, 1);') : 'ucfirst',
  207. 'ucwords' => $utf8 ? create_function('$string', '
  208. global $smcFunc;
  209. $words = preg_split(\'~([\s\r\n\t]+)~\', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
  210. for ($i = 0, $n = count($words); $i < $n; $i += 2)
  211. $words[$i] = $smcFunc[\'ucfirst\']($words[$i]);
  212. return implode(\'\', $words);') : 'ucwords',
  213. );
  214. // Setting the timezone is a requirement for some functions in PHP >= 5.1.
  215. if (isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
  216. date_default_timezone_set($modSettings['default_timezone']);
  217. // Check the load averages?
  218. if (!empty($modSettings['loadavg_enable']))
  219. {
  220. if (($modSettings['load_average'] = cache_get_data('loadavg', 90)) == null)
  221. {
  222. $modSettings['load_average'] = @file_get_contents('/proc/loadavg');
  223. if (!empty($modSettings['load_average']) && preg_match('~^([^ ]+?) ([^ ]+?) ([^ ]+)~', $modSettings['load_average'], $matches) != 0)
  224. $modSettings['load_average'] = (float) $matches[1];
  225. elseif (($modSettings['load_average'] = @`uptime`) != null && preg_match('~load average[s]?: (\d+\.\d+), (\d+\.\d+), (\d+\.\d+)~i', $modSettings['load_average'], $matches) != 0)
  226. $modSettings['load_average'] = (float) $matches[1];
  227. else
  228. unset($modSettings['load_average']);
  229. if (!empty($modSettings['load_average']))
  230. cache_put_data('loadavg', $modSettings['load_average'], 90);
  231. }
  232. if (!empty($modSettings['loadavg_forum']) && !empty($modSettings['load_average']) && $modSettings['load_average'] >= $modSettings['loadavg_forum'])
  233. db_fatal_error(true);
  234. }
  235. // Is post moderation alive and well?
  236. $modSettings['postmod_active'] = isset($modSettings['admin_features']) ? in_array('pm', explode(',', $modSettings['admin_features'])) : true;
  237. // Integration is cool.
  238. if (defined('SMF_INTEGRATION_SETTINGS'))
  239. {
  240. $integration_settings = unserialize(SMF_INTEGRATION_SETTINGS);
  241. foreach ($integration_settings as $hook => $function)
  242. add_integration_function($hook, $function, false);
  243. }
  244. // Any files to pre include?
  245. if (!empty($modSettings['integrate_pre_include']))
  246. {
  247. $pre_includes = explode(',', $modSettings['integrate_pre_include']);
  248. foreach ($pre_includes as $include)
  249. {
  250. $include = strtr(trim($include), array('$boarddir' => $boarddir, '$sourcedir' => $sourcedir));
  251. if (file_exists($include))
  252. require_once($include);
  253. }
  254. }
  255. // Call pre load integration functions.
  256. call_integration_hook('integrate_pre_load');
  257. }
  258. // Load all the important user information...
  259. function loadUserSettings()
  260. {
  261. global $modSettings, $user_settings, $sourcedir, $smcFunc;
  262. global $cookiename, $user_info, $language;
  263. // Check first the integration, then the cookie, and last the session.
  264. if (count($integration_ids = call_integration_hook('integrate_verify_user')) > 0)
  265. {
  266. $id_member = 0;
  267. foreach ($integration_ids as $integration_id)
  268. {
  269. $integration_id = (int) $integration_id;
  270. if ($integration_id > 0)
  271. {
  272. $id_member = $integration_id;
  273. $already_verified = true;
  274. break;
  275. }
  276. }
  277. }
  278. else
  279. $id_member = 0;
  280. if (empty($id_member) && isset($_COOKIE[$cookiename]))
  281. {
  282. // Fix a security hole in PHP 4.3.9 and below...
  283. if (preg_match('~^a:[34]:\{i:0;(i:\d{1,6}|s:[1-8]:"\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\d{1,14};(i:3;i:\d;)?\}$~i', $_COOKIE[$cookiename]) == 1)
  284. {
  285. list ($id_member, $password) = @unserialize($_COOKIE[$cookiename]);
  286. $id_member = !empty($id_member) && strlen($password) > 0 ? (int) $id_member : 0;
  287. }
  288. else
  289. $id_member = 0;
  290. }
  291. elseif (empty($id_member) && isset($_SESSION['login_' . $cookiename]) && ($_SESSION['USER_AGENT'] == $_SERVER['HTTP_USER_AGENT'] || !empty($modSettings['disableCheckUA'])))
  292. {
  293. // !!! Perhaps we can do some more checking on this, such as on the first octet of the IP?
  294. list ($id_member, $password, $login_span) = @unserialize($_SESSION['login_' . $cookiename]);
  295. $id_member = !empty($id_member) && strlen($password) == 40 && $login_span > time() ? (int) $id_member : 0;
  296. }
  297. // Only load this stuff if the user isn't a guest.
  298. if ($id_member != 0)
  299. {
  300. // Is the member data cached?
  301. if (empty($modSettings['cache_enable']) || $modSettings['cache_enable'] < 2 || ($user_settings = cache_get_data('user_settings-' . $id_member, 60)) == null)
  302. {
  303. $request = $smcFunc['db_query']('', '
  304. SELECT mem.*, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type
  305. FROM {db_prefix}members AS mem
  306. LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = {int:id_member})
  307. WHERE mem.id_member = {int:id_member}
  308. LIMIT 1',
  309. array(
  310. 'id_member' => $id_member,
  311. )
  312. );
  313. $user_settings = $smcFunc['db_fetch_assoc']($request);
  314. $smcFunc['db_free_result']($request);
  315. if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
  316. cache_put_data('user_settings-' . $id_member, $user_settings, 60);
  317. }
  318. // Did we find 'im? If not, junk it.
  319. if (!empty($user_settings))
  320. {
  321. // As much as the password should be right, we can assume the integration set things up.
  322. if (!empty($already_verified) && $already_verified === true)
  323. $check = true;
  324. // SHA-1 passwords should be 40 characters long.
  325. elseif (strlen($password) == 40)
  326. $check = sha1($user_settings['passwd'] . $user_settings['password_salt']) == $password;
  327. else
  328. $check = false;
  329. // Wrong password or not activated - either way, you're going nowhere.
  330. $id_member = $check && ($user_settings['is_activated'] == 1 || $user_settings['is_activated'] == 11) ? $user_settings['id_member'] : 0;
  331. }
  332. else
  333. $id_member = 0;
  334. // If we no longer have the member maybe they're being all hackey, stop brute force!
  335. if (!$id_member)
  336. {
  337. require_once($sourcedir . '/LogInOut.php');
  338. validatePasswordFlood(!empty($user_settings['id_member']) ? $user_settings['id_member'] : $id_member, !empty($user_settings['passwd_flood']) ? $user_settings['passwd_flood'] : false, $id_member != 0);
  339. }
  340. }
  341. // Found 'im, let's set up the variables.
  342. if ($id_member != 0)
  343. {
  344. // Let's not update the last visit time in these cases...
  345. // 1. SSI doesn't count as visiting the forum.
  346. // 2. RSS feeds and XMLHTTP requests don't count either.
  347. // 3. If it was set within this session, no need to set it again.
  348. // 4. New session, yet updated < five hours ago? Maybe cache can help.
  349. if (SMF != 'SSI' && !isset($_REQUEST['xml']) && (!isset($_REQUEST['action']) || $_REQUEST['action'] != '.xml') && empty($_SESSION['id_msg_last_visit']) && (empty($modSettings['cache_enable']) || ($_SESSION['id_msg_last_visit'] = cache_get_data('user_last_visit-' . $id_member, 5 * 3600)) === null))
  350. {
  351. // Do a quick query to make sure this isn't a mistake.
  352. $result = $smcFunc['db_query']('', '
  353. SELECT poster_time
  354. FROM {db_prefix}messages
  355. WHERE id_msg = {int:id_msg}
  356. LIMIT 1',
  357. array(
  358. 'id_msg' => $user_settings['id_msg_last_visit'],
  359. )
  360. );
  361. list ($visitTime) = $smcFunc['db_fetch_row']($result);
  362. $smcFunc['db_free_result']($result);
  363. $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
  364. // If it was *at least* five hours ago...
  365. if ($visitTime < time() - 5 * 3600)
  366. {
  367. updateMemberData($id_member, array('id_msg_last_visit' => (int) $modSettings['maxMsgID'], 'last_login' => time(), 'member_ip' => $_SERVER['REMOTE_ADDR'], 'member_ip2' => $_SERVER['BAN_CHECK_IP']));
  368. $user_settings['last_login'] = time();
  369. if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
  370. cache_put_data('user_settings-' . $id_member, $user_settings, 60);
  371. if (!empty($modSettings['cache_enable']))
  372. cache_put_data('user_last_visit-' . $id_member, $_SESSION['id_msg_last_visit'], 5 * 3600);
  373. }
  374. }
  375. elseif (empty($_SESSION['id_msg_last_visit']))
  376. $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
  377. $username = $user_settings['member_name'];
  378. if (empty($user_settings['additional_groups']))
  379. $user_info = array(
  380. 'groups' => array($user_settings['id_group'], $user_settings['id_post_group'])
  381. );
  382. else
  383. $user_info = array(
  384. 'groups' => array_merge(
  385. array($user_settings['id_group'], $user_settings['id_post_group']),
  386. explode(',', $user_settings['additional_groups'])
  387. )
  388. );
  389. // Because history has proven that it is possible for groups to go bad - clean up in case.
  390. foreach ($user_info['groups'] as $k => $v)
  391. $user_info['groups'][$k] = (int) $v;
  392. // This is a logged in user, so definitely not a spider.
  393. $user_info['possibly_robot'] = false;
  394. }
  395. // If the user is a guest, initialize all the critical user settings.
  396. else
  397. {
  398. // This is what a guest's variables should be.
  399. $username = '';
  400. $user_info = array('groups' => array(-1));
  401. $user_settings = array();
  402. if (isset($_COOKIE[$cookiename]))
  403. $_COOKIE[$cookiename] = '';
  404. // Do we perhaps think this is a search robot? Check every five minutes just in case...
  405. if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300))
  406. {
  407. require_once($sourcedir . '/ManageSearchEngines.php');
  408. $user_info['possibly_robot'] = SpiderCheck();
  409. }
  410. elseif (!empty($modSettings['spider_mode']))
  411. $user_info['possibly_robot'] = isset($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0;
  412. // If we haven't turned on proper spider hunts then have a guess!
  413. else
  414. {
  415. $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  416. $user_info['possibly_robot'] = (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla') === false && strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') === false) || strpos($ci_user_agent, 'googlebot') !== false || strpos($ci_user_agent, 'slurp') !== false || strpos($ci_user_agent, 'crawl') !== false;
  417. }
  418. }
  419. // Set up the $user_info array.
  420. $user_info += array(
  421. 'id' => $id_member,
  422. 'username' => $username,
  423. 'name' => isset($user_settings['real_name']) ? $user_settings['real_name'] : '',
  424. 'email' => isset($user_settings['email_address']) ? $user_settings['email_address'] : '',
  425. 'passwd' => isset($user_settings['passwd']) ? $user_settings['passwd'] : '',
  426. 'language' => empty($user_settings['lngfile']) || empty($modSettings['userLanguage']) ? $language : $user_settings['lngfile'],
  427. 'is_guest' => $id_member == 0,
  428. 'is_admin' => in_array(1, $user_info['groups']),
  429. 'theme' => empty($user_settings['id_theme']) ? 0 : $user_settings['id_theme'],
  430. 'last_login' => empty($user_settings['last_login']) ? 0 : $user_settings['last_login'],
  431. 'ip' => $_SERVER['REMOTE_ADDR'],
  432. 'ip2' => $_SERVER['BAN_CHECK_IP'],
  433. 'posts' => empty($user_settings['posts']) ? 0 : $user_settings['posts'],
  434. 'time_format' => empty($user_settings['time_format']) ? $modSettings['time_format'] : $user_settings['time_format'],
  435. 'time_offset' => empty($user_settings['time_offset']) ? 0 : $user_settings['time_offset'],
  436. 'avatar' => array(
  437. 'url' => isset($user_settings['avatar']) ? $user_settings['avatar'] : '',
  438. 'filename' => empty($user_settings['filename']) ? '' : $user_settings['filename'],
  439. 'custom_dir' => !empty($user_settings['attachment_type']) && $user_settings['attachment_type'] == 1,
  440. 'id_attach' => isset($user_settings['id_attach']) ? $user_settings['id_attach'] : 0
  441. ),
  442. 'smiley_set' => isset($user_settings['smiley_set']) ? $user_settings['smiley_set'] : '',
  443. 'messages' => empty($user_settings['instant_messages']) ? 0 : $user_settings['instant_messages'],
  444. 'unread_messages' => empty($user_settings['unread_messages']) ? 0 : $user_settings['unread_messages'],
  445. 'total_time_logged_in' => empty($user_settings['total_time_logged_in']) ? 0 : $user_settings['total_time_logged_in'],
  446. 'buddies' => !empty($modSettings['enable_buddylist']) && !empty($user_settings['buddy_list']) ? explode(',', $user_settings['buddy_list']) : array(),
  447. 'ignoreboards' => !empty($user_settings['ignore_boards']) && !empty($modSettings['allow_ignore_boards']) ? explode(',', $user_settings['ignore_boards']) : array(),
  448. 'ignoreusers' => !empty($user_settings['pm_ignore_list']) ? explode(',', $user_settings['pm_ignore_list']) : array(),
  449. 'warning' => isset($user_settings['warning']) ? $user_settings['warning'] : 0,
  450. 'permissions' => array(),
  451. );
  452. $user_info['groups'] = array_unique($user_info['groups']);
  453. // Make sure that the last item in the ignore boards array is valid. If the list was too long it could have an ending comma that could cause problems.
  454. if (!empty($user_info['ignoreboards']) && empty($user_info['ignoreboards'][$tmp = count($user_info['ignoreboards']) - 1]))
  455. unset($user_info['ignoreboards'][$tmp]);
  456. // Do we have any languages to validate this?
  457. if (!empty($modSettings['userLanguage']) && (!empty($_GET['language']) || !empty($_SESSION['language'])))
  458. $languages = getLanguages();
  459. // Allow the user to change their language if its valid.
  460. if (!empty($modSettings['userLanguage']) && !empty($_GET['language']) && isset($languages[strtr($_GET['language'], './\\:', '____')]))
  461. {
  462. $user_info['language'] = strtr($_GET['language'], './\\:', '____');
  463. $_SESSION['language'] = $user_info['language'];
  464. }
  465. elseif (!empty($modSettings['userLanguage']) && !empty($_SESSION['language']) && isset($languages[strtr($_SESSION['language'], './\\:', '____')]))
  466. $user_info['language'] = strtr($_SESSION['language'], './\\:', '____');
  467. // Just build this here, it makes it easier to change/use - administrators can see all boards.
  468. if ($user_info['is_admin'])
  469. $user_info['query_see_board'] = '1=1';
  470. // Otherwise just the groups in $user_info['groups'].
  471. else
  472. $user_info['query_see_board'] = '(FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0' . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')';
  473. // Build the list of boards they WANT to see.
  474. // This will take the place of query_see_boards in certain spots, so it better include the boards they can see also
  475. // If they aren't ignoring any boards then they want to see all the boards they can see
  476. if (empty($user_info['ignoreboards']))
  477. $user_info['query_wanna_see_board'] = $user_info['query_see_board'];
  478. // Ok I guess they don't want to see all the boards
  479. else
  480. $user_info['query_wanna_see_board'] = '(' . $user_info['query_see_board'] . ' AND b.id_board NOT IN (' . implode(',', $user_info['ignoreboards']) . '))';
  481. }
  482. // Check for moderators and see if they have access to the board.
  483. function loadBoard()
  484. {
  485. global $txt, $scripturl, $context, $modSettings;
  486. global $board_info, $board, $topic, $user_info, $smcFunc;
  487. // Assume they are not a moderator.
  488. $user_info['is_mod'] = false;
  489. $context['user']['is_mod'] = &$user_info['is_mod'];
  490. // Start the linktree off empty..
  491. $context['linktree'] = array();
  492. // Have they by chance specified a message id but nothing else?
  493. if (empty($_REQUEST['action']) && empty($topic) && empty($board) && !empty($_REQUEST['msg']))
  494. {
  495. // Make sure the message id is really an int.
  496. $_REQUEST['msg'] = (int) $_REQUEST['msg'];
  497. // Looking through the message table can be slow, so try using the cache first.
  498. if (($topic = cache_get_data('msg_topic-' . $_REQUEST['msg'], 120)) === NULL)
  499. {
  500. $request = $smcFunc['db_query']('', '
  501. SELECT id_topic
  502. FROM {db_prefix}messages
  503. WHERE id_msg = {int:id_msg}
  504. LIMIT 1',
  505. array(
  506. 'id_msg' => $_REQUEST['msg'],
  507. )
  508. );
  509. // So did it find anything?
  510. if ($smcFunc['db_num_rows']($request))
  511. {
  512. list ($topic) = $smcFunc['db_fetch_row']($request);
  513. $smcFunc['db_free_result']($request);
  514. // Save save save.
  515. cache_put_data('msg_topic-' . $_REQUEST['msg'], $topic, 120);
  516. }
  517. }
  518. // Remember redirection is the key to avoiding fallout from your bosses.
  519. if (!empty($topic))
  520. redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg']);
  521. else
  522. {
  523. loadPermissions();
  524. loadTheme();
  525. fatal_lang_error('topic_gone', false);
  526. }
  527. }
  528. // Load this board only if it is specified.
  529. if (empty($board) && empty($topic))
  530. {
  531. $board_info = array('moderators' => array());
  532. return;
  533. }
  534. if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
  535. {
  536. // !!! SLOW?
  537. if (!empty($topic))
  538. $temp = cache_get_data('topic_board-' . $topic, 120);
  539. else
  540. $temp = cache_get_data('board-' . $board, 120);
  541. if (!empty($temp))
  542. {
  543. $board_info = $temp;
  544. $board = $board_info['id'];
  545. }
  546. }
  547. if (empty($temp))
  548. {
  549. $request = $smcFunc['db_query']('', '
  550. SELECT
  551. c.id_cat, b.name AS bname, b.description, b.num_topics, b.member_groups,
  552. b.id_parent, c.name AS cname, IFNULL(mem.id_member, 0) AS id_moderator,
  553. mem.real_name' . (!empty($topic) ? ', b.id_board' : '') . ', b.child_level,
  554. b.id_theme, b.override_theme, b.count_posts, b.id_profile, b.redirect,
  555. b.unapproved_topics, b.unapproved_posts' . (!empty($topic) ? ', t.approved, t.id_member_started' : '') . '
  556. FROM {db_prefix}boards AS b' . (!empty($topic) ? '
  557. INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})' : '') . '
  558. LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
  559. LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = {raw:board_link})
  560. LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
  561. WHERE b.id_board = {raw:board_link}',
  562. array(
  563. 'current_topic' => $topic,
  564. 'board_link' => empty($topic) ? $smcFunc['db_quote']('{int:current_board}', array('current_board' => $board)) : 't.id_board',
  565. )
  566. );
  567. // If there aren't any, skip.
  568. if ($smcFunc['db_num_rows']($request) > 0)
  569. {
  570. $row = $smcFunc['db_fetch_assoc']($request);
  571. // Set the current board.
  572. if (!empty($row['id_board']))
  573. $board = $row['id_board'];
  574. // Basic operating information. (globals... :/)
  575. $board_info = array(
  576. 'id' => $board,
  577. 'moderators' => array(),
  578. 'cat' => array(
  579. 'id' => $row['id_cat'],
  580. 'name' => $row['cname']
  581. ),
  582. 'name' => $row['bname'],
  583. 'description' => $row['description'],
  584. 'num_topics' => $row['num_topics'],
  585. 'unapproved_topics' => $row['unapproved_topics'],
  586. 'unapproved_posts' => $row['unapproved_posts'],
  587. 'unapproved_user_topics' => 0,
  588. 'parent_boards' => getBoardParents($row['id_parent']),
  589. 'parent' => $row['id_parent'],
  590. 'child_level' => $row['child_level'],
  591. 'theme' => $row['id_theme'],
  592. 'override_theme' => !empty($row['override_theme']),
  593. 'profile' => $row['id_profile'],
  594. 'redirect' => $row['redirect'],
  595. 'posts_count' => empty($row['count_posts']),
  596. 'cur_topic_approved' => empty($topic) || $row['approved'],
  597. 'cur_topic_starter' => empty($topic) ? 0 : $row['id_member_started'],
  598. );
  599. // Load the membergroups allowed, and check permissions.
  600. $board_info['groups'] = $row['member_groups'] == '' ? array() : explode(',', $row['member_groups']);
  601. do
  602. {
  603. if (!empty($row['id_moderator']))
  604. $board_info['moderators'][$row['id_moderator']] = array(
  605. 'id' => $row['id_moderator'],
  606. 'name' => $row['real_name'],
  607. 'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'],
  608. 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>'
  609. );
  610. }
  611. while ($row = $smcFunc['db_fetch_assoc']($request));
  612. // If the board only contains unapproved posts and the user isn't an approver then they can't see any topics.
  613. // If that is the case do an additional check to see if they have any topics waiting to be approved.
  614. if ($board_info['num_topics'] == 0 && $modSettings['postmod_active'] && !allowedTo('approve_posts'))
  615. {
  616. $smcFunc['db_free_result']($request); // Free the previous result
  617. $request = $smcFunc['db_query']('', '
  618. SELECT COUNT(id_topic)
  619. FROM {db_prefix}topics
  620. WHERE id_member_started={int:id_member}
  621. AND approved = {int:unapproved}
  622. AND id_board = {int:board}',
  623. array(
  624. 'id_member' => $user_info['id'],
  625. 'unapproved' => 0,
  626. 'board' => $board,
  627. )
  628. );
  629. list ($board_info['unapproved_user_topics']) = $smcFunc['db_fetch_row']($request);
  630. }
  631. if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
  632. {
  633. // !!! SLOW?
  634. if (!empty($topic))
  635. cache_put_data('topic_board-' . $topic, $board_info, 120);
  636. cache_put_data('board-' . $board, $board_info, 120);
  637. }
  638. }
  639. else
  640. {
  641. // Otherwise the topic is invalid, there are no moderators, etc.
  642. $board_info = array(
  643. 'moderators' => array(),
  644. 'error' => 'exist'
  645. );
  646. $topic = null;
  647. $board = 0;
  648. }
  649. $smcFunc['db_free_result']($request);
  650. }
  651. if (!empty($topic))
  652. $_GET['board'] = (int) $board;
  653. if (!empty($board))
  654. {
  655. // Now check if the user is a moderator.
  656. $user_info['is_mod'] = isset($board_info['moderators'][$user_info['id']]);
  657. if (count(array_intersect($user_info['groups'], $board_info['groups'])) == 0 && !$user_info['is_admin'])
  658. $board_info['error'] = 'access';
  659. // Build up the linktree.
  660. $context['linktree'] = array_merge(
  661. $context['linktree'],
  662. array(array(
  663. 'url' => $scripturl . '#c' . $board_info['cat']['id'],
  664. 'name' => $board_info['cat']['name']
  665. )),
  666. array_reverse($board_info['parent_boards']),
  667. array(array(
  668. 'url' => $scripturl . '?board=' . $board . '.0',
  669. 'name' => $board_info['name']
  670. ))
  671. );
  672. }
  673. // Set the template contextual information.
  674. $context['user']['is_mod'] = &$user_info['is_mod'];
  675. $context['current_topic'] = $topic;
  676. $context['current_board'] = $board;
  677. // Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
  678. if (!empty($board_info['error']) && ($board_info['error'] != 'access' || !$user_info['is_mod']))
  679. {
  680. // The permissions and theme need loading, just to make sure everything goes smoothly.
  681. loadPermissions();
  682. loadTheme();
  683. $_GET['board'] = '';
  684. $_GET['topic'] = '';
  685. // The linktree should not give the game away mate!
  686. $context['linktree'] = array(
  687. array(
  688. 'url' => $scripturl,
  689. 'name' => $context['forum_name_html_safe']
  690. )
  691. );
  692. // If it's a prefetching agent or we're requesting an attachment.
  693. if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') || (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach'))
  694. {
  695. ob_end_clean();
  696. header('HTTP/1.1 403 Forbidden');
  697. die;
  698. }
  699. elseif ($user_info['is_guest'])
  700. {
  701. loadLanguage('Errors');
  702. is_not_guest($txt['topic_gone']);
  703. }
  704. else
  705. fatal_lang_error('topic_gone', false);
  706. }
  707. if ($user_info['is_mod'])
  708. $user_info['groups'][] = 3;
  709. }
  710. // Load this user's permissions.
  711. function loadPermissions()
  712. {
  713. global $user_info, $board, $board_info, $modSettings, $smcFunc, $sourcedir;
  714. if ($user_info['is_admin'])
  715. {
  716. banPermissions();
  717. return;
  718. }
  719. if (!empty($modSettings['cache_enable']))
  720. {
  721. $cache_groups = $user_info['groups'];
  722. asort($cache_groups);
  723. $cache_groups = implode(',', $cache_groups);
  724. // If it's a spider then cache it different.
  725. if ($user_info['possibly_robot'])
  726. $cache_groups .= '-spider';
  727. if ($modSettings['cache_enable'] >= 2 && !empty($board) && ($temp = cache_get_data('permissions:' . $cache_groups . ':' . $board, 240)) != null && time() - 240 > $modSettings['settings_updated'])
  728. {
  729. list ($user_info['permissions']) = $temp;
  730. banPermissions();
  731. return;
  732. }
  733. elseif (($temp = cache_get_data('permissions:' . $cache_groups, 240)) != null && time() - 240 > $modSettings['settings_updated'])
  734. list ($user_info['permissions'], $removals) = $temp;
  735. }
  736. // If it is detected as a robot, and we are restricting permissions as a special group - then implement this.
  737. $spider_restrict = $user_info['possibly_robot'] && !empty($modSettings['spider_group']) ? ' OR (id_group = {int:spider_group} AND add_deny = 0)' : '';
  738. if (empty($user_info['permissions']))
  739. {
  740. // Get the general permissions.
  741. $request = $smcFunc['db_query']('', '
  742. SELECT permission, add_deny
  743. FROM {db_prefix}permissions
  744. WHERE id_group IN ({array_int:member_groups})
  745. ' . $spider_restrict,
  746. array(
  747. 'member_groups' => $user_info['groups'],
  748. 'spider_group' => !empty($modSettings['spider_group']) ? $modSettings['spider_group'] : 0,
  749. )
  750. );
  751. $removals = array();
  752. while ($row = $smcFunc['db_fetch_assoc']($request))
  753. {
  754. if (empty($row['add_deny']))
  755. $removals[] = $row['permission'];
  756. else
  757. $user_info['permissions'][] = $row['permission'];
  758. }
  759. $smcFunc['db_free_result']($request);
  760. if (isset($cache_groups))
  761. cache_put_data('permissions:' . $cache_groups, array($user_info['permissions'], $removals), 240);
  762. }
  763. // Get the board permissions.
  764. if (!empty($board))
  765. {
  766. // Make sure the board (if any) has been loaded by loadBoard().
  767. if (!isset($board_info['profile']))
  768. fatal_lang_error('no_board');
  769. $request = $smcFunc['db_query']('', '
  770. SELECT permission, add_deny
  771. FROM {db_prefix}board_permissions
  772. WHERE (id_group IN ({array_int:member_groups})
  773. ' . $spider_restrict . ')
  774. AND id_profile = {int:id_profile}',
  775. array(
  776. 'member_groups' => $user_info['groups'],
  777. 'id_profile' => $board_info['profile'],
  778. 'spider_group' => !empty($modSettings['spider_group']) ? $modSettings['spider_group'] : 0,
  779. )
  780. );
  781. while ($row = $smcFunc['db_fetch_assoc']($request))
  782. {
  783. if (empty($row['add_deny']))
  784. $removals[] = $row['permission'];
  785. else
  786. $user_info['permissions'][] = $row['permission'];
  787. }
  788. $smcFunc['db_free_result']($request);
  789. }
  790. // Remove all the permissions they shouldn't have ;).
  791. if (!empty($modSettings['permission_enable_deny']))
  792. $user_info['permissions'] = array_diff($user_info['permissions'], $removals);
  793. if (isset($cache_groups) && !empty($board) && $modSettings['cache_enable'] >= 2)
  794. cache_put_data('permissions:' . $cache_groups . ':' . $board, array($user_info['permissions'], null), 240);
  795. // Banned? Watch, don't touch..
  796. banPermissions();
  797. // Load the mod cache so we can know what additional boards they should see, but no sense in doing it for guests
  798. if (!$user_info['is_guest'])
  799. {
  800. if (!isset($_SESSION['mc']) || $_SESSION['mc']['time'] <= $modSettings['settings_updated'])
  801. {
  802. require_once($sourcedir . '/Subs-Auth.php');
  803. rebuildModCache();
  804. }
  805. else
  806. $user_info['mod_cache'] = $_SESSION['mc'];
  807. }
  808. }
  809. // Loads an array of users' data by ID or member_name.
  810. function loadMemberData($users, $is_name = false, $set = 'normal')
  811. {
  812. global $user_profile, $modSettings, $board_info, $smcFunc;
  813. // Can't just look for no users :P.
  814. if (empty($users))
  815. return false;
  816. // Make sure it's an array.
  817. $users = !is_array($users) ? array($users) : array_unique($users);
  818. $loaded_ids = array();
  819. if (!$is_name && !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 3)
  820. {
  821. $users = array_values($users);
  822. for ($i = 0, $n = count($users); $i < $n; $i++)
  823. {
  824. $data = cache_get_data('member_data-' . $set . '-' . $users[$i], 240);
  825. if ($data == null)
  826. continue;
  827. $loaded_ids[] = $data['id_member'];
  828. $user_profile[$data['id_member']] = $data;
  829. unset($users[$i]);
  830. }
  831. }
  832. if ($set == 'normal')
  833. {
  834. $select_columns = '
  835. IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type,
  836. mem.signature, mem.personal_text, mem.location, mem.gender, mem.avatar, mem.id_member, mem.member_name,
  837. mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url,
  838. mem.birthdate, mem.member_ip, mem.member_ip2, mem.icq, mem.aim, mem.yim, mem.msn, mem.posts, mem.last_login,
  839. mem.karma_good, mem.id_post_group, mem.karma_bad, mem.lngfile, mem.id_group, mem.time_offset, mem.show_online,
  840. mem.buddy_list, mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group,
  841. pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group, mem.is_activated, mem.warning,
  842. CASE WHEN mem.id_group = 0 OR mg.stars = {string:blank_string} THEN pg.stars ELSE mg.stars END AS stars' . (!empty($modSettings['titlesEnable']) ? ',
  843. mem.usertitle' : '');
  844. $select_tables = '
  845. LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)
  846. LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member)
  847. LEFT JOIN {db_prefix}membergroups AS pg ON (pg.id_group = mem.id_post_group)
  848. LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)';
  849. }
  850. elseif ($set == 'profile')
  851. {
  852. $select_columns = '
  853. IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type,
  854. mem.signature, mem.personal_text, mem.location, mem.gender, mem.avatar, mem.id_member, mem.member_name,
  855. mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url,
  856. mem.openid_uri, mem.birthdate, mem.icq, mem.aim, mem.yim, mem.msn, mem.posts, mem.last_login, mem.karma_good,
  857. mem.karma_bad, mem.member_ip, mem.member_ip2, mem.lngfile, mem.id_group, mem.id_theme, mem.buddy_list,
  858. mem.pm_ignore_list, mem.pm_email_notify, mem.pm_receive_from, mem.time_offset' . (!empty($modSettings['titlesEnable']) ? ', mem.usertitle' : '') . ',
  859. mem.time_format, mem.secret_question, mem.is_activated, mem.additional_groups, mem.smiley_set, mem.show_online,
  860. mem.total_time_logged_in, mem.id_post_group, mem.notify_announcements, mem.notify_regularity, mem.notify_send_body,
  861. mem.notify_types, lo.url, mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group,
  862. pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group, mem.ignore_boards, mem.warning,
  863. CASE WHEN mem.id_group = 0 OR mg.stars = {string:blank_string} THEN pg.stars ELSE mg.stars END AS stars, mem.password_salt, mem.pm_prefs';
  864. $select_tables = '
  865. LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)
  866. LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member)
  867. LEFT JOIN {db_prefix}membergroups AS pg ON (pg.id_group = mem.id_post_group)
  868. LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)';
  869. }
  870. elseif ($set == 'minimal')
  871. {
  872. $select_columns = '
  873. mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.hide_email, mem.date_registered,
  874. mem.posts, mem.last_login, mem.member_ip, mem.member_ip2, mem.lngfile, mem.id_group';
  875. $select_tables = '';
  876. }
  877. else
  878. trigger_error('loadMemberData(): Invalid member data set \'' . $set . '\'', E_USER_WARNING);
  879. if (!empty($users))
  880. {
  881. // Load the member's data.
  882. $request = $smcFunc['db_query']('', '
  883. SELECT' . $select_columns . '
  884. FROM {db_prefix}members AS mem' . $select_tables . '
  885. WHERE mem.' . ($is_name ? 'member_name' : 'id_member') . (count($users) == 1 ? ' = {' . ($is_name ? 'string' : 'int') . ':users}' : ' IN ({' . ($is_name ? 'array_string' : 'array_int') . ':users})'),
  886. array(
  887. 'blank_string' => '',
  888. 'users' => count($users) == 1 ? current($users) : $users,
  889. )
  890. );
  891. $new_loaded_ids = array();
  892. while ($row = $smcFunc['db_fetch_assoc']($request))
  893. {
  894. $new_loaded_ids[] = $row['id_member'];
  895. $loaded_ids[] = $row['id_member'];
  896. $row['options'] = array();
  897. $user_profile[$row['id_member']] = $row;
  898. }
  899. $smcFunc['db_free_result']($request);
  900. }
  901. if (!empty($new_loaded_ids) && $set !== 'minimal')
  902. {
  903. $request = $smcFunc['db_query']('', '
  904. SELECT *
  905. FROM {db_prefix}themes
  906. WHERE id_member' . (count($new_loaded_ids) == 1 ? ' = {int:loaded_ids}' : ' IN ({array_int:loaded_ids})'),
  907. array(
  908. 'loaded_ids' => count($new_loaded_ids) == 1 ? $new_loaded_ids[0] : $new_loaded_ids,
  909. )
  910. );
  911. while ($row = $smcFunc['db_fetch_assoc']($request))
  912. $user_profile[$row['id_member']]['options'][$row['variable']] = $row['value'];
  913. $smcFunc['db_free_result']($request);
  914. }
  915. if (!empty($new_loaded_ids) && !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 3)
  916. {
  917. for ($i = 0, $n = count($new_loaded_ids); $i < $n; $i++)
  918. cache_put_data('member_data-' . $set . '-' . $new_loaded_ids[$i], $user_profile[$new_loaded_ids[$i]], 240);
  919. }
  920. // Are we loading any moderators? If so, fix their group data...
  921. if (!empty($loaded_ids) && !empty($board_info['moderators']) && $set === 'normal' && count($temp_mods = array_intersect($loaded_ids, array_keys($board_info['moderators']))) !== 0)
  922. {
  923. if (($row = cache_get_data('moderator_group_info', 480)) == null)
  924. {
  925. $request = $smcFunc['db_query']('', '
  926. SELECT group_name AS member_group, online_color AS member_group_color, stars
  927. FROM {db_prefix}membergroups
  928. WHERE id_group = {int:moderator_group}
  929. LIMIT 1',
  930. array(
  931. 'moderator_group' => 3,
  932. )
  933. );
  934. $row = $smcFunc['db_fetch_assoc']($request);
  935. $smcFunc['db_free_result']($request);
  936. cache_put_data('moderator_group_info', $row, 480);
  937. }
  938. foreach ($temp_mods as $id)
  939. {
  940. // By popular demand, don't show admins or global moderators as moderators.
  941. if ($user_profile[$id]['id_group'] != 1 && $user_profile[$id]['id_group'] != 2)
  942. $user_profile[$id]['member_group'] = $row['member_group'];
  943. // If the Moderator group has no color or stars, but their group does... don't overwrite.
  944. if (!empty($row['stars']))
  945. $user_profile[$id]['stars'] = $row['stars'];
  946. if (!empty($row['member_group_color']))
  947. $user_profile[$id]['member_group_color'] = $row['member_group_color'];
  948. }
  949. }
  950. return empty($loaded_ids) ? false : $loaded_ids;
  951. }
  952. // Loads the user's basic values... meant for template/theme usage.
  953. function loadMemberContext($user, $display_custom_fields = false)
  954. {
  955. global $memberContext, $user_profile, $txt, $scripturl, $user_info;
  956. global $context, $modSettings, $board_info, $settings;
  957. global $smcFunc;
  958. static $dataLoaded = array();
  959. // If this person's data is already loaded, skip it.
  960. if (isset($dataLoaded[$user]))
  961. return true;
  962. // We can't load guests or members not loaded by loadMemberData()!
  963. if ($user == 0)
  964. return false;
  965. if (!isset($user_profile[$user]))
  966. {
  967. trigger_error('loadMemberContext(): member id ' . $user . ' not previously loaded by loadMemberData()', E_USER_WARNING);
  968. return false;
  969. }
  970. // Well, it's loaded now anyhow.
  971. $dataLoaded[$user] = true;
  972. $profile = $user_profile[$user];
  973. // Censor everything.
  974. censorText($profile['signature']);
  975. censorText($profile['personal_text']);
  976. censorText($profile['location']);
  977. // Set things up to be used before hand.
  978. $gendertxt = $profile['gender'] == 2 ? $txt['female'] : ($profile['gender'] == 1 ? $txt['male'] : '');
  979. $profile['signature'] = str_replace(array("\n", "\r"), array('<br />', ''), $profile['signature']);
  980. $profile['signature'] = parse_bbc($profile['signature'], true, 'sig' . $profile['id_member']);
  981. $profile['is_online'] = (!empty($profile['show_online']) || allowedTo('moderate_forum')) && $profile['is_online'] > 0;
  982. $profile['stars'] = empty($profile['stars']) ? array('', '') : explode('#', $profile['stars']);
  983. // Setup the buddy status here (One whole in_array call saved :P)
  984. $profile['buddy'] = in_array($profile['id_member'], $user_info['buddies']);
  985. $buddy_list = !empty($profile['buddy_list']) ? explode(',', $profile['buddy_list']) : array();
  986. // If we're always html resizing, assume it's too large.
  987. if ($modSettings['avatar_action_too_large'] == 'option_html_resize' || $modSettings['avatar_action_too_large'] == 'option_js_resize')
  988. {
  989. $avatar_width = !empty($modSettings['avatar_max_width_external']) ? ' width="' . $modSettings['avatar_max_width_external'] . '"' : '';
  990. $avatar_height = !empty($modSettings['avatar_max_height_external']) ? ' height="' . $modSettings['avatar_max_height_external'] . '"' : '';
  991. }
  992. else
  993. {
  994. $avatar_width = '';
  995. $avatar_height = '';
  996. }
  997. // What a monstrous array...
  998. $memberContext[$user] = array(
  999. 'username' => $profile['member_name'],
  1000. 'name' => $profile['real_name'],
  1001. 'id' => $profile['id_member'],
  1002. 'is_buddy' => $profile['buddy'],
  1003. 'is_reverse_buddy' => in_array($user_info['id'], $buddy_list),
  1004. 'buddies' => $buddy_list,
  1005. 'title' => !empty($modSettings['titlesEnable']) ? $profile['usertitle'] : '',
  1006. 'href' => $scripturl . '?action=profile;u=' . $profile['id_member'],
  1007. 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $profile['id_member'] . '" title="' . $txt['profile_of'] . ' ' . $profile['real_name'] . '">' . $profile['real_name'] . '</a>',
  1008. 'email' => $profile['email_address'],
  1009. 'show_email' => showEmailAddress(!empty($profile['hide_email']), $profile['id_member']),
  1010. 'registered' => empty($profile['date_registered']) ? $txt['not_applicable'] : timeformat($profile['date_registered']),
  1011. 'registered_timestamp' => empty($profile['date_registered']) ? 0 : forum_time(true, $profile['date_registered']),
  1012. 'blurb' => $profile['personal_text'],
  1013. 'gender' => array(
  1014. 'name' => $gendertxt,
  1015. 'image' => !empty($profile['gender']) ? '<img class="gender" src="' . $settings['images_url'] . '/' . ($profile['gender'] == 1 ? 'Male' : 'Female') . '.gif" alt="' . $gendertxt . '" />' : ''
  1016. ),
  1017. 'website' => array(
  1018. 'title' => $profile['website_title'],
  1019. 'url' => $profile['website_url'],
  1020. ),
  1021. 'birth_date' => empty($profile['birthdate']) || $profile['birthdate'] === '0001-01-01' ? '0000-00-00' : (substr($profile['birthdate'], 0, 4) === '0004' ? '0000' . substr($profile['birthdate'], 4) : $profile['birthdate']),
  1022. 'signature' => $profile['signature'],
  1023. 'location' => $profile['location'],
  1024. 'icq' => $profile['icq'] != '' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
  1025. 'name' => $profile['icq'],
  1026. 'href' => 'http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'],
  1027. 'link' => '<a class="icq new_win" href="http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'] . '" target="_blank" title="' . $txt['icq_title'] . ' - ' . $profile['icq'] . '"><img src="http://status.icq.com/online.gif?img=5&amp;icq=' . $profile['icq'] . '" alt="' . $txt['icq_title'] . ' - ' . $profile['icq'] . '" width="18" height="18" /></a>',
  1028. 'link_text' => '<a class="icq extern" href="http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'] . '" title="' . $txt['icq_title'] . ' - ' . $profile['icq'] . '">' . $profile['icq'] . '</a>',
  1029. ) : array('name' => '', 'add' => '', 'href' => '', 'link' => '', 'link_text' => ''),
  1030. 'aim' => $profile['aim'] != '' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
  1031. 'name' => $profile['aim'],
  1032. 'href' => 'aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['a…

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