annotate forum/Sources/Load.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
rev   line source
Chris@76 1 <?php
Chris@76 2
Chris@76 3 /**
Chris@76 4 * Simple Machines Forum (SMF)
Chris@76 5 *
Chris@76 6 * @package SMF
Chris@76 7 * @author Simple Machines http://www.simplemachines.org
Chris@76 8 * @copyright 2011 Simple Machines
Chris@76 9 * @license http://www.simplemachines.org/about/smf/license.php BSD
Chris@76 10 *
Chris@76 11 * @version 2.0.3
Chris@76 12 */
Chris@76 13
Chris@76 14 if (!defined('SMF'))
Chris@76 15 die('Hacking attempt...');
Chris@76 16
Chris@76 17 /* This file has the hefty job of loading information for the forum. It uses
Chris@76 18 the following functions:
Chris@76 19
Chris@76 20 void reloadSettings()
Chris@76 21 - loads or reloads the $modSettings array.
Chris@76 22 - loads any integration settings, SMF_INTEGRATION_SETTINGS, etc.
Chris@76 23
Chris@76 24 void loadUserSettings()
Chris@76 25 - sets up the $user_info array
Chris@76 26 - assigns $user_info['query_wanna_see_board'] for what boards the user can see.
Chris@76 27 - first checks for cookie or intergration validation.
Chris@76 28 - uses the current session if no integration function or cookie is found.
Chris@76 29 - checks password length, if member is activated and the login span isn't over.
Chris@76 30 - if validation fails for the user, $id_member is set to 0.
Chris@76 31 - updates the last visit time when needed.
Chris@76 32
Chris@76 33 void loadBoard()
Chris@76 34 - sets up the $board_info array for current board information.
Chris@76 35 - if cache is enabled, the $board_info array is stored in cache.
Chris@76 36 - redirects to appropriate post if only message id is requested.
Chris@76 37 - is only used when inside a topic or board.
Chris@76 38 - determines the local moderators for the board.
Chris@76 39 - adds group id 3 if the user is a local moderator for the board they are in.
Chris@76 40 - prevents access if user is not in proper group nor a local moderator of the board.
Chris@76 41
Chris@76 42 void loadPermissions()
Chris@76 43 // !!!
Chris@76 44
Chris@76 45 array loadMemberData(array members, bool is_name = false, string set = 'normal')
Chris@76 46 // !!!
Chris@76 47
Chris@76 48 bool loadMemberContext(int id_member)
Chris@76 49 // !!!
Chris@76 50
Chris@76 51 void loadTheme(int id_theme = auto_detect)
Chris@76 52 // !!!
Chris@76 53
Chris@76 54 void loadTemplate(string template_name, array style_sheets = array(), bool fatal = true)
Chris@76 55 - loads a template file with the name template_name from the current,
Chris@76 56 default, or base theme.
Chris@76 57 - uses the template_include() function to include the file.
Chris@76 58 - detects a wrong default theme directory and tries to work around it.
Chris@76 59 - if fatal is true, dies with an error message if the template cannot
Chris@76 60 be found.
Chris@76 61
Chris@76 62 void loadSubTemplate(string sub_template_name, bool fatal = false)
Chris@76 63 - loads the sub template specified by sub_template_name, which must be
Chris@76 64 in an already-loaded template.
Chris@76 65 - if ?debug is in the query string, shows administrators a marker after
Chris@76 66 every sub template for debugging purposes.
Chris@76 67
Chris@76 68 string loadLanguage(string template_name, string language = default, bool fatal = true, bool force_reload = false)
Chris@76 69 // !!!
Chris@76 70
Chris@76 71 array getBoardParents(int id_parent)
Chris@76 72 - finds all the parents of id_parent, and that board itself.
Chris@76 73 - additionally detects the moderators of said boards.
Chris@76 74 - returns an array of information about the boards found.
Chris@76 75
Chris@76 76 string &censorText(string &text, bool force = false)
Chris@76 77 - censors the passed string.
Chris@76 78 - if the theme setting allow_no_censored is on, and the theme option
Chris@76 79 show_no_censored is enabled, does not censor - unless force is set.
Chris@76 80 - caches the list of censored words to reduce parsing.
Chris@76 81
Chris@76 82 void template_include(string filename, bool only_once = false)
Chris@76 83 - loads the template or language file specified by filename.
Chris@76 84 - if once is true, only includes the file once (like include_once.)
Chris@76 85 - uses eval unless disableTemplateEval is enabled.
Chris@76 86 - outputs a parse error if the file did not exist or contained errors.
Chris@76 87 - attempts to detect the error and line, and show detailed information.
Chris@76 88
Chris@76 89 void loadSession()
Chris@76 90 // !!!
Chris@76 91
Chris@76 92 void loadDatabase()
Chris@76 93 - takes care of mysql_set_mode, if set.
Chris@76 94 // !!!
Chris@76 95
Chris@76 96 bool sessionOpen(string session_save_path, string session_name)
Chris@76 97 bool sessionClose()
Chris@76 98 bool sessionRead(string session_id)
Chris@76 99 bool sessionWrite(string session_id, string data)
Chris@76 100 bool sessionDestroy(string session_id)
Chris@76 101 bool sessionGC(int max_lifetime)
Chris@76 102 - implementations of PHP's session API.
Chris@76 103 - handle the session data in the database (more scalable.)
Chris@76 104 - use the databaseSession_lifetime setting for garbage collection.
Chris@76 105 - set by loadSession().
Chris@76 106
Chris@76 107 void cache_put_data(string key, mixed value, int ttl = 120)
Chris@76 108 - puts value in the cache under key for ttl seconds.
Chris@76 109 - may "miss" so shouldn't be depended on, and may go to any of many
Chris@76 110 various caching servers.
Chris@76 111 - supports eAccelerator, Turck MMCache, ZPS, and memcached.
Chris@76 112
Chris@76 113 mixed cache_get_data(string key, int ttl = 120)
Chris@76 114 - gets the value from the cache specified by key, so long as it is not
Chris@76 115 older than ttl seconds.
Chris@76 116 - may often "miss", so shouldn't be depended on.
Chris@76 117 - supports the same as cache_put_data().
Chris@76 118
Chris@76 119 void get_memcached_server(int recursion_level = 3)
Chris@76 120 - used by cache_get_data() and cache_put_data().
Chris@76 121 - attempts to connect to a random server in the cache_memcached
Chris@76 122 setting.
Chris@76 123 - recursively calls itself up to recursion_level times.
Chris@76 124 */
Chris@76 125
Chris@76 126 // Load the $modSettings array.
Chris@76 127 function reloadSettings()
Chris@76 128 {
Chris@76 129 global $modSettings, $boarddir, $smcFunc, $txt, $db_character_set, $context, $sourcedir;
Chris@76 130
Chris@76 131 // Most database systems have not set UTF-8 as their default input charset.
Chris@76 132 if (!empty($db_character_set))
Chris@76 133 $smcFunc['db_query']('set_character_set', '
Chris@76 134 SET NAMES ' . $db_character_set,
Chris@76 135 array(
Chris@76 136 )
Chris@76 137 );
Chris@76 138
Chris@76 139 // Try to load it from the cache first; it'll never get cached if the setting is off.
Chris@76 140 if (($modSettings = cache_get_data('modSettings', 90)) == null)
Chris@76 141 {
Chris@76 142 $request = $smcFunc['db_query']('', '
Chris@76 143 SELECT variable, value
Chris@76 144 FROM {db_prefix}settings',
Chris@76 145 array(
Chris@76 146 )
Chris@76 147 );
Chris@76 148 $modSettings = array();
Chris@76 149 if (!$request)
Chris@76 150 db_fatal_error();
Chris@76 151 while ($row = $smcFunc['db_fetch_row']($request))
Chris@76 152 $modSettings[$row[0]] = $row[1];
Chris@76 153 $smcFunc['db_free_result']($request);
Chris@76 154
Chris@76 155 // Do a few things to protect against missing settings or settings with invalid values...
Chris@76 156 if (empty($modSettings['defaultMaxTopics']) || $modSettings['defaultMaxTopics'] <= 0 || $modSettings['defaultMaxTopics'] > 999)
Chris@76 157 $modSettings['defaultMaxTopics'] = 20;
Chris@76 158 if (empty($modSettings['defaultMaxMessages']) || $modSettings['defaultMaxMessages'] <= 0 || $modSettings['defaultMaxMessages'] > 999)
Chris@76 159 $modSettings['defaultMaxMessages'] = 15;
Chris@76 160 if (empty($modSettings['defaultMaxMembers']) || $modSettings['defaultMaxMembers'] <= 0 || $modSettings['defaultMaxMembers'] > 999)
Chris@76 161 $modSettings['defaultMaxMembers'] = 30;
Chris@76 162
Chris@76 163 if (!empty($modSettings['cache_enable']))
Chris@76 164 cache_put_data('modSettings', $modSettings, 90);
Chris@76 165 }
Chris@76 166
Chris@76 167 // UTF-8 in regular expressions is unsupported on PHP(win) versions < 4.2.3.
Chris@76 168 $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);
Chris@76 169
Chris@76 170 // Set a list of common functions.
Chris@76 171 $ent_list = empty($modSettings['disableEntityCheck']) ? '&(#\d{1,7}|quot|amp|lt|gt|nbsp);' : '&(#021|quot|amp|lt|gt|nbsp);';
Chris@76 172 $ent_check = empty($modSettings['disableEntityCheck']) ? array('preg_replace(\'~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~e\', \'$smcFunc[\\\'entity_fix\\\'](\\\'\\2\\\')\', ', ')') : array('', '');
Chris@76 173
Chris@76 174 // Preg_replace can handle complex characters only for higher PHP versions.
Chris@76 175 $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';
Chris@76 176
Chris@76 177 $smcFunc += array(
Chris@76 178 'entity_fix' => create_function('$string', '
Chris@76 179 $num = substr($string, 0, 1) === \'x\' ? hexdec(substr($string, 1)) : (int) $string;
Chris@76 180 return $num < 0x20 || $num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) || $num === 0x202E || $num === 0x202D ? \'\' : \'&#\' . $num . \';\';'),
Chris@76 181 'htmlspecialchars' => create_function('$string, $quote_style = ENT_COMPAT, $charset = \'ISO-8859-1\'', '
Chris@76 182 global $smcFunc;
Chris@76 183 return ' . strtr($ent_check[0], array('&' => '&amp;')) . 'htmlspecialchars($string, $quote_style, ' . ($utf8 ? '\'UTF-8\'' : '$charset') . ')' . $ent_check[1] . ';'),
Chris@76 184 'htmltrim' => create_function('$string', '
Chris@76 185 global $smcFunc;
Chris@76 186 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) . ');'),
Chris@76 187 'strlen' => create_function('$string', '
Chris@76 188 global $smcFunc;
Chris@76 189 return strlen(preg_replace(\'~' . $ent_list . ($utf8 ? '|.~u' : '~') . '\', \'_\', ' . implode('$string', $ent_check) . '));'),
Chris@76 190 'strpos' => create_function('$haystack, $needle, $offset = 0', '
Chris@76 191 global $smcFunc;
Chris@76 192 $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);
Chris@76 193 $haystack_size = count($haystack_arr);
Chris@76 194 if (strlen($needle) === 1)
Chris@76 195 {
Chris@76 196 $result = array_search($needle, array_slice($haystack_arr, $offset));
Chris@76 197 return is_int($result) ? $result + $offset : false;
Chris@76 198 }
Chris@76 199 else
Chris@76 200 {
Chris@76 201 $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);
Chris@76 202 $needle_size = count($needle_arr);
Chris@76 203
Chris@76 204 $result = array_search($needle_arr[0], array_slice($haystack_arr, $offset));
Chris@76 205 while (is_int($result))
Chris@76 206 {
Chris@76 207 $offset += $result;
Chris@76 208 if (array_slice($haystack_arr, $offset, $needle_size) === $needle_arr)
Chris@76 209 return $offset;
Chris@76 210 $result = array_search($needle_arr[0], array_slice($haystack_arr, ++$offset));
Chris@76 211 }
Chris@76 212 return false;
Chris@76 213 }'),
Chris@76 214 'substr' => create_function('$string, $start, $length = null', '
Chris@76 215 global $smcFunc;
Chris@76 216 $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);
Chris@76 217 return $length === null ? implode(\'\', array_slice($ent_arr, $start)) : implode(\'\', array_slice($ent_arr, $start, $length));'),
Chris@76 218 'strtolower' => $utf8 ? (function_exists('mb_strtolower') ? create_function('$string', '
Chris@76 219 return mb_strtolower($string, \'UTF-8\');') : create_function('$string', '
Chris@76 220 global $sourcedir;
Chris@76 221 require_once($sourcedir . \'/Subs-Charset.php\');
Chris@76 222 return utf8_strtolower($string);')) : 'strtolower',
Chris@76 223 'strtoupper' => $utf8 ? (function_exists('mb_strtoupper') ? create_function('$string', '
Chris@76 224 return mb_strtoupper($string, \'UTF-8\');') : create_function('$string', '
Chris@76 225 global $sourcedir;
Chris@76 226 require_once($sourcedir . \'/Subs-Charset.php\');
Chris@76 227 return utf8_strtoupper($string);')) : 'strtoupper',
Chris@76 228 'truncate' => create_function('$string, $length', (empty($modSettings['disableEntityCheck']) ? '
Chris@76 229 global $smcFunc;
Chris@76 230 $string = ' . implode('$string', $ent_check) . ';' : '') . '
Chris@76 231 preg_match(\'~^(' . $ent_list . '|.){\' . $smcFunc[\'strlen\'](substr($string, 0, $length)) . \'}~'. ($utf8 ? 'u' : '') . '\', $string, $matches);
Chris@76 232 $string = $matches[0];
Chris@76 233 while (strlen($string) > $length)
Chris@76 234 $string = preg_replace(\'~(?:' . $ent_list . '|.)$~'. ($utf8 ? 'u' : '') . '\', \'\', $string);
Chris@76 235 return $string;'),
Chris@76 236 'ucfirst' => $utf8 ? create_function('$string', '
Chris@76 237 global $smcFunc;
Chris@76 238 return $smcFunc[\'strtoupper\']($smcFunc[\'substr\']($string, 0, 1)) . $smcFunc[\'substr\']($string, 1);') : 'ucfirst',
Chris@76 239 'ucwords' => $utf8 ? create_function('$string', '
Chris@76 240 global $smcFunc;
Chris@76 241 $words = preg_split(\'~([\s\r\n\t]+)~\', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
Chris@76 242 for ($i = 0, $n = count($words); $i < $n; $i += 2)
Chris@76 243 $words[$i] = $smcFunc[\'ucfirst\']($words[$i]);
Chris@76 244 return implode(\'\', $words);') : 'ucwords',
Chris@76 245 );
Chris@76 246
Chris@76 247 // Setting the timezone is a requirement for some functions in PHP >= 5.1.
Chris@76 248 if (isset($modSettings['default_timezone']) && function_exists('date_default_timezone_set'))
Chris@76 249 date_default_timezone_set($modSettings['default_timezone']);
Chris@76 250
Chris@76 251 // Check the load averages?
Chris@76 252 if (!empty($modSettings['loadavg_enable']))
Chris@76 253 {
Chris@76 254 if (($modSettings['load_average'] = cache_get_data('loadavg', 90)) == null)
Chris@76 255 {
Chris@76 256 $modSettings['load_average'] = @file_get_contents('/proc/loadavg');
Chris@76 257 if (!empty($modSettings['load_average']) && preg_match('~^([^ ]+?) ([^ ]+?) ([^ ]+)~', $modSettings['load_average'], $matches) != 0)
Chris@76 258 $modSettings['load_average'] = (float) $matches[1];
Chris@76 259 elseif (($modSettings['load_average'] = @`uptime`) != null && preg_match('~load average[s]?: (\d+\.\d+), (\d+\.\d+), (\d+\.\d+)~i', $modSettings['load_average'], $matches) != 0)
Chris@76 260 $modSettings['load_average'] = (float) $matches[1];
Chris@76 261 else
Chris@76 262 unset($modSettings['load_average']);
Chris@76 263
Chris@76 264 if (!empty($modSettings['load_average']))
Chris@76 265 cache_put_data('loadavg', $modSettings['load_average'], 90);
Chris@76 266 }
Chris@76 267
Chris@76 268 if (!empty($modSettings['loadavg_forum']) && !empty($modSettings['load_average']) && $modSettings['load_average'] >= $modSettings['loadavg_forum'])
Chris@76 269 db_fatal_error(true);
Chris@76 270 }
Chris@76 271
Chris@76 272 // Is post moderation alive and well?
Chris@76 273 $modSettings['postmod_active'] = isset($modSettings['admin_features']) ? in_array('pm', explode(',', $modSettings['admin_features'])) : true;
Chris@76 274
Chris@76 275 // Integration is cool.
Chris@76 276 if (defined('SMF_INTEGRATION_SETTINGS'))
Chris@76 277 {
Chris@76 278 $integration_settings = unserialize(SMF_INTEGRATION_SETTINGS);
Chris@76 279 foreach ($integration_settings as $hook => $function)
Chris@76 280 add_integration_function($hook, $function, false);
Chris@76 281 }
Chris@76 282
Chris@76 283 // Any files to pre include?
Chris@76 284 if (!empty($modSettings['integrate_pre_include']))
Chris@76 285 {
Chris@76 286 $pre_includes = explode(',', $modSettings['integrate_pre_include']);
Chris@76 287 foreach ($pre_includes as $include)
Chris@76 288 {
Chris@76 289 $include = strtr(trim($include), array('$boarddir' => $boarddir, '$sourcedir' => $sourcedir));
Chris@76 290 if (file_exists($include))
Chris@76 291 require_once($include);
Chris@76 292 }
Chris@76 293 }
Chris@76 294
Chris@76 295 // Call pre load integration functions.
Chris@76 296 call_integration_hook('integrate_pre_load');
Chris@76 297 }
Chris@76 298
Chris@76 299 // Load all the important user information...
Chris@76 300 function loadUserSettings()
Chris@76 301 {
Chris@76 302 global $modSettings, $user_settings, $sourcedir, $smcFunc;
Chris@76 303 global $cookiename, $user_info, $language;
Chris@76 304
Chris@76 305 // Check first the integration, then the cookie, and last the session.
Chris@76 306 if (count($integration_ids = call_integration_hook('integrate_verify_user')) > 0)
Chris@76 307 {
Chris@76 308 $id_member = 0;
Chris@76 309 foreach ($integration_ids as $integration_id)
Chris@76 310 {
Chris@76 311 $integration_id = (int) $integration_id;
Chris@76 312 if ($integration_id > 0)
Chris@76 313 {
Chris@76 314 $id_member = $integration_id;
Chris@76 315 $already_verified = true;
Chris@76 316 break;
Chris@76 317 }
Chris@76 318 }
Chris@76 319 }
Chris@76 320 else
Chris@76 321 $id_member = 0;
Chris@76 322
Chris@76 323 if (empty($id_member) && isset($_COOKIE[$cookiename]))
Chris@76 324 {
Chris@76 325 // Fix a security hole in PHP 4.3.9 and below...
Chris@76 326 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)
Chris@76 327 {
Chris@76 328 list ($id_member, $password) = @unserialize($_COOKIE[$cookiename]);
Chris@76 329 $id_member = !empty($id_member) && strlen($password) > 0 ? (int) $id_member : 0;
Chris@76 330 }
Chris@76 331 else
Chris@76 332 $id_member = 0;
Chris@76 333 }
Chris@76 334 elseif (empty($id_member) && isset($_SESSION['login_' . $cookiename]) && ($_SESSION['USER_AGENT'] == $_SERVER['HTTP_USER_AGENT'] || !empty($modSettings['disableCheckUA'])))
Chris@76 335 {
Chris@76 336 // !!! Perhaps we can do some more checking on this, such as on the first octet of the IP?
Chris@76 337 list ($id_member, $password, $login_span) = @unserialize($_SESSION['login_' . $cookiename]);
Chris@76 338 $id_member = !empty($id_member) && strlen($password) == 40 && $login_span > time() ? (int) $id_member : 0;
Chris@76 339 }
Chris@76 340
Chris@76 341 // Only load this stuff if the user isn't a guest.
Chris@76 342 if ($id_member != 0)
Chris@76 343 {
Chris@76 344 // Is the member data cached?
Chris@76 345 if (empty($modSettings['cache_enable']) || $modSettings['cache_enable'] < 2 || ($user_settings = cache_get_data('user_settings-' . $id_member, 60)) == null)
Chris@76 346 {
Chris@76 347 $request = $smcFunc['db_query']('', '
Chris@76 348 SELECT mem.*, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type
Chris@76 349 FROM {db_prefix}members AS mem
Chris@76 350 LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = {int:id_member})
Chris@76 351 WHERE mem.id_member = {int:id_member}
Chris@76 352 LIMIT 1',
Chris@76 353 array(
Chris@76 354 'id_member' => $id_member,
Chris@76 355 )
Chris@76 356 );
Chris@76 357 $user_settings = $smcFunc['db_fetch_assoc']($request);
Chris@76 358 $smcFunc['db_free_result']($request);
Chris@76 359
Chris@76 360 if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
Chris@76 361 cache_put_data('user_settings-' . $id_member, $user_settings, 60);
Chris@76 362 }
Chris@76 363
Chris@76 364 // Did we find 'im? If not, junk it.
Chris@76 365 if (!empty($user_settings))
Chris@76 366 {
Chris@76 367 // As much as the password should be right, we can assume the integration set things up.
Chris@76 368 if (!empty($already_verified) && $already_verified === true)
Chris@76 369 $check = true;
Chris@76 370 // SHA-1 passwords should be 40 characters long.
Chris@76 371 elseif (strlen($password) == 40)
Chris@76 372 $check = sha1($user_settings['passwd'] . $user_settings['password_salt']) == $password;
Chris@76 373 else
Chris@76 374 $check = false;
Chris@76 375
Chris@76 376 // Wrong password or not activated - either way, you're going nowhere.
Chris@76 377 $id_member = $check && ($user_settings['is_activated'] == 1 || $user_settings['is_activated'] == 11) ? $user_settings['id_member'] : 0;
Chris@76 378 }
Chris@76 379 else
Chris@76 380 $id_member = 0;
Chris@76 381
Chris@76 382 // If we no longer have the member maybe they're being all hackey, stop brute force!
Chris@76 383 if (!$id_member)
Chris@76 384 {
Chris@76 385 require_once($sourcedir . '/LogInOut.php');
Chris@76 386 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);
Chris@76 387 }
Chris@76 388 }
Chris@76 389
Chris@76 390 // Found 'im, let's set up the variables.
Chris@76 391 if ($id_member != 0)
Chris@76 392 {
Chris@76 393 // Let's not update the last visit time in these cases...
Chris@76 394 // 1. SSI doesn't count as visiting the forum.
Chris@76 395 // 2. RSS feeds and XMLHTTP requests don't count either.
Chris@76 396 // 3. If it was set within this session, no need to set it again.
Chris@76 397 // 4. New session, yet updated < five hours ago? Maybe cache can help.
Chris@76 398 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))
Chris@76 399 {
Chris@76 400 // Do a quick query to make sure this isn't a mistake.
Chris@76 401 $result = $smcFunc['db_query']('', '
Chris@76 402 SELECT poster_time
Chris@76 403 FROM {db_prefix}messages
Chris@76 404 WHERE id_msg = {int:id_msg}
Chris@76 405 LIMIT 1',
Chris@76 406 array(
Chris@76 407 'id_msg' => $user_settings['id_msg_last_visit'],
Chris@76 408 )
Chris@76 409 );
Chris@76 410 list ($visitTime) = $smcFunc['db_fetch_row']($result);
Chris@76 411 $smcFunc['db_free_result']($result);
Chris@76 412
Chris@76 413 $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
Chris@76 414
Chris@76 415 // If it was *at least* five hours ago...
Chris@76 416 if ($visitTime < time() - 5 * 3600)
Chris@76 417 {
Chris@76 418 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']));
Chris@76 419 $user_settings['last_login'] = time();
Chris@76 420
Chris@76 421 if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
Chris@76 422 cache_put_data('user_settings-' . $id_member, $user_settings, 60);
Chris@76 423
Chris@76 424 if (!empty($modSettings['cache_enable']))
Chris@76 425 cache_put_data('user_last_visit-' . $id_member, $_SESSION['id_msg_last_visit'], 5 * 3600);
Chris@76 426 }
Chris@76 427 }
Chris@76 428 elseif (empty($_SESSION['id_msg_last_visit']))
Chris@76 429 $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
Chris@76 430
Chris@76 431 $username = $user_settings['member_name'];
Chris@76 432
Chris@76 433 if (empty($user_settings['additional_groups']))
Chris@76 434 $user_info = array(
Chris@76 435 'groups' => array($user_settings['id_group'], $user_settings['id_post_group'])
Chris@76 436 );
Chris@76 437 else
Chris@76 438 $user_info = array(
Chris@76 439 'groups' => array_merge(
Chris@76 440 array($user_settings['id_group'], $user_settings['id_post_group']),
Chris@76 441 explode(',', $user_settings['additional_groups'])
Chris@76 442 )
Chris@76 443 );
Chris@76 444
Chris@76 445 // Because history has proven that it is possible for groups to go bad - clean up in case.
Chris@76 446 foreach ($user_info['groups'] as $k => $v)
Chris@76 447 $user_info['groups'][$k] = (int) $v;
Chris@76 448
Chris@76 449 // This is a logged in user, so definitely not a spider.
Chris@76 450 $user_info['possibly_robot'] = false;
Chris@76 451 }
Chris@76 452 // If the user is a guest, initialize all the critical user settings.
Chris@76 453 else
Chris@76 454 {
Chris@76 455 // This is what a guest's variables should be.
Chris@76 456 $username = '';
Chris@76 457 $user_info = array('groups' => array(-1));
Chris@76 458 $user_settings = array();
Chris@76 459
Chris@76 460 if (isset($_COOKIE[$cookiename]))
Chris@76 461 $_COOKIE[$cookiename] = '';
Chris@76 462
Chris@76 463 // Do we perhaps think this is a search robot? Check every five minutes just in case...
Chris@76 464 if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300))
Chris@76 465 {
Chris@76 466 require_once($sourcedir . '/ManageSearchEngines.php');
Chris@76 467 $user_info['possibly_robot'] = SpiderCheck();
Chris@76 468 }
Chris@76 469 elseif (!empty($modSettings['spider_mode']))
Chris@76 470 $user_info['possibly_robot'] = isset($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0;
Chris@76 471 // If we haven't turned on proper spider hunts then have a guess!
Chris@76 472 else
Chris@76 473 {
Chris@76 474 $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
Chris@76 475 $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;
Chris@76 476 }
Chris@76 477 }
Chris@76 478
Chris@76 479 // Set up the $user_info array.
Chris@76 480 $user_info += array(
Chris@76 481 'id' => $id_member,
Chris@76 482 'username' => $username,
Chris@76 483 'name' => isset($user_settings['real_name']) ? $user_settings['real_name'] : '',
Chris@76 484 'email' => isset($user_settings['email_address']) ? $user_settings['email_address'] : '',
Chris@76 485 'passwd' => isset($user_settings['passwd']) ? $user_settings['passwd'] : '',
Chris@76 486 'language' => empty($user_settings['lngfile']) || empty($modSettings['userLanguage']) ? $language : $user_settings['lngfile'],
Chris@76 487 'is_guest' => $id_member == 0,
Chris@76 488 'is_admin' => in_array(1, $user_info['groups']),
Chris@76 489 'theme' => empty($user_settings['id_theme']) ? 0 : $user_settings['id_theme'],
Chris@76 490 'last_login' => empty($user_settings['last_login']) ? 0 : $user_settings['last_login'],
Chris@76 491 'ip' => $_SERVER['REMOTE_ADDR'],
Chris@76 492 'ip2' => $_SERVER['BAN_CHECK_IP'],
Chris@76 493 'posts' => empty($user_settings['posts']) ? 0 : $user_settings['posts'],
Chris@76 494 'time_format' => empty($user_settings['time_format']) ? $modSettings['time_format'] : $user_settings['time_format'],
Chris@76 495 'time_offset' => empty($user_settings['time_offset']) ? 0 : $user_settings['time_offset'],
Chris@76 496 'avatar' => array(
Chris@76 497 'url' => isset($user_settings['avatar']) ? $user_settings['avatar'] : '',
Chris@76 498 'filename' => empty($user_settings['filename']) ? '' : $user_settings['filename'],
Chris@76 499 'custom_dir' => !empty($user_settings['attachment_type']) && $user_settings['attachment_type'] == 1,
Chris@76 500 'id_attach' => isset($user_settings['id_attach']) ? $user_settings['id_attach'] : 0
Chris@76 501 ),
Chris@76 502 'smiley_set' => isset($user_settings['smiley_set']) ? $user_settings['smiley_set'] : '',
Chris@76 503 'messages' => empty($user_settings['instant_messages']) ? 0 : $user_settings['instant_messages'],
Chris@76 504 'unread_messages' => empty($user_settings['unread_messages']) ? 0 : $user_settings['unread_messages'],
Chris@76 505 'total_time_logged_in' => empty($user_settings['total_time_logged_in']) ? 0 : $user_settings['total_time_logged_in'],
Chris@76 506 'buddies' => !empty($modSettings['enable_buddylist']) && !empty($user_settings['buddy_list']) ? explode(',', $user_settings['buddy_list']) : array(),
Chris@76 507 'ignoreboards' => !empty($user_settings['ignore_boards']) && !empty($modSettings['allow_ignore_boards']) ? explode(',', $user_settings['ignore_boards']) : array(),
Chris@76 508 'ignoreusers' => !empty($user_settings['pm_ignore_list']) ? explode(',', $user_settings['pm_ignore_list']) : array(),
Chris@76 509 'warning' => isset($user_settings['warning']) ? $user_settings['warning'] : 0,
Chris@76 510 'permissions' => array(),
Chris@76 511 );
Chris@76 512 $user_info['groups'] = array_unique($user_info['groups']);
Chris@76 513 // 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.
Chris@76 514 if (!empty($user_info['ignoreboards']) && empty($user_info['ignoreboards'][$tmp = count($user_info['ignoreboards']) - 1]))
Chris@76 515 unset($user_info['ignoreboards'][$tmp]);
Chris@76 516
Chris@76 517 // Do we have any languages to validate this?
Chris@76 518 if (!empty($modSettings['userLanguage']) && (!empty($_GET['language']) || !empty($_SESSION['language'])))
Chris@76 519 $languages = getLanguages();
Chris@76 520
Chris@76 521 // Allow the user to change their language if its valid.
Chris@76 522 if (!empty($modSettings['userLanguage']) && !empty($_GET['language']) && isset($languages[strtr($_GET['language'], './\\:', '____')]))
Chris@76 523 {
Chris@76 524 $user_info['language'] = strtr($_GET['language'], './\\:', '____');
Chris@76 525 $_SESSION['language'] = $user_info['language'];
Chris@76 526 }
Chris@76 527 elseif (!empty($modSettings['userLanguage']) && !empty($_SESSION['language']) && isset($languages[strtr($_SESSION['language'], './\\:', '____')]))
Chris@76 528 $user_info['language'] = strtr($_SESSION['language'], './\\:', '____');
Chris@76 529
Chris@76 530 // Just build this here, it makes it easier to change/use - administrators can see all boards.
Chris@76 531 if ($user_info['is_admin'])
Chris@76 532 $user_info['query_see_board'] = '1=1';
Chris@76 533 // Otherwise just the groups in $user_info['groups'].
Chris@76 534 else
Chris@76 535 $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'] : '') . ')';
Chris@76 536
Chris@76 537 // Build the list of boards they WANT to see.
Chris@76 538 // This will take the place of query_see_boards in certain spots, so it better include the boards they can see also
Chris@76 539
Chris@76 540 // If they aren't ignoring any boards then they want to see all the boards they can see
Chris@76 541 if (empty($user_info['ignoreboards']))
Chris@76 542 $user_info['query_wanna_see_board'] = $user_info['query_see_board'];
Chris@76 543 // Ok I guess they don't want to see all the boards
Chris@76 544 else
Chris@76 545 $user_info['query_wanna_see_board'] = '(' . $user_info['query_see_board'] . ' AND b.id_board NOT IN (' . implode(',', $user_info['ignoreboards']) . '))';
Chris@76 546 }
Chris@76 547
Chris@76 548 // Check for moderators and see if they have access to the board.
Chris@76 549 function loadBoard()
Chris@76 550 {
Chris@76 551 global $txt, $scripturl, $context, $modSettings;
Chris@76 552 global $board_info, $board, $topic, $user_info, $smcFunc;
Chris@76 553
Chris@76 554 // Assume they are not a moderator.
Chris@76 555 $user_info['is_mod'] = false;
Chris@76 556 $context['user']['is_mod'] = &$user_info['is_mod'];
Chris@76 557
Chris@76 558 // Start the linktree off empty..
Chris@76 559 $context['linktree'] = array();
Chris@76 560
Chris@76 561 // Have they by chance specified a message id but nothing else?
Chris@76 562 if (empty($_REQUEST['action']) && empty($topic) && empty($board) && !empty($_REQUEST['msg']))
Chris@76 563 {
Chris@76 564 // Make sure the message id is really an int.
Chris@76 565 $_REQUEST['msg'] = (int) $_REQUEST['msg'];
Chris@76 566
Chris@76 567 // Looking through the message table can be slow, so try using the cache first.
Chris@76 568 if (($topic = cache_get_data('msg_topic-' . $_REQUEST['msg'], 120)) === NULL)
Chris@76 569 {
Chris@76 570 $request = $smcFunc['db_query']('', '
Chris@76 571 SELECT id_topic
Chris@76 572 FROM {db_prefix}messages
Chris@76 573 WHERE id_msg = {int:id_msg}
Chris@76 574 LIMIT 1',
Chris@76 575 array(
Chris@76 576 'id_msg' => $_REQUEST['msg'],
Chris@76 577 )
Chris@76 578 );
Chris@76 579
Chris@76 580 // So did it find anything?
Chris@76 581 if ($smcFunc['db_num_rows']($request))
Chris@76 582 {
Chris@76 583 list ($topic) = $smcFunc['db_fetch_row']($request);
Chris@76 584 $smcFunc['db_free_result']($request);
Chris@76 585 // Save save save.
Chris@76 586 cache_put_data('msg_topic-' . $_REQUEST['msg'], $topic, 120);
Chris@76 587 }
Chris@76 588 }
Chris@76 589
Chris@76 590 // Remember redirection is the key to avoiding fallout from your bosses.
Chris@76 591 if (!empty($topic))
Chris@76 592 redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg']);
Chris@76 593 else
Chris@76 594 {
Chris@76 595 loadPermissions();
Chris@76 596 loadTheme();
Chris@76 597 fatal_lang_error('topic_gone', false);
Chris@76 598 }
Chris@76 599 }
Chris@76 600
Chris@76 601 // Load this board only if it is specified.
Chris@76 602 if (empty($board) && empty($topic))
Chris@76 603 {
Chris@76 604 $board_info = array('moderators' => array());
Chris@76 605 return;
Chris@76 606 }
Chris@76 607
Chris@76 608 if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
Chris@76 609 {
Chris@76 610 // !!! SLOW?
Chris@76 611 if (!empty($topic))
Chris@76 612 $temp = cache_get_data('topic_board-' . $topic, 120);
Chris@76 613 else
Chris@76 614 $temp = cache_get_data('board-' . $board, 120);
Chris@76 615
Chris@76 616 if (!empty($temp))
Chris@76 617 {
Chris@76 618 $board_info = $temp;
Chris@76 619 $board = $board_info['id'];
Chris@76 620 }
Chris@76 621 }
Chris@76 622
Chris@76 623 if (empty($temp))
Chris@76 624 {
Chris@76 625 $request = $smcFunc['db_query']('', '
Chris@76 626 SELECT
Chris@76 627 c.id_cat, b.name AS bname, b.description, b.num_topics, b.member_groups,
Chris@76 628 b.id_parent, c.name AS cname, IFNULL(mem.id_member, 0) AS id_moderator,
Chris@76 629 mem.real_name' . (!empty($topic) ? ', b.id_board' : '') . ', b.child_level,
Chris@76 630 b.id_theme, b.override_theme, b.count_posts, b.id_profile, b.redirect,
Chris@76 631 b.unapproved_topics, b.unapproved_posts' . (!empty($topic) ? ', t.approved, t.id_member_started' : '') . '
Chris@76 632 FROM {db_prefix}boards AS b' . (!empty($topic) ? '
Chris@76 633 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})' : '') . '
Chris@76 634 LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
Chris@76 635 LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = {raw:board_link})
Chris@76 636 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
Chris@76 637 WHERE b.id_board = {raw:board_link}',
Chris@76 638 array(
Chris@76 639 'current_topic' => $topic,
Chris@76 640 'board_link' => empty($topic) ? $smcFunc['db_quote']('{int:current_board}', array('current_board' => $board)) : 't.id_board',
Chris@76 641 )
Chris@76 642 );
Chris@76 643 // If there aren't any, skip.
Chris@76 644 if ($smcFunc['db_num_rows']($request) > 0)
Chris@76 645 {
Chris@76 646 $row = $smcFunc['db_fetch_assoc']($request);
Chris@76 647
Chris@76 648 // Set the current board.
Chris@76 649 if (!empty($row['id_board']))
Chris@76 650 $board = $row['id_board'];
Chris@76 651
Chris@76 652 // Basic operating information. (globals... :/)
Chris@76 653 $board_info = array(
Chris@76 654 'id' => $board,
Chris@76 655 'moderators' => array(),
Chris@76 656 'cat' => array(
Chris@76 657 'id' => $row['id_cat'],
Chris@76 658 'name' => $row['cname']
Chris@76 659 ),
Chris@76 660 'name' => $row['bname'],
Chris@76 661 'description' => $row['description'],
Chris@76 662 'num_topics' => $row['num_topics'],
Chris@76 663 'unapproved_topics' => $row['unapproved_topics'],
Chris@76 664 'unapproved_posts' => $row['unapproved_posts'],
Chris@76 665 'unapproved_user_topics' => 0,
Chris@76 666 'parent_boards' => getBoardParents($row['id_parent']),
Chris@76 667 'parent' => $row['id_parent'],
Chris@76 668 'child_level' => $row['child_level'],
Chris@76 669 'theme' => $row['id_theme'],
Chris@76 670 'override_theme' => !empty($row['override_theme']),
Chris@76 671 'profile' => $row['id_profile'],
Chris@76 672 'redirect' => $row['redirect'],
Chris@76 673 'posts_count' => empty($row['count_posts']),
Chris@76 674 'cur_topic_approved' => empty($topic) || $row['approved'],
Chris@76 675 'cur_topic_starter' => empty($topic) ? 0 : $row['id_member_started'],
Chris@76 676 );
Chris@76 677
Chris@76 678 // Load the membergroups allowed, and check permissions.
Chris@76 679 $board_info['groups'] = $row['member_groups'] == '' ? array() : explode(',', $row['member_groups']);
Chris@76 680
Chris@76 681 do
Chris@76 682 {
Chris@76 683 if (!empty($row['id_moderator']))
Chris@76 684 $board_info['moderators'][$row['id_moderator']] = array(
Chris@76 685 'id' => $row['id_moderator'],
Chris@76 686 'name' => $row['real_name'],
Chris@76 687 'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'],
Chris@76 688 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>'
Chris@76 689 );
Chris@76 690 }
Chris@76 691 while ($row = $smcFunc['db_fetch_assoc']($request));
Chris@76 692
Chris@76 693 // If the board only contains unapproved posts and the user isn't an approver then they can't see any topics.
Chris@76 694 // If that is the case do an additional check to see if they have any topics waiting to be approved.
Chris@76 695 if ($board_info['num_topics'] == 0 && $modSettings['postmod_active'] && !allowedTo('approve_posts'))
Chris@76 696 {
Chris@76 697 $smcFunc['db_free_result']($request); // Free the previous result
Chris@76 698
Chris@76 699 $request = $smcFunc['db_query']('', '
Chris@76 700 SELECT COUNT(id_topic)
Chris@76 701 FROM {db_prefix}topics
Chris@76 702 WHERE id_member_started={int:id_member}
Chris@76 703 AND approved = {int:unapproved}
Chris@76 704 AND id_board = {int:board}',
Chris@76 705 array(
Chris@76 706 'id_member' => $user_info['id'],
Chris@76 707 'unapproved' => 0,
Chris@76 708 'board' => $board,
Chris@76 709 )
Chris@76 710 );
Chris@76 711
Chris@76 712 list ($board_info['unapproved_user_topics']) = $smcFunc['db_fetch_row']($request);
Chris@76 713 }
Chris@76 714
Chris@76 715 if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
Chris@76 716 {
Chris@76 717 // !!! SLOW?
Chris@76 718 if (!empty($topic))
Chris@76 719 cache_put_data('topic_board-' . $topic, $board_info, 120);
Chris@76 720 cache_put_data('board-' . $board, $board_info, 120);
Chris@76 721 }
Chris@76 722 }
Chris@76 723 else
Chris@76 724 {
Chris@76 725 // Otherwise the topic is invalid, there are no moderators, etc.
Chris@76 726 $board_info = array(
Chris@76 727 'moderators' => array(),
Chris@76 728 'error' => 'exist'
Chris@76 729 );
Chris@76 730 $topic = null;
Chris@76 731 $board = 0;
Chris@76 732 }
Chris@76 733 $smcFunc['db_free_result']($request);
Chris@76 734 }
Chris@76 735
Chris@76 736 if (!empty($topic))
Chris@76 737 $_GET['board'] = (int) $board;
Chris@76 738
Chris@76 739 if (!empty($board))
Chris@76 740 {
Chris@76 741 // Now check if the user is a moderator.
Chris@76 742 $user_info['is_mod'] = isset($board_info['moderators'][$user_info['id']]);
Chris@76 743
Chris@76 744 if (count(array_intersect($user_info['groups'], $board_info['groups'])) == 0 && !$user_info['is_admin'])
Chris@76 745 $board_info['error'] = 'access';
Chris@76 746
Chris@76 747 // Build up the linktree.
Chris@76 748 $context['linktree'] = array_merge(
Chris@76 749 $context['linktree'],
Chris@76 750 array(array(
Chris@76 751 'url' => $scripturl . '#c' . $board_info['cat']['id'],
Chris@76 752 'name' => $board_info['cat']['name']
Chris@76 753 )),
Chris@76 754 array_reverse($board_info['parent_boards']),
Chris@76 755 array(array(
Chris@76 756 'url' => $scripturl . '?board=' . $board . '.0',
Chris@76 757 'name' => $board_info['name']
Chris@76 758 ))
Chris@76 759 );
Chris@76 760 }
Chris@76 761
Chris@76 762 // Set the template contextual information.
Chris@76 763 $context['user']['is_mod'] = &$user_info['is_mod'];
Chris@76 764 $context['current_topic'] = $topic;
Chris@76 765 $context['current_board'] = $board;
Chris@76 766
Chris@76 767 // Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
Chris@76 768 if (!empty($board_info['error']) && ($board_info['error'] != 'access' || !$user_info['is_mod']))
Chris@76 769 {
Chris@76 770 // The permissions and theme need loading, just to make sure everything goes smoothly.
Chris@76 771 loadPermissions();
Chris@76 772 loadTheme();
Chris@76 773
Chris@76 774 $_GET['board'] = '';
Chris@76 775 $_GET['topic'] = '';
Chris@76 776
Chris@76 777 // The linktree should not give the game away mate!
Chris@76 778 $context['linktree'] = array(
Chris@76 779 array(
Chris@76 780 'url' => $scripturl,
Chris@76 781 'name' => $context['forum_name_html_safe']
Chris@76 782 )
Chris@76 783 );
Chris@76 784
Chris@76 785 // If it's a prefetching agent or we're requesting an attachment.
Chris@76 786 if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') || (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach'))
Chris@76 787 {
Chris@76 788 ob_end_clean();
Chris@76 789 header('HTTP/1.1 403 Forbidden');
Chris@76 790 die;
Chris@76 791 }
Chris@76 792 elseif ($user_info['is_guest'])
Chris@76 793 {
Chris@76 794 loadLanguage('Errors');
Chris@76 795 is_not_guest($txt['topic_gone']);
Chris@76 796 }
Chris@76 797 else
Chris@76 798 fatal_lang_error('topic_gone', false);
Chris@76 799 }
Chris@76 800
Chris@76 801 if ($user_info['is_mod'])
Chris@76 802 $user_info['groups'][] = 3;
Chris@76 803 }
Chris@76 804
Chris@76 805 // Load this user's permissions.
Chris@76 806 function loadPermissions()
Chris@76 807 {
Chris@76 808 global $user_info, $board, $board_info, $modSettings, $smcFunc, $sourcedir;
Chris@76 809
Chris@76 810 if ($user_info['is_admin'])
Chris@76 811 {
Chris@76 812 banPermissions();
Chris@76 813 return;
Chris@76 814 }
Chris@76 815
Chris@76 816 if (!empty($modSettings['cache_enable']))
Chris@76 817 {
Chris@76 818 $cache_groups = $user_info['groups'];
Chris@76 819 asort($cache_groups);
Chris@76 820 $cache_groups = implode(',', $cache_groups);
Chris@76 821 // If it's a spider then cache it different.
Chris@76 822 if ($user_info['possibly_robot'])
Chris@76 823 $cache_groups .= '-spider';
Chris@76 824
Chris@76 825 if ($modSettings['cache_enable'] >= 2 && !empty($board) && ($temp = cache_get_data('permissions:' . $cache_groups . ':' . $board, 240)) != null && time() - 240 > $modSettings['settings_updated'])
Chris@76 826 {
Chris@76 827 list ($user_info['permissions']) = $temp;
Chris@76 828 banPermissions();
Chris@76 829
Chris@76 830 return;
Chris@76 831 }
Chris@76 832 elseif (($temp = cache_get_data('permissions:' . $cache_groups, 240)) != null && time() - 240 > $modSettings['settings_updated'])
Chris@76 833 list ($user_info['permissions'], $removals) = $temp;
Chris@76 834 }
Chris@76 835
Chris@76 836 // If it is detected as a robot, and we are restricting permissions as a special group - then implement this.
Chris@76 837 $spider_restrict = $user_info['possibly_robot'] && !empty($modSettings['spider_group']) ? ' OR (id_group = {int:spider_group} AND add_deny = 0)' : '';
Chris@76 838
Chris@76 839 if (empty($user_info['permissions']))
Chris@76 840 {
Chris@76 841 // Get the general permissions.
Chris@76 842 $request = $smcFunc['db_query']('', '
Chris@76 843 SELECT permission, add_deny
Chris@76 844 FROM {db_prefix}permissions
Chris@76 845 WHERE id_group IN ({array_int:member_groups})
Chris@76 846 ' . $spider_restrict,
Chris@76 847 array(
Chris@76 848 'member_groups' => $user_info['groups'],
Chris@76 849 'spider_group' => !empty($modSettings['spider_group']) ? $modSettings['spider_group'] : 0,
Chris@76 850 )
Chris@76 851 );
Chris@76 852 $removals = array();
Chris@76 853 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 854 {
Chris@76 855 if (empty($row['add_deny']))
Chris@76 856 $removals[] = $row['permission'];
Chris@76 857 else
Chris@76 858 $user_info['permissions'][] = $row['permission'];
Chris@76 859 }
Chris@76 860 $smcFunc['db_free_result']($request);
Chris@76 861
Chris@76 862 if (isset($cache_groups))
Chris@76 863 cache_put_data('permissions:' . $cache_groups, array($user_info['permissions'], $removals), 240);
Chris@76 864 }
Chris@76 865
Chris@76 866 // Get the board permissions.
Chris@76 867 if (!empty($board))
Chris@76 868 {
Chris@76 869 // Make sure the board (if any) has been loaded by loadBoard().
Chris@76 870 if (!isset($board_info['profile']))
Chris@76 871 fatal_lang_error('no_board');
Chris@76 872
Chris@76 873 $request = $smcFunc['db_query']('', '
Chris@76 874 SELECT permission, add_deny
Chris@76 875 FROM {db_prefix}board_permissions
Chris@76 876 WHERE (id_group IN ({array_int:member_groups})
Chris@76 877 ' . $spider_restrict . ')
Chris@76 878 AND id_profile = {int:id_profile}',
Chris@76 879 array(
Chris@76 880 'member_groups' => $user_info['groups'],
Chris@76 881 'id_profile' => $board_info['profile'],
Chris@76 882 'spider_group' => !empty($modSettings['spider_group']) ? $modSettings['spider_group'] : 0,
Chris@76 883 )
Chris@76 884 );
Chris@76 885 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 886 {
Chris@76 887 if (empty($row['add_deny']))
Chris@76 888 $removals[] = $row['permission'];
Chris@76 889 else
Chris@76 890 $user_info['permissions'][] = $row['permission'];
Chris@76 891 }
Chris@76 892 $smcFunc['db_free_result']($request);
Chris@76 893 }
Chris@76 894
Chris@76 895 // Remove all the permissions they shouldn't have ;).
Chris@76 896 if (!empty($modSettings['permission_enable_deny']))
Chris@76 897 $user_info['permissions'] = array_diff($user_info['permissions'], $removals);
Chris@76 898
Chris@76 899 if (isset($cache_groups) && !empty($board) && $modSettings['cache_enable'] >= 2)
Chris@76 900 cache_put_data('permissions:' . $cache_groups . ':' . $board, array($user_info['permissions'], null), 240);
Chris@76 901
Chris@76 902 // Banned? Watch, don't touch..
Chris@76 903 banPermissions();
Chris@76 904
Chris@76 905 // Load the mod cache so we can know what additional boards they should see, but no sense in doing it for guests
Chris@76 906 if (!$user_info['is_guest'])
Chris@76 907 {
Chris@76 908 if (!isset($_SESSION['mc']) || $_SESSION['mc']['time'] <= $modSettings['settings_updated'])
Chris@76 909 {
Chris@76 910 require_once($sourcedir . '/Subs-Auth.php');
Chris@76 911 rebuildModCache();
Chris@76 912 }
Chris@76 913 else
Chris@76 914 $user_info['mod_cache'] = $_SESSION['mc'];
Chris@76 915 }
Chris@76 916 }
Chris@76 917
Chris@76 918 // Loads an array of users' data by ID or member_name.
Chris@76 919 function loadMemberData($users, $is_name = false, $set = 'normal')
Chris@76 920 {
Chris@76 921 global $user_profile, $modSettings, $board_info, $smcFunc;
Chris@76 922
Chris@76 923 // Can't just look for no users :P.
Chris@76 924 if (empty($users))
Chris@76 925 return false;
Chris@76 926
Chris@76 927 // Make sure it's an array.
Chris@76 928 $users = !is_array($users) ? array($users) : array_unique($users);
Chris@76 929 $loaded_ids = array();
Chris@76 930
Chris@76 931 if (!$is_name && !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 3)
Chris@76 932 {
Chris@76 933 $users = array_values($users);
Chris@76 934 for ($i = 0, $n = count($users); $i < $n; $i++)
Chris@76 935 {
Chris@76 936 $data = cache_get_data('member_data-' . $set . '-' . $users[$i], 240);
Chris@76 937 if ($data == null)
Chris@76 938 continue;
Chris@76 939
Chris@76 940 $loaded_ids[] = $data['id_member'];
Chris@76 941 $user_profile[$data['id_member']] = $data;
Chris@76 942 unset($users[$i]);
Chris@76 943 }
Chris@76 944 }
Chris@76 945
Chris@76 946 if ($set == 'normal')
Chris@76 947 {
Chris@76 948 $select_columns = '
Chris@76 949 IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type,
Chris@76 950 mem.signature, mem.personal_text, mem.location, mem.gender, mem.avatar, mem.id_member, mem.member_name,
Chris@76 951 mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url,
Chris@76 952 mem.birthdate, mem.member_ip, mem.member_ip2, mem.icq, mem.aim, mem.yim, mem.msn, mem.posts, mem.last_login,
Chris@76 953 mem.karma_good, mem.id_post_group, mem.karma_bad, mem.lngfile, mem.id_group, mem.time_offset, mem.show_online,
Chris@76 954 mem.buddy_list, mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group,
Chris@76 955 pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group, mem.is_activated, mem.warning,
Chris@76 956 CASE WHEN mem.id_group = 0 OR mg.stars = {string:blank_string} THEN pg.stars ELSE mg.stars END AS stars' . (!empty($modSettings['titlesEnable']) ? ',
Chris@76 957 mem.usertitle' : '');
Chris@76 958 $select_tables = '
Chris@76 959 LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)
Chris@76 960 LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member)
Chris@76 961 LEFT JOIN {db_prefix}membergroups AS pg ON (pg.id_group = mem.id_post_group)
Chris@76 962 LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)';
Chris@76 963 }
Chris@76 964 elseif ($set == 'profile')
Chris@76 965 {
Chris@76 966 $select_columns = '
Chris@76 967 IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type,
Chris@76 968 mem.signature, mem.personal_text, mem.location, mem.gender, mem.avatar, mem.id_member, mem.member_name,
Chris@76 969 mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url,
Chris@76 970 mem.openid_uri, mem.birthdate, mem.icq, mem.aim, mem.yim, mem.msn, mem.posts, mem.last_login, mem.karma_good,
Chris@76 971 mem.karma_bad, mem.member_ip, mem.member_ip2, mem.lngfile, mem.id_group, mem.id_theme, mem.buddy_list,
Chris@76 972 mem.pm_ignore_list, mem.pm_email_notify, mem.pm_receive_from, mem.time_offset' . (!empty($modSettings['titlesEnable']) ? ', mem.usertitle' : '') . ',
Chris@76 973 mem.time_format, mem.secret_question, mem.is_activated, mem.additional_groups, mem.smiley_set, mem.show_online,
Chris@76 974 mem.total_time_logged_in, mem.id_post_group, mem.notify_announcements, mem.notify_regularity, mem.notify_send_body,
Chris@76 975 mem.notify_types, lo.url, mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group,
Chris@76 976 pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group, mem.ignore_boards, mem.warning,
Chris@76 977 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';
Chris@76 978 $select_tables = '
Chris@76 979 LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member)
Chris@76 980 LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member)
Chris@76 981 LEFT JOIN {db_prefix}membergroups AS pg ON (pg.id_group = mem.id_post_group)
Chris@76 982 LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)';
Chris@76 983 }
Chris@76 984 elseif ($set == 'minimal')
Chris@76 985 {
Chris@76 986 $select_columns = '
Chris@76 987 mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.hide_email, mem.date_registered,
Chris@76 988 mem.posts, mem.last_login, mem.member_ip, mem.member_ip2, mem.lngfile, mem.id_group';
Chris@76 989 $select_tables = '';
Chris@76 990 }
Chris@76 991 else
Chris@76 992 trigger_error('loadMemberData(): Invalid member data set \'' . $set . '\'', E_USER_WARNING);
Chris@76 993
Chris@76 994 if (!empty($users))
Chris@76 995 {
Chris@76 996 // Load the member's data.
Chris@76 997 $request = $smcFunc['db_query']('', '
Chris@76 998 SELECT' . $select_columns . '
Chris@76 999 FROM {db_prefix}members AS mem' . $select_tables . '
Chris@76 1000 WHERE mem.' . ($is_name ? 'member_name' : 'id_member') . (count($users) == 1 ? ' = {' . ($is_name ? 'string' : 'int') . ':users}' : ' IN ({' . ($is_name ? 'array_string' : 'array_int') . ':users})'),
Chris@76 1001 array(
Chris@76 1002 'blank_string' => '',
Chris@76 1003 'users' => count($users) == 1 ? current($users) : $users,
Chris@76 1004 )
Chris@76 1005 );
Chris@76 1006 $new_loaded_ids = array();
Chris@76 1007 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1008 {
Chris@76 1009 $new_loaded_ids[] = $row['id_member'];
Chris@76 1010 $loaded_ids[] = $row['id_member'];
Chris@76 1011 $row['options'] = array();
Chris@76 1012 $user_profile[$row['id_member']] = $row;
Chris@76 1013 }
Chris@76 1014 $smcFunc['db_free_result']($request);
Chris@76 1015 }
Chris@76 1016
Chris@76 1017 if (!empty($new_loaded_ids) && $set !== 'minimal')
Chris@76 1018 {
Chris@76 1019 $request = $smcFunc['db_query']('', '
Chris@76 1020 SELECT *
Chris@76 1021 FROM {db_prefix}themes
Chris@76 1022 WHERE id_member' . (count($new_loaded_ids) == 1 ? ' = {int:loaded_ids}' : ' IN ({array_int:loaded_ids})'),
Chris@76 1023 array(
Chris@76 1024 'loaded_ids' => count($new_loaded_ids) == 1 ? $new_loaded_ids[0] : $new_loaded_ids,
Chris@76 1025 )
Chris@76 1026 );
Chris@76 1027 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1028 $user_profile[$row['id_member']]['options'][$row['variable']] = $row['value'];
Chris@76 1029 $smcFunc['db_free_result']($request);
Chris@76 1030 }
Chris@76 1031
Chris@76 1032 if (!empty($new_loaded_ids) && !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 3)
Chris@76 1033 {
Chris@76 1034 for ($i = 0, $n = count($new_loaded_ids); $i < $n; $i++)
Chris@76 1035 cache_put_data('member_data-' . $set . '-' . $new_loaded_ids[$i], $user_profile[$new_loaded_ids[$i]], 240);
Chris@76 1036 }
Chris@76 1037
Chris@76 1038 // Are we loading any moderators? If so, fix their group data...
Chris@76 1039 if (!empty($loaded_ids) && !empty($board_info['moderators']) && $set === 'normal' && count($temp_mods = array_intersect($loaded_ids, array_keys($board_info['moderators']))) !== 0)
Chris@76 1040 {
Chris@76 1041 if (($row = cache_get_data('moderator_group_info', 480)) == null)
Chris@76 1042 {
Chris@76 1043 $request = $smcFunc['db_query']('', '
Chris@76 1044 SELECT group_name AS member_group, online_color AS member_group_color, stars
Chris@76 1045 FROM {db_prefix}membergroups
Chris@76 1046 WHERE id_group = {int:moderator_group}
Chris@76 1047 LIMIT 1',
Chris@76 1048 array(
Chris@76 1049 'moderator_group' => 3,
Chris@76 1050 )
Chris@76 1051 );
Chris@76 1052 $row = $smcFunc['db_fetch_assoc']($request);
Chris@76 1053 $smcFunc['db_free_result']($request);
Chris@76 1054
Chris@76 1055 cache_put_data('moderator_group_info', $row, 480);
Chris@76 1056 }
Chris@76 1057
Chris@76 1058 foreach ($temp_mods as $id)
Chris@76 1059 {
Chris@76 1060 // By popular demand, don't show admins or global moderators as moderators.
Chris@76 1061 if ($user_profile[$id]['id_group'] != 1 && $user_profile[$id]['id_group'] != 2)
Chris@76 1062 $user_profile[$id]['member_group'] = $row['member_group'];
Chris@76 1063
Chris@76 1064 // If the Moderator group has no color or stars, but their group does... don't overwrite.
Chris@76 1065 if (!empty($row['stars']))
Chris@76 1066 $user_profile[$id]['stars'] = $row['stars'];
Chris@76 1067 if (!empty($row['member_group_color']))
Chris@76 1068 $user_profile[$id]['member_group_color'] = $row['member_group_color'];
Chris@76 1069 }
Chris@76 1070 }
Chris@76 1071
Chris@76 1072 return empty($loaded_ids) ? false : $loaded_ids;
Chris@76 1073 }
Chris@76 1074
Chris@76 1075 // Loads the user's basic values... meant for template/theme usage.
Chris@76 1076 function loadMemberContext($user, $display_custom_fields = false)
Chris@76 1077 {
Chris@76 1078 global $memberContext, $user_profile, $txt, $scripturl, $user_info;
Chris@76 1079 global $context, $modSettings, $board_info, $settings;
Chris@76 1080 global $smcFunc;
Chris@76 1081 static $dataLoaded = array();
Chris@76 1082
Chris@76 1083 // If this person's data is already loaded, skip it.
Chris@76 1084 if (isset($dataLoaded[$user]))
Chris@76 1085 return true;
Chris@76 1086
Chris@76 1087 // We can't load guests or members not loaded by loadMemberData()!
Chris@76 1088 if ($user == 0)
Chris@76 1089 return false;
Chris@76 1090 if (!isset($user_profile[$user]))
Chris@76 1091 {
Chris@76 1092 trigger_error('loadMemberContext(): member id ' . $user . ' not previously loaded by loadMemberData()', E_USER_WARNING);
Chris@76 1093 return false;
Chris@76 1094 }
Chris@76 1095
Chris@76 1096 // Well, it's loaded now anyhow.
Chris@76 1097 $dataLoaded[$user] = true;
Chris@76 1098 $profile = $user_profile[$user];
Chris@76 1099
Chris@76 1100 // Censor everything.
Chris@76 1101 censorText($profile['signature']);
Chris@76 1102 censorText($profile['personal_text']);
Chris@76 1103 censorText($profile['location']);
Chris@76 1104
Chris@76 1105 // Set things up to be used before hand.
Chris@76 1106 $gendertxt = $profile['gender'] == 2 ? $txt['female'] : ($profile['gender'] == 1 ? $txt['male'] : '');
Chris@76 1107 $profile['signature'] = str_replace(array("\n", "\r"), array('<br />', ''), $profile['signature']);
Chris@76 1108 $profile['signature'] = parse_bbc($profile['signature'], true, 'sig' . $profile['id_member']);
Chris@76 1109
Chris@76 1110 $profile['is_online'] = (!empty($profile['show_online']) || allowedTo('moderate_forum')) && $profile['is_online'] > 0;
Chris@76 1111 $profile['stars'] = empty($profile['stars']) ? array('', '') : explode('#', $profile['stars']);
Chris@76 1112 // Setup the buddy status here (One whole in_array call saved :P)
Chris@76 1113 $profile['buddy'] = in_array($profile['id_member'], $user_info['buddies']);
Chris@76 1114 $buddy_list = !empty($profile['buddy_list']) ? explode(',', $profile['buddy_list']) : array();
Chris@76 1115
Chris@76 1116 // If we're always html resizing, assume it's too large.
Chris@76 1117 if ($modSettings['avatar_action_too_large'] == 'option_html_resize' || $modSettings['avatar_action_too_large'] == 'option_js_resize')
Chris@76 1118 {
Chris@76 1119 $avatar_width = !empty($modSettings['avatar_max_width_external']) ? ' width="' . $modSettings['avatar_max_width_external'] . '"' : '';
Chris@76 1120 $avatar_height = !empty($modSettings['avatar_max_height_external']) ? ' height="' . $modSettings['avatar_max_height_external'] . '"' : '';
Chris@76 1121 }
Chris@76 1122 else
Chris@76 1123 {
Chris@76 1124 $avatar_width = '';
Chris@76 1125 $avatar_height = '';
Chris@76 1126 }
Chris@76 1127
Chris@76 1128 // What a monstrous array...
Chris@76 1129 $memberContext[$user] = array(
Chris@76 1130 'username' => $profile['member_name'],
Chris@76 1131 'name' => $profile['real_name'],
Chris@76 1132 'id' => $profile['id_member'],
Chris@76 1133 'is_buddy' => $profile['buddy'],
Chris@76 1134 'is_reverse_buddy' => in_array($user_info['id'], $buddy_list),
Chris@76 1135 'buddies' => $buddy_list,
Chris@76 1136 'title' => !empty($modSettings['titlesEnable']) ? $profile['usertitle'] : '',
Chris@76 1137 'href' => $scripturl . '?action=profile;u=' . $profile['id_member'],
Chris@76 1138 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $profile['id_member'] . '" title="' . $txt['profile_of'] . ' ' . $profile['real_name'] . '">' . $profile['real_name'] . '</a>',
Chris@76 1139 'email' => $profile['email_address'],
Chris@76 1140 'show_email' => showEmailAddress(!empty($profile['hide_email']), $profile['id_member']),
Chris@76 1141 'registered' => empty($profile['date_registered']) ? $txt['not_applicable'] : timeformat($profile['date_registered']),
Chris@76 1142 'registered_timestamp' => empty($profile['date_registered']) ? 0 : forum_time(true, $profile['date_registered']),
Chris@76 1143 'blurb' => $profile['personal_text'],
Chris@76 1144 'gender' => array(
Chris@76 1145 'name' => $gendertxt,
Chris@76 1146 'image' => !empty($profile['gender']) ? '<img class="gender" src="' . $settings['images_url'] . '/' . ($profile['gender'] == 1 ? 'Male' : 'Female') . '.gif" alt="' . $gendertxt . '" />' : ''
Chris@76 1147 ),
Chris@76 1148 'website' => array(
Chris@76 1149 'title' => $profile['website_title'],
Chris@76 1150 'url' => $profile['website_url'],
Chris@76 1151 ),
Chris@76 1152 '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']),
Chris@76 1153 'signature' => $profile['signature'],
Chris@76 1154 'location' => $profile['location'],
Chris@76 1155 'icq' => $profile['icq'] != '' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
Chris@76 1156 'name' => $profile['icq'],
Chris@76 1157 'href' => 'http://www.icq.com/whitepages/about_me.php?uin=' . $profile['icq'],
Chris@76 1158 '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>',
Chris@76 1159 '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>',
Chris@76 1160 ) : array('name' => '', 'add' => '', 'href' => '', 'link' => '', 'link_text' => ''),
Chris@76 1161 'aim' => $profile['aim'] != '' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
Chris@76 1162 'name' => $profile['aim'],
Chris@76 1163 'href' => 'aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'],
Chris@76 1164 'link' => '<a class="aim" href="aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'] . '" title="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '"><img src="' . $settings['images_url'] . '/aim.gif" alt="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '" /></a>',
Chris@76 1165 'link_text' => '<a class="aim" href="aim:goim?screenname=' . urlencode(strtr($profile['aim'], array(' ' => '%20'))) . '&amp;message=' . $txt['aim_default_message'] . '" title="' . $txt['aim_title'] . ' - ' . $profile['aim'] . '">' . $profile['aim'] . '</a>'
Chris@76 1166 ) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => ''),
Chris@76 1167 'yim' => $profile['yim'] != '' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
Chris@76 1168 'name' => $profile['yim'],
Chris@76 1169 'href' => 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']),
Chris@76 1170 'link' => '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']) . '" title="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '"><img src="http://opi.yahoo.com/online?u=' . urlencode($profile['yim']) . '&amp;m=g&amp;t=0" alt="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '" /></a>',
Chris@76 1171 'link_text' => '<a class="yim" href="http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($profile['yim']) . '" title="' . $txt['yim_title'] . ' - ' . $profile['yim'] . '">' . $profile['yim'] . '</a>'
Chris@76 1172 ) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => ''),
Chris@76 1173 'msn' => $profile['msn'] !='' && (empty($modSettings['guest_hideContacts']) || !$user_info['is_guest']) ? array(
Chris@76 1174 'name' => $profile['msn'],
Chris@76 1175 'href' => 'http://members.msn.com/' . $profile['msn'],
Chris@76 1176 'link' => '<a class="msn new_win" href="http://members.msn.com/' . $profile['msn'] . '" title="' . $txt['msn_title'] . ' - ' . $profile['msn'] . '"><img src="' . $settings['images_url'] . '/msntalk.gif" alt="' . $txt['msn_title'] . ' - ' . $profile['msn'] . '" /></a>',
Chris@76 1177 'link_text' => '<a class="msn new_win" href="http://members.msn.com/' . $profile['msn'] . '" title="' . $txt['msn_title'] . ' - ' . $profile['msn'] . '">' . $profile['msn'] . '</a>'
Chris@76 1178 ) : array('name' => '', 'href' => '', 'link' => '', 'link_text' => ''),
Chris@76 1179 'real_posts' => $profile['posts'],
Chris@76 1180 'posts' => $profile['posts'] > 500000 ? $txt['geek'] : comma_format($profile['posts']),
Chris@76 1181 'avatar' => array(
Chris@76 1182 'name' => $profile['avatar'],
Chris@76 1183 'image' => $profile['avatar'] == '' ? ($profile['id_attach'] > 0 ? '<img class="avatar" src="' . (empty($profile['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $profile['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $profile['filename']) . '" alt="" />' : '') : (stristr($profile['avatar'], 'http://') ? '<img class="avatar" src="' . $profile['avatar'] . '"' . $avatar_width . $avatar_height . ' alt="" />' : '<img class="avatar" src="' . $modSettings['avatar_url'] . '/' . htmlspecialchars($profile['avatar']) . '" alt="" />'),
Chris@76 1184 'href' => $profile['avatar'] == '' ? ($profile['id_attach'] > 0 ? (empty($profile['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $profile['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $profile['filename']) : '') : (stristr($profile['avatar'], 'http://') ? $profile['avatar'] : $modSettings['avatar_url'] . '/' . $profile['avatar']),
Chris@76 1185 'url' => $profile['avatar'] == '' ? '' : (stristr($profile['avatar'], 'http://') ? $profile['avatar'] : $modSettings['avatar_url'] . '/' . $profile['avatar'])
Chris@76 1186 ),
Chris@76 1187 'last_login' => empty($profile['last_login']) ? $txt['never'] : timeformat($profile['last_login']),
Chris@76 1188 'last_login_timestamp' => empty($profile['last_login']) ? 0 : forum_time(0, $profile['last_login']),
Chris@76 1189 'karma' => array(
Chris@76 1190 'good' => $profile['karma_good'],
Chris@76 1191 'bad' => $profile['karma_bad'],
Chris@76 1192 'allow' => !$user_info['is_guest'] && !empty($modSettings['karmaMode']) && $user_info['id'] != $user && allowedTo('karma_edit') &&
Chris@76 1193 ($user_info['posts'] >= $modSettings['karmaMinPosts'] || $user_info['is_admin']),
Chris@76 1194 ),
Chris@76 1195 'ip' => htmlspecialchars($profile['member_ip']),
Chris@76 1196 'ip2' => htmlspecialchars($profile['member_ip2']),
Chris@76 1197 'online' => array(
Chris@76 1198 'is_online' => $profile['is_online'],
Chris@76 1199 'text' => $txt[$profile['is_online'] ? 'online' : 'offline'],
Chris@76 1200 'href' => $scripturl . '?action=pm;sa=send;u=' . $profile['id_member'],
Chris@76 1201 'link' => '<a href="' . $scripturl . '?action=pm;sa=send;u=' . $profile['id_member'] . '">' . $txt[$profile['is_online'] ? 'online' : 'offline'] . '</a>',
Chris@76 1202 'image_href' => $settings['images_url'] . '/' . ($profile['buddy'] ? 'buddy_' : '') . ($profile['is_online'] ? 'useron' : 'useroff') . '.gif',
Chris@76 1203 'label' => $txt[$profile['is_online'] ? 'online' : 'offline']
Chris@76 1204 ),
Chris@76 1205 'language' => $smcFunc['ucwords'](strtr($profile['lngfile'], array('_' => ' ', '-utf8' => ''))),
Chris@76 1206 'is_activated' => isset($profile['is_activated']) ? $profile['is_activated'] : 1,
Chris@76 1207 'is_banned' => isset($profile['is_activated']) ? $profile['is_activated'] >= 10 : 0,
Chris@76 1208 'options' => $profile['options'],
Chris@76 1209 'is_guest' => false,
Chris@76 1210 'group' => $profile['member_group'],
Chris@76 1211 'group_color' => $profile['member_group_color'],
Chris@76 1212 'group_id' => $profile['id_group'],
Chris@76 1213 'post_group' => $profile['post_group'],
Chris@76 1214 'post_group_color' => $profile['post_group_color'],
Chris@76 1215 'group_stars' => str_repeat('<img src="' . str_replace('$language', $context['user']['language'], isset($profile['stars'][1]) ? $settings['images_url'] . '/' . $profile['stars'][1] : '') . '" alt="*" />', empty($profile['stars'][0]) || empty($profile['stars'][1]) ? 0 : $profile['stars'][0]),
Chris@76 1216 'warning' => $profile['warning'],
Chris@76 1217 'warning_status' => !empty($modSettings['warning_mute']) && $modSettings['warning_mute'] <= $profile['warning'] ? 'mute' : (!empty($modSettings['warning_moderate']) && $modSettings['warning_moderate'] <= $profile['warning'] ? 'moderate' : (!empty($modSettings['warning_watch']) && $modSettings['warning_watch'] <= $profile['warning'] ? 'watch' : (''))),
Chris@76 1218 'local_time' => timeformat(time() + ($profile['time_offset'] - $user_info['time_offset']) * 3600, false),
Chris@76 1219 );
Chris@76 1220
Chris@76 1221 // First do a quick run through to make sure there is something to be shown.
Chris@76 1222 $memberContext[$user]['has_messenger'] = false;
Chris@76 1223 foreach (array('icq', 'msn', 'aim', 'yim') as $messenger)
Chris@76 1224 {
Chris@76 1225 if (!isset($context['disabled_fields'][$messenger]) && !empty($memberContext[$user][$messenger]['link']))
Chris@76 1226 {
Chris@76 1227 $memberContext[$user]['has_messenger'] = true;
Chris@76 1228 break;
Chris@76 1229 }
Chris@76 1230 }
Chris@76 1231
Chris@76 1232 // Are we also loading the members custom fields into context?
Chris@76 1233 if ($display_custom_fields && !empty($modSettings['displayFields']))
Chris@76 1234 {
Chris@76 1235 $memberContext[$user]['custom_fields'] = array();
Chris@76 1236 if (!isset($context['display_fields']))
Chris@76 1237 $context['display_fields'] = unserialize($modSettings['displayFields']);
Chris@76 1238
Chris@76 1239 foreach ($context['display_fields'] as $custom)
Chris@76 1240 {
Chris@76 1241 if (empty($custom['title']) || empty($profile['options'][$custom['colname']]))
Chris@76 1242 continue;
Chris@76 1243
Chris@76 1244 $value = $profile['options'][$custom['colname']];
Chris@76 1245
Chris@76 1246 // BBC?
Chris@76 1247 if ($custom['bbc'])
Chris@76 1248 $value = parse_bbc($value);
Chris@76 1249 // ... or checkbox?
Chris@76 1250 elseif (isset($custom['type']) && $custom['type'] == 'check')
Chris@76 1251 $value = $value ? $txt['yes'] : $txt['no'];
Chris@76 1252
Chris@76 1253 // Enclosing the user input within some other text?
Chris@76 1254 if (!empty($custom['enclose']))
Chris@76 1255 $value = strtr($custom['enclose'], array(
Chris@76 1256 '{SCRIPTURL}' => $scripturl,
Chris@76 1257 '{IMAGES_URL}' => $settings['images_url'],
Chris@76 1258 '{DEFAULT_IMAGES_URL}' => $settings['default_images_url'],
Chris@76 1259 '{INPUT}' => $value,
Chris@76 1260 ));
Chris@76 1261
Chris@76 1262 $memberContext[$user]['custom_fields'][] = array(
Chris@76 1263 'title' => $custom['title'],
Chris@76 1264 'colname' => $custom['colname'],
Chris@76 1265 'value' => $value,
Chris@76 1266 'placement' => !empty($custom['placement']) ? $custom['placement'] : 0,
Chris@76 1267 );
Chris@76 1268 }
Chris@76 1269 }
Chris@76 1270
Chris@76 1271 return true;
Chris@76 1272 }
Chris@76 1273
Chris@76 1274 function detectBrowser()
Chris@76 1275 {
Chris@76 1276 global $context, $user_info;
Chris@76 1277
Chris@76 1278 // The following determines the user agent (browser) as best it can.
Chris@76 1279 $context['browser'] = array(
Chris@76 1280 'is_opera' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false,
Chris@76 1281 'is_opera6' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 6') !== false,
Chris@76 1282 'is_opera7' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 7') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/7') !== false,
Chris@76 1283 'is_opera8' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 8') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/8') !== false,
Chris@76 1284 'is_opera9' => preg_match('~Opera[ /]9(?!\\.[89])~', $_SERVER['HTTP_USER_AGENT']) === 1,
Chris@76 1285 'is_opera10' => preg_match('~Opera[ /]10\\.~', $_SERVER['HTTP_USER_AGENT']) === 1 || (preg_match('~Opera[ /]9\\.[89]~', $_SERVER['HTTP_USER_AGENT']) === 1 && preg_match('~Version/1[0-9]\\.~', $_SERVER['HTTP_USER_AGENT']) === 1),
Chris@76 1286 'is_ie4' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 4') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') === false,
Chris@76 1287 'is_webkit' => strpos($_SERVER['HTTP_USER_AGENT'], 'AppleWebKit') !== false,
Chris@76 1288 'is_mac_ie' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') !== false,
Chris@76 1289 'is_web_tv' => strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') !== false,
Chris@76 1290 'is_konqueror' => strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false,
Chris@76 1291 'is_firefox' => preg_match('~(?:Firefox|Ice[wW]easel|IceCat)/~', $_SERVER['HTTP_USER_AGENT']) === 1,
Chris@76 1292 'is_firefox1' => preg_match('~(?:Firefox|Ice[wW]easel|IceCat)/1\\.~', $_SERVER['HTTP_USER_AGENT']) === 1,
Chris@76 1293 'is_firefox2' => preg_match('~(?:Firefox|Ice[wW]easel|IceCat)/2\\.~', $_SERVER['HTTP_USER_AGENT']) === 1,
Chris@76 1294 'is_firefox3' => preg_match('~(?:Firefox|Ice[wW]easel|IceCat|Shiretoko|Minefield)/3\\.~', $_SERVER['HTTP_USER_AGENT']) === 1,
Chris@76 1295 'is_iphone' => strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'iPod') !== false,
Chris@76 1296 'is_android' => strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false,
Chris@76 1297 );
Chris@76 1298
Chris@76 1299 $context['browser']['is_chrome'] = $context['browser']['is_webkit'] && strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false;
Chris@76 1300 $context['browser']['is_safari'] = !$context['browser']['is_chrome'] && strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== false;
Chris@76 1301 $context['browser']['is_gecko'] = strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false && !$context['browser']['is_webkit'] && !$context['browser']['is_konqueror'];
Chris@76 1302
Chris@76 1303 // Internet Explorer 5 and 6 are often "emulated".
Chris@76 1304 $context['browser']['is_ie8'] = !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'] && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 8') !== false;
Chris@76 1305 $context['browser']['is_ie7'] = !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'] && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !$context['browser']['is_ie8'];
Chris@76 1306 $context['browser']['is_ie6'] = !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'] && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6') !== false && !$context['browser']['is_ie8'] && !$context['browser']['is_ie7'];
Chris@76 1307 $context['browser']['is_ie5.5'] = !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'] && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.5') !== false;
Chris@76 1308 $context['browser']['is_ie5'] = !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'] && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.0') !== false;
Chris@76 1309
Chris@76 1310 $context['browser']['is_ie'] = $context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie6'] || $context['browser']['is_ie7'] || $context['browser']['is_ie8'];
Chris@76 1311 // Before IE8 we need to fix IE... lots!
Chris@76 1312 $context['browser']['ie_standards_fix'] = !$context['browser']['is_ie8'];
Chris@76 1313
Chris@76 1314 $context['browser']['needs_size_fix'] = ($context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie4'] || $context['browser']['is_opera6']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false;
Chris@76 1315
Chris@76 1316 // This isn't meant to be reliable, it's just meant to catch most bots to prevent PHPSESSID from showing up.
Chris@76 1317 $context['browser']['possibly_robot'] = !empty($user_info['possibly_robot']);
Chris@76 1318
Chris@76 1319 // Robots shouldn't be logging in or registering. So, they aren't a bot. Better to be wrong than sorry (or people won't be able to log in!), anyway.
Chris@76 1320 if ((isset($_REQUEST['action']) && in_array($_REQUEST['action'], array('login', 'login2', 'register'))) || !$user_info['is_guest'])
Chris@76 1321 $context['browser']['possibly_robot'] = false;
Chris@76 1322 }
Chris@76 1323
Chris@76 1324 // Load a theme, by ID.
Chris@76 1325 function loadTheme($id_theme = 0, $initialize = true)
Chris@76 1326 {
Chris@76 1327 global $user_info, $user_settings, $board_info, $sc, $boarddir;
Chris@76 1328 global $txt, $boardurl, $scripturl, $mbname, $modSettings, $language;
Chris@76 1329 global $context, $settings, $options, $sourcedir, $ssi_theme, $smcFunc;
Chris@76 1330
Chris@76 1331 // The theme was specified by parameter.
Chris@76 1332 if (!empty($id_theme))
Chris@76 1333 $id_theme = (int) $id_theme;
Chris@76 1334 // The theme was specified by REQUEST.
Chris@76 1335 elseif (!empty($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum')))
Chris@76 1336 {
Chris@76 1337 $id_theme = (int) $_REQUEST['theme'];
Chris@76 1338 $_SESSION['id_theme'] = $id_theme;
Chris@76 1339 }
Chris@76 1340 // The theme was specified by REQUEST... previously.
Chris@76 1341 elseif (!empty($_SESSION['id_theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum')))
Chris@76 1342 $id_theme = (int) $_SESSION['id_theme'];
Chris@76 1343 // The theme is just the user's choice. (might use ?board=1;theme=0 to force board theme.)
Chris@76 1344 elseif (!empty($user_info['theme']) && !isset($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum')))
Chris@76 1345 $id_theme = $user_info['theme'];
Chris@76 1346 // The theme was specified by the board.
Chris@76 1347 elseif (!empty($board_info['theme']))
Chris@76 1348 $id_theme = $board_info['theme'];
Chris@76 1349 // The theme is the forum's default.
Chris@76 1350 else
Chris@76 1351 $id_theme = $modSettings['theme_guests'];
Chris@76 1352
Chris@76 1353 // Verify the id_theme... no foul play.
Chris@76 1354 // Always allow the board specific theme, if they are overriding.
Chris@76 1355 if (!empty($board_info['theme']) && $board_info['override_theme'])
Chris@76 1356 $id_theme = $board_info['theme'];
Chris@76 1357 // If they have specified a particular theme to use with SSI allow it to be used.
Chris@76 1358 elseif (!empty($ssi_theme) && $id_theme == $ssi_theme)
Chris@76 1359 $id_theme = (int) $id_theme;
Chris@76 1360 elseif (!empty($modSettings['knownThemes']) && !allowedTo('admin_forum'))
Chris@76 1361 {
Chris@76 1362 $themes = explode(',', $modSettings['knownThemes']);
Chris@76 1363 if (!in_array($id_theme, $themes))
Chris@76 1364 $id_theme = $modSettings['theme_guests'];
Chris@76 1365 else
Chris@76 1366 $id_theme = (int) $id_theme;
Chris@76 1367 }
Chris@76 1368 else
Chris@76 1369 $id_theme = (int) $id_theme;
Chris@76 1370
Chris@76 1371 $member = empty($user_info['id']) ? -1 : $user_info['id'];
Chris@76 1372
Chris@76 1373 if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2 && ($temp = cache_get_data('theme_settings-' . $id_theme . ':' . $member, 60)) != null && time() - 60 > $modSettings['settings_updated'])
Chris@76 1374 {
Chris@76 1375 $themeData = $temp;
Chris@76 1376 $flag = true;
Chris@76 1377 }
Chris@76 1378 elseif (($temp = cache_get_data('theme_settings-' . $id_theme, 90)) != null && time() - 60 > $modSettings['settings_updated'])
Chris@76 1379 $themeData = $temp + array($member => array());
Chris@76 1380 else
Chris@76 1381 $themeData = array(-1 => array(), 0 => array(), $member => array());
Chris@76 1382
Chris@76 1383 if (empty($flag))
Chris@76 1384 {
Chris@76 1385 // Load variables from the current or default theme, global or this user's.
Chris@76 1386 $result = $smcFunc['db_query']('', '
Chris@76 1387 SELECT variable, value, id_member, id_theme
Chris@76 1388 FROM {db_prefix}themes
Chris@76 1389 WHERE id_member' . (empty($themeData[0]) ? ' IN (-1, 0, {int:id_member})' : ' = {int:id_member}') . '
Chris@76 1390 AND id_theme' . ($id_theme == 1 ? ' = {int:id_theme}' : ' IN ({int:id_theme}, 1)'),
Chris@76 1391 array(
Chris@76 1392 'id_theme' => $id_theme,
Chris@76 1393 'id_member' => $member,
Chris@76 1394 )
Chris@76 1395 );
Chris@76 1396 // Pick between $settings and $options depending on whose data it is.
Chris@76 1397 while ($row = $smcFunc['db_fetch_assoc']($result))
Chris@76 1398 {
Chris@76 1399 // There are just things we shouldn't be able to change as members.
Chris@76 1400 if ($row['id_member'] != 0 && in_array($row['variable'], array('actual_theme_url', 'actual_images_url', 'base_theme_dir', 'base_theme_url', 'default_images_url', 'default_theme_dir', 'default_theme_url', 'default_template', 'images_url', 'number_recent_posts', 'smiley_sets_default', 'theme_dir', 'theme_id', 'theme_layers', 'theme_templates', 'theme_url')))
Chris@76 1401 continue;
Chris@76 1402
Chris@76 1403 // If this is the theme_dir of the default theme, store it.
Chris@76 1404 if (in_array($row['variable'], array('theme_dir', 'theme_url', 'images_url')) && $row['id_theme'] == '1' && empty($row['id_member']))
Chris@76 1405 $themeData[0]['default_' . $row['variable']] = $row['value'];
Chris@76 1406
Chris@76 1407 // If this isn't set yet, is a theme option, or is not the default theme..
Chris@76 1408 if (!isset($themeData[$row['id_member']][$row['variable']]) || $row['id_theme'] != '1')
Chris@76 1409 $themeData[$row['id_member']][$row['variable']] = substr($row['variable'], 0, 5) == 'show_' ? $row['value'] == '1' : $row['value'];
Chris@76 1410 }
Chris@76 1411 $smcFunc['db_free_result']($result);
Chris@76 1412
Chris@76 1413 if (!empty($themeData[-1]))
Chris@76 1414 foreach ($themeData[-1] as $k => $v)
Chris@76 1415 {
Chris@76 1416 if (!isset($themeData[$member][$k]))
Chris@76 1417 $themeData[$member][$k] = $v;
Chris@76 1418 }
Chris@76 1419
Chris@76 1420 if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2)
Chris@76 1421 cache_put_data('theme_settings-' . $id_theme . ':' . $member, $themeData, 60);
Chris@76 1422 // Only if we didn't already load that part of the cache...
Chris@76 1423 elseif (!isset($temp))
Chris@76 1424 cache_put_data('theme_settings-' . $id_theme, array(-1 => $themeData[-1], 0 => $themeData[0]), 90);
Chris@76 1425 }
Chris@76 1426
Chris@76 1427 $settings = $themeData[0];
Chris@76 1428 $options = $themeData[$member];
Chris@76 1429
Chris@76 1430 $settings['theme_id'] = $id_theme;
Chris@76 1431
Chris@76 1432 $settings['actual_theme_url'] = $settings['theme_url'];
Chris@76 1433 $settings['actual_images_url'] = $settings['images_url'];
Chris@76 1434 $settings['actual_theme_dir'] = $settings['theme_dir'];
Chris@76 1435
Chris@76 1436 $settings['template_dirs'] = array();
Chris@76 1437 // This theme first.
Chris@76 1438 $settings['template_dirs'][] = $settings['theme_dir'];
Chris@76 1439
Chris@76 1440 // Based on theme (if there is one).
Chris@76 1441 if (!empty($settings['base_theme_dir']))
Chris@76 1442 $settings['template_dirs'][] = $settings['base_theme_dir'];
Chris@76 1443
Chris@76 1444 // Lastly the default theme.
Chris@76 1445 if ($settings['theme_dir'] != $settings['default_theme_dir'])
Chris@76 1446 $settings['template_dirs'][] = $settings['default_theme_dir'];
Chris@76 1447
Chris@76 1448 if (!$initialize)
Chris@76 1449 return;
Chris@76 1450
Chris@76 1451 // Check to see if they're accessing it from the wrong place.
Chris@76 1452 if (isset($_SERVER['HTTP_HOST']) || isset($_SERVER['SERVER_NAME']))
Chris@76 1453 {
Chris@76 1454 $detected_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 'https://' : 'http://';
Chris@76 1455 $detected_url .= empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST'];
Chris@76 1456 $temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(dirname($_SERVER['PHP_SELF']), '\\', '/'));
Chris@76 1457 if ($temp != '/')
Chris@76 1458 $detected_url .= $temp;
Chris@76 1459 }
Chris@76 1460 if (isset($detected_url) && $detected_url != $boardurl)
Chris@76 1461 {
Chris@76 1462 // Try #1 - check if it's in a list of alias addresses.
Chris@76 1463 if (!empty($modSettings['forum_alias_urls']))
Chris@76 1464 {
Chris@76 1465 $aliases = explode(',', $modSettings['forum_alias_urls']);
Chris@76 1466
Chris@76 1467 foreach ($aliases as $alias)
Chris@76 1468 {
Chris@76 1469 // Rip off all the boring parts, spaces, etc.
Chris@76 1470 if ($detected_url == trim($alias) || strtr($detected_url, array('http://' => '', 'https://' => '')) == trim($alias))
Chris@76 1471 $do_fix = true;
Chris@76 1472 }
Chris@76 1473 }
Chris@76 1474
Chris@76 1475 // Hmm... check #2 - is it just different by a www? Send them to the correct place!!
Chris@76 1476 if (empty($do_fix) && strtr($detected_url, array('://' => '://www.')) == $boardurl && (empty($_GET) || count($_GET) == 1) && SMF != 'SSI')
Chris@76 1477 {
Chris@76 1478 // Okay, this seems weird, but we don't want an endless loop - this will make $_GET not empty ;).
Chris@76 1479 if (empty($_GET))
Chris@76 1480 redirectexit('wwwRedirect');
Chris@76 1481 else
Chris@76 1482 {
Chris@76 1483 list ($k, $v) = each($_GET);
Chris@76 1484
Chris@76 1485 if ($k != 'wwwRedirect')
Chris@76 1486 redirectexit('wwwRedirect;' . $k . '=' . $v);
Chris@76 1487 }
Chris@76 1488 }
Chris@76 1489
Chris@76 1490 // #3 is just a check for SSL...
Chris@76 1491 if (strtr($detected_url, array('https://' => 'http://')) == $boardurl)
Chris@76 1492 $do_fix = true;
Chris@76 1493
Chris@76 1494 // Okay, #4 - perhaps it's an IP address? We're gonna want to use that one, then. (assuming it's the IP or something...)
Chris@76 1495 if (!empty($do_fix) || preg_match('~^http[s]?://(?:[\d\.:]+|\[[\d:]+\](?::\d+)?)(?:$|/)~', $detected_url) == 1)
Chris@76 1496 {
Chris@76 1497 // Caching is good ;).
Chris@76 1498 $oldurl = $boardurl;
Chris@76 1499
Chris@76 1500 // Fix $boardurl and $scripturl.
Chris@76 1501 $boardurl = $detected_url;
Chris@76 1502 $scripturl = strtr($scripturl, array($oldurl => $boardurl));
Chris@76 1503 $_SERVER['REQUEST_URL'] = strtr($_SERVER['REQUEST_URL'], array($oldurl => $boardurl));
Chris@76 1504
Chris@76 1505 // Fix the theme urls...
Chris@76 1506 $settings['theme_url'] = strtr($settings['theme_url'], array($oldurl => $boardurl));
Chris@76 1507 $settings['default_theme_url'] = strtr($settings['default_theme_url'], array($oldurl => $boardurl));
Chris@76 1508 $settings['actual_theme_url'] = strtr($settings['actual_theme_url'], array($oldurl => $boardurl));
Chris@76 1509 $settings['images_url'] = strtr($settings['images_url'], array($oldurl => $boardurl));
Chris@76 1510 $settings['default_images_url'] = strtr($settings['default_images_url'], array($oldurl => $boardurl));
Chris@76 1511 $settings['actual_images_url'] = strtr($settings['actual_images_url'], array($oldurl => $boardurl));
Chris@76 1512
Chris@76 1513 // And just a few mod settings :).
Chris@76 1514 $modSettings['smileys_url'] = strtr($modSettings['smileys_url'], array($oldurl => $boardurl));
Chris@76 1515 $modSettings['avatar_url'] = strtr($modSettings['avatar_url'], array($oldurl => $boardurl));
Chris@76 1516
Chris@76 1517 // Clean up after loadBoard().
Chris@76 1518 if (isset($board_info['moderators']))
Chris@76 1519 {
Chris@76 1520 foreach ($board_info['moderators'] as $k => $dummy)
Chris@76 1521 {
Chris@76 1522 $board_info['moderators'][$k]['href'] = strtr($dummy['href'], array($oldurl => $boardurl));
Chris@76 1523 $board_info['moderators'][$k]['link'] = strtr($dummy['link'], array('"' . $oldurl => '"' . $boardurl));
Chris@76 1524 }
Chris@76 1525 }
Chris@76 1526 foreach ($context['linktree'] as $k => $dummy)
Chris@76 1527 $context['linktree'][$k]['url'] = strtr($dummy['url'], array($oldurl => $boardurl));
Chris@76 1528 }
Chris@76 1529 }
Chris@76 1530 // Set up the contextual user array.
Chris@76 1531 $context['user'] = array(
Chris@76 1532 'id' => $user_info['id'],
Chris@76 1533 'is_logged' => !$user_info['is_guest'],
Chris@76 1534 'is_guest' => &$user_info['is_guest'],
Chris@76 1535 'is_admin' => &$user_info['is_admin'],
Chris@76 1536 'is_mod' => &$user_info['is_mod'],
Chris@76 1537 // A user can mod if they have permission to see the mod center, or they are a board/group/approval moderator.
Chris@76 1538 'can_mod' => allowedTo('access_mod_center') || (!$user_info['is_guest'] && ($user_info['mod_cache']['gq'] != '0=1' || $user_info['mod_cache']['bq'] != '0=1' || ($modSettings['postmod_active'] && !empty($user_info['mod_cache']['ap'])))),
Chris@76 1539 'username' => $user_info['username'],
Chris@76 1540 'language' => $user_info['language'],
Chris@76 1541 'email' => $user_info['email'],
Chris@76 1542 'ignoreusers' => $user_info['ignoreusers'],
Chris@76 1543 );
Chris@76 1544 if (!$context['user']['is_guest'])
Chris@76 1545 $context['user']['name'] = $user_info['name'];
Chris@76 1546 elseif ($context['user']['is_guest'] && !empty($txt['guest_title']))
Chris@76 1547 $context['user']['name'] = $txt['guest_title'];
Chris@76 1548
Chris@76 1549 // Determine the current smiley set.
Chris@76 1550 $user_info['smiley_set'] = (!in_array($user_info['smiley_set'], explode(',', $modSettings['smiley_sets_known'])) && $user_info['smiley_set'] != 'none') || empty($modSettings['smiley_sets_enable']) ? (!empty($settings['smiley_sets_default']) ? $settings['smiley_sets_default'] : $modSettings['smiley_sets_default']) : $user_info['smiley_set'];
Chris@76 1551 $context['user']['smiley_set'] = $user_info['smiley_set'];
Chris@76 1552
Chris@76 1553 // Some basic information...
Chris@76 1554 if (!isset($context['html_headers']))
Chris@76 1555 $context['html_headers'] = '';
Chris@76 1556
Chris@76 1557 $context['menu_separator'] = !empty($settings['use_image_buttons']) ? ' ' : ' | ';
Chris@76 1558 $context['session_var'] = $_SESSION['session_var'];
Chris@76 1559 $context['session_id'] = $_SESSION['session_value'];
Chris@76 1560 $context['forum_name'] = $mbname;
Chris@76 1561 $context['forum_name_html_safe'] = $smcFunc['htmlspecialchars']($context['forum_name']);
Chris@76 1562 $context['header_logo_url_html_safe'] = empty($settings['header_logo_url']) ? '' : $smcFunc['htmlspecialchars']($settings['header_logo_url']);
Chris@76 1563 $context['current_action'] = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
Chris@76 1564 $context['current_subaction'] = isset($_REQUEST['sa']) ? $_REQUEST['sa'] : null;
Chris@76 1565 if (isset($modSettings['load_average']))
Chris@76 1566 $context['load_average'] = $modSettings['load_average'];
Chris@76 1567
Chris@76 1568 // Set some permission related settings.
Chris@76 1569 $context['show_login_bar'] = $user_info['is_guest'] && !empty($modSettings['enableVBStyleLogin']);
Chris@76 1570
Chris@76 1571 // This determines the server... not used in many places, except for login fixing.
Chris@76 1572 $context['server'] = array(
Chris@76 1573 'is_iis' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false,
Chris@76 1574 'is_apache' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false,
Chris@76 1575 'is_lighttpd' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false,
Chris@76 1576 'is_nginx' => isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false,
Chris@76 1577 'is_cgi' => isset($_SERVER['SERVER_SOFTWARE']) && strpos(php_sapi_name(), 'cgi') !== false,
Chris@76 1578 'is_windows' => strpos(PHP_OS, 'WIN') === 0,
Chris@76 1579 'iso_case_folding' => ord(strtolower(chr(138))) === 154,
Chris@76 1580 'complex_preg_chars' => @version_compare(PHP_VERSION, '4.3.3') != -1,
Chris@76 1581 );
Chris@76 1582 // A bug in some versions of IIS under CGI (older ones) makes cookie setting not work with Location: headers.
Chris@76 1583 $context['server']['needs_login_fix'] = $context['server']['is_cgi'] && $context['server']['is_iis'];
Chris@76 1584
Chris@76 1585 // Detect the browser. This is separated out because it's also used in attachment downloads
Chris@76 1586 detectBrowser();
Chris@76 1587
Chris@76 1588 // Set the top level linktree up.
Chris@76 1589 array_unshift($context['linktree'], array(
Chris@76 1590 'url' => $scripturl,
Chris@76 1591 'name' => $context['forum_name_html_safe']
Chris@76 1592 ));
Chris@76 1593
Chris@76 1594 // This allows sticking some HTML on the page output - useful for controls.
Chris@76 1595 $context['insert_after_template'] = '';
Chris@76 1596
Chris@76 1597 if (!isset($txt))
Chris@76 1598 $txt = array();
Chris@76 1599 $simpleActions = array(
Chris@76 1600 'findmember',
Chris@76 1601 'helpadmin',
Chris@76 1602 'printpage',
Chris@76 1603 'quotefast',
Chris@76 1604 'spellcheck',
Chris@76 1605 );
Chris@76 1606
Chris@76 1607 // Wireless mode? Load up the wireless stuff.
Chris@76 1608 if (WIRELESS)
Chris@76 1609 {
Chris@76 1610 $context['template_layers'] = array(WIRELESS_PROTOCOL);
Chris@76 1611 loadTemplate('Wireless');
Chris@76 1612 loadLanguage('Wireless+index+Modifications');
Chris@76 1613 }
Chris@76 1614 // Output is fully XML, so no need for the index template.
Chris@76 1615 elseif (isset($_REQUEST['xml']))
Chris@76 1616 {
Chris@76 1617 loadLanguage('index+Modifications');
Chris@76 1618 loadTemplate('Xml');
Chris@76 1619 $context['template_layers'] = array();
Chris@76 1620 }
Chris@76 1621 // These actions don't require the index template at all.
Chris@76 1622 elseif (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], $simpleActions))
Chris@76 1623 {
Chris@76 1624 loadLanguage('index+Modifications');
Chris@76 1625 $context['template_layers'] = array();
Chris@76 1626 }
Chris@76 1627 else
Chris@76 1628 {
Chris@76 1629 // Custom templates to load, or just default?
Chris@76 1630 if (isset($settings['theme_templates']))
Chris@76 1631 $templates = explode(',', $settings['theme_templates']);
Chris@76 1632 else
Chris@76 1633 $templates = array('index');
Chris@76 1634
Chris@76 1635 // Load each template...
Chris@76 1636 foreach ($templates as $template)
Chris@76 1637 loadTemplate($template);
Chris@76 1638
Chris@76 1639 // ...and attempt to load their associated language files.
Chris@76 1640 $required_files = implode('+', array_merge($templates, array('Modifications')));
Chris@76 1641 loadLanguage($required_files, '', false);
Chris@76 1642
Chris@76 1643 // Custom template layers?
Chris@76 1644 if (isset($settings['theme_layers']))
Chris@76 1645 $context['template_layers'] = explode(',', $settings['theme_layers']);
Chris@76 1646 else
Chris@76 1647 $context['template_layers'] = array('html', 'body');
Chris@76 1648 }
Chris@76 1649
Chris@76 1650 // Initialize the theme.
Chris@76 1651 loadSubTemplate('init', 'ignore');
Chris@76 1652
Chris@76 1653 // Load the compatibility stylesheet if the theme hasn't been updated for 2.0 RC2 (yet).
Chris@76 1654 if (isset($settings['theme_version']) && (version_compare($settings['theme_version'], '2.0 RC2', '<') || strpos($settings['theme_version'], '2.0 Beta') !== false))
Chris@76 1655 loadTemplate(false, 'compat');
Chris@76 1656
Chris@76 1657 // Guests may still need a name.
Chris@76 1658 if ($context['user']['is_guest'] && empty($context['user']['name']))
Chris@76 1659 $context['user']['name'] = $txt['guest_title'];
Chris@76 1660
Chris@76 1661 // Any theme-related strings that need to be loaded?
Chris@76 1662 if (!empty($settings['require_theme_strings']))
Chris@76 1663 loadLanguage('ThemeStrings', '', false);
Chris@76 1664
Chris@76 1665 // We allow theme variants, because we're cool.
Chris@76 1666 $context['theme_variant'] = '';
Chris@76 1667 $context['theme_variant_url'] = '';
Chris@76 1668 if (!empty($settings['theme_variants']))
Chris@76 1669 {
Chris@76 1670 // Overriding - for previews and that ilk.
Chris@76 1671 if (!empty($_REQUEST['variant']))
Chris@76 1672 $_SESSION['id_variant'] = $_REQUEST['variant'];
Chris@76 1673 // User selection?
Chris@76 1674 if (empty($settings['disable_user_variant']) || allowedTo('admin_forum'))
Chris@76 1675 $context['theme_variant'] = !empty($_SESSION['id_variant']) ? $_SESSION['id_variant'] : (!empty($options['theme_variant']) ? $options['theme_variant'] : '');
Chris@76 1676 // If not a user variant, select the default.
Chris@76 1677 if ($context['theme_variant'] == '' || !in_array($context['theme_variant'], $settings['theme_variants']))
Chris@76 1678 $context['theme_variant'] = !empty($settings['default_variant']) && in_array($settings['default_variant'], $settings['theme_variants']) ? $settings['default_variant'] : $settings['theme_variants'][0];
Chris@76 1679
Chris@76 1680 // Do this to keep things easier in the templates.
Chris@76 1681 $context['theme_variant'] = '_' . $context['theme_variant'];
Chris@76 1682 $context['theme_variant_url'] = $context['theme_variant'] . '/';
Chris@76 1683 }
Chris@76 1684
Chris@76 1685 // Let's be compatible with old themes!
Chris@76 1686 if (!function_exists('template_html_above') && in_array('html', $context['template_layers']))
Chris@76 1687 $context['template_layers'] = array('main');
Chris@76 1688
Chris@76 1689 // Allow overriding the board wide time/number formats.
Chris@76 1690 if (empty($user_settings['time_format']) && !empty($txt['time_format']))
Chris@76 1691 $user_info['time_format'] = $txt['time_format'];
Chris@76 1692 $txt['number_format'] = empty($txt['number_format']) ? empty($modSettings['number_format']) ? '' : $modSettings['number_format'] : $txt['number_format'];
Chris@76 1693
Chris@76 1694 if (isset($settings['use_default_images']) && $settings['use_default_images'] == 'always')
Chris@76 1695 {
Chris@76 1696 $settings['theme_url'] = $settings['default_theme_url'];
Chris@76 1697 $settings['images_url'] = $settings['default_images_url'];
Chris@76 1698 $settings['theme_dir'] = $settings['default_theme_dir'];
Chris@76 1699 }
Chris@76 1700 // Make a special URL for the language.
Chris@76 1701 $settings['lang_images_url'] = $settings['images_url'] . '/' . (!empty($txt['image_lang']) ? $txt['image_lang'] : $user_info['language']);
Chris@76 1702
Chris@76 1703 // Set the character set from the template.
Chris@76 1704 $context['character_set'] = empty($modSettings['global_character_set']) ? $txt['lang_character_set'] : $modSettings['global_character_set'];
Chris@76 1705 $context['utf8'] = $context['character_set'] === 'UTF-8' && (strpos(strtolower(PHP_OS), 'win') === false || @version_compare(PHP_VERSION, '4.2.3') != -1);
Chris@76 1706 $context['right_to_left'] = !empty($txt['lang_rtl']);
Chris@76 1707
Chris@76 1708 $context['tabindex'] = 1;
Chris@76 1709
Chris@76 1710 // Fix font size with HTML 4.01, etc.
Chris@76 1711 if (isset($settings['doctype']))
Chris@76 1712 $context['browser']['needs_size_fix'] |= $settings['doctype'] == 'html' && $context['browser']['is_ie6'];
Chris@76 1713
Chris@76 1714 // Compatibility.
Chris@76 1715 if (!isset($settings['theme_version']))
Chris@76 1716 $modSettings['memberCount'] = $modSettings['totalMembers'];
Chris@76 1717
Chris@76 1718 // This allows us to change the way things look for the admin.
Chris@76 1719 $context['admin_features'] = isset($modSettings['admin_features']) ? explode(',', $modSettings['admin_features']) : array('cd,cp,k,w,rg,ml,pm');
Chris@76 1720
Chris@76 1721 // If we think we have mail to send, let's offer up some possibilities... robots get pain (Now with scheduled task support!)
Chris@76 1722 if ((!empty($modSettings['mail_next_send']) && $modSettings['mail_next_send'] < time() && empty($modSettings['mail_queue_use_cron'])) || empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time())
Chris@76 1723 {
Chris@76 1724 if ($context['browser']['possibly_robot'])
Chris@76 1725 {
Chris@76 1726 //!!! Maybe move this somewhere better?!
Chris@76 1727 require_once($sourcedir . '/ScheduledTasks.php');
Chris@76 1728
Chris@76 1729 // What to do, what to do?!
Chris@76 1730 if (empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time())
Chris@76 1731 AutoTask();
Chris@76 1732 else
Chris@76 1733 ReduceMailQueue();
Chris@76 1734 }
Chris@76 1735 else
Chris@76 1736 {
Chris@76 1737 $type = empty($modSettings['next_task_time']) || $modSettings['next_task_time'] < time() ? 'task' : 'mailq';
Chris@76 1738 $ts = $type == 'mailq' ? $modSettings['mail_next_send'] : $modSettings['next_task_time'];
Chris@76 1739
Chris@76 1740 $context['html_headers'] .= '
Chris@76 1741 <script type="text/javascript">
Chris@76 1742 function smfAutoTask()
Chris@76 1743 {
Chris@76 1744 var tempImage = new Image();
Chris@76 1745 tempImage.src = "' . $scripturl . '?scheduled=' . $type . ';ts=' . $ts . '";
Chris@76 1746 }
Chris@76 1747 window.setTimeout("smfAutoTask();", 1);
Chris@76 1748 </script>';
Chris@76 1749 }
Chris@76 1750 }
Chris@76 1751
Chris@76 1752 // Any files to include at this point?
Chris@76 1753 if (!empty($modSettings['integrate_theme_include']))
Chris@76 1754 {
Chris@76 1755 $theme_includes = explode(',', $modSettings['integrate_theme_include']);
Chris@76 1756 foreach ($theme_includes as $include)
Chris@76 1757 {
Chris@76 1758 $include = strtr(trim($include), array('$boarddir' => $boarddir, '$sourcedir' => $sourcedir, '$themedir' => $settings['theme_dir']));
Chris@76 1759 if (file_exists($include))
Chris@76 1760 require_once($include);
Chris@76 1761 }
Chris@76 1762 }
Chris@76 1763
Chris@76 1764 // Call load theme integration functions.
Chris@76 1765 call_integration_hook('integrate_load_theme');
Chris@76 1766
Chris@76 1767 // We are ready to go.
Chris@76 1768 $context['theme_loaded'] = true;
Chris@76 1769 }
Chris@76 1770
Chris@76 1771 // Load a template - if the theme doesn't include it, use the default.
Chris@76 1772 function loadTemplate($template_name, $style_sheets = array(), $fatal = true)
Chris@76 1773 {
Chris@76 1774 global $context, $settings, $txt, $scripturl, $boarddir, $db_show_debug;
Chris@76 1775
Chris@76 1776 // Do any style sheets first, cause we're easy with those.
Chris@76 1777 if (!empty($style_sheets))
Chris@76 1778 {
Chris@76 1779 if (!is_array($style_sheets))
Chris@76 1780 $style_sheets = array($style_sheets);
Chris@76 1781
Chris@76 1782 foreach ($style_sheets as $sheet)
Chris@76 1783 {
Chris@76 1784 // Prevent the style sheet from being included twice.
Chris@76 1785 if (strpos($context['html_headers'], 'id="' . $sheet . '_css"') !== false)
Chris@76 1786 continue;
Chris@76 1787
Chris@76 1788 $sheet_path = file_exists($settings['theme_dir']. '/css/' . $sheet . '.css') ? 'theme_url' : (file_exists($settings['default_theme_dir']. '/css/' . $sheet . '.css') ? 'default_theme_url' : '');
Chris@76 1789 if ($sheet_path)
Chris@76 1790 {
Chris@76 1791 $context['html_headers'] .= "\n\t" . '<link rel="stylesheet" type="text/css" id="' . $sheet . '_css" href="' . $settings[$sheet_path] . '/css/' . $sheet . '.css" />';
Chris@76 1792 if ($db_show_debug === true)
Chris@76 1793 $context['debug']['sheets'][] = $sheet . ' (' . basename($settings[$sheet_path]) . ')';
Chris@76 1794 }
Chris@76 1795 }
Chris@76 1796 }
Chris@76 1797
Chris@76 1798 // No template to load?
Chris@76 1799 if ($template_name === false)
Chris@76 1800 return true;
Chris@76 1801
Chris@76 1802 $loaded = false;
Chris@76 1803 foreach ($settings['template_dirs'] as $template_dir)
Chris@76 1804 {
Chris@76 1805 if (file_exists($template_dir . '/' . $template_name . '.template.php'))
Chris@76 1806 {
Chris@76 1807 $loaded = true;
Chris@76 1808 template_include($template_dir . '/' . $template_name . '.template.php', true);
Chris@76 1809 break;
Chris@76 1810 }
Chris@76 1811 }
Chris@76 1812
Chris@76 1813 if ($loaded)
Chris@76 1814 {
Chris@76 1815 // For compatibility reasons, if this is the index template without new functions, include compatible stuff.
Chris@76 1816 if (substr($template_name, 0, 5) == 'index' && !function_exists('template_button_strip'))
Chris@76 1817 loadTemplate('Compat');
Chris@76 1818
Chris@76 1819 if ($db_show_debug === true)
Chris@76 1820 $context['debug']['templates'][] = $template_name . ' (' . basename($template_dir) . ')';
Chris@76 1821
Chris@76 1822 // If they have specified an initialization function for this template, go ahead and call it now.
Chris@76 1823 if (function_exists('template_' . $template_name . '_init'))
Chris@76 1824 call_user_func('template_' . $template_name . '_init');
Chris@76 1825 }
Chris@76 1826 // Hmmm... doesn't exist?! I don't suppose the directory is wrong, is it?
Chris@76 1827 elseif (!file_exists($settings['default_theme_dir']) && file_exists($boarddir . '/Themes/default'))
Chris@76 1828 {
Chris@76 1829 $settings['default_theme_dir'] = $boarddir . '/Themes/default';
Chris@76 1830 $settings['template_dirs'][] = $settings['default_theme_dir'];
Chris@76 1831
Chris@76 1832 if (!empty($context['user']['is_admin']) && !isset($_GET['th']))
Chris@76 1833 {
Chris@76 1834 loadLanguage('Errors');
Chris@76 1835 echo '
Chris@76 1836 <div class="alert errorbox">
Chris@76 1837 <a href="', $scripturl . '?action=admin;area=theme;sa=settings;th=1;' . $context['session_var'] . '=' . $context['session_id'], '" class="alert">', $txt['theme_dir_wrong'], '</a>
Chris@76 1838 </div>';
Chris@76 1839 }
Chris@76 1840
Chris@76 1841 loadTemplate($template_name);
Chris@76 1842 }
Chris@76 1843 // Cause an error otherwise.
Chris@76 1844 elseif ($template_name != 'Errors' && $template_name != 'index' && $fatal)
Chris@76 1845 fatal_lang_error('theme_template_error', 'template', array((string) $template_name));
Chris@76 1846 elseif ($fatal)
Chris@76 1847 die(log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load Themes/default/%s.template.php!', (string) $template_name), 'template'));
Chris@76 1848 else
Chris@76 1849 return false;
Chris@76 1850 }
Chris@76 1851
Chris@76 1852 // Load a sub template... fatal is for templates that shouldn't get a 'pretty' error screen.
Chris@76 1853 function loadSubTemplate($sub_template_name, $fatal = false)
Chris@76 1854 {
Chris@76 1855 global $context, $settings, $options, $txt, $db_show_debug;
Chris@76 1856
Chris@76 1857 if ($db_show_debug === true)
Chris@76 1858 $context['debug']['sub_templates'][] = $sub_template_name;
Chris@76 1859
Chris@76 1860 // Figure out what the template function is named.
Chris@76 1861 $theme_function = 'template_' . $sub_template_name;
Chris@76 1862 if (function_exists($theme_function))
Chris@76 1863 $theme_function();
Chris@76 1864 elseif ($fatal === false)
Chris@76 1865 fatal_lang_error('theme_template_error', 'template', array((string) $sub_template_name));
Chris@76 1866 elseif ($fatal !== 'ignore')
Chris@76 1867 die(log_error(sprintf(isset($txt['theme_template_error']) ? $txt['theme_template_error'] : 'Unable to load the %s sub template!', (string) $sub_template_name), 'template'));
Chris@76 1868
Chris@76 1869 // Are we showing debugging for templates? Just make sure not to do it before the doctype...
Chris@76 1870 if (allowedTo('admin_forum') && isset($_REQUEST['debug']) && !in_array($sub_template_name, array('init', 'main_below')) && ob_get_length() > 0 && !isset($_REQUEST['xml']))
Chris@76 1871 {
Chris@76 1872 echo '
Chris@76 1873 <div style="font-size: 8pt; border: 1px dashed red; background: orange; text-align: center; font-weight: bold;">---- ', $sub_template_name, ' ends ----</div>';
Chris@76 1874 }
Chris@76 1875 }
Chris@76 1876
Chris@76 1877 // Load a language file. Tries the current and default themes as well as the user and global languages.
Chris@76 1878 function loadLanguage($template_name, $lang = '', $fatal = true, $force_reload = false)
Chris@76 1879 {
Chris@76 1880 global $user_info, $language, $settings, $context, $modSettings;
Chris@76 1881 global $cachedir, $db_show_debug, $sourcedir, $txt;
Chris@76 1882 static $already_loaded = array();
Chris@76 1883
Chris@76 1884 // Default to the user's language.
Chris@76 1885 if ($lang == '')
Chris@76 1886 $lang = isset($user_info['language']) ? $user_info['language'] : $language;
Chris@76 1887
Chris@76 1888 // Do we want the English version of language file as fallback?
Chris@76 1889 if (empty($modSettings['disable_language_fallback']) && $lang != 'english')
Chris@76 1890 loadLanguage($template_name, 'english', false);
Chris@76 1891
Chris@76 1892 if (!$force_reload && isset($already_loaded[$template_name]) && $already_loaded[$template_name] == $lang)
Chris@76 1893 return $lang;
Chris@76 1894
Chris@76 1895 // Make sure we have $settings - if not we're in trouble and need to find it!
Chris@76 1896 if (empty($settings['default_theme_dir']))
Chris@76 1897 {
Chris@76 1898 require_once($sourcedir . '/ScheduledTasks.php');
Chris@76 1899 loadEssentialThemeData();
Chris@76 1900 }
Chris@76 1901
Chris@76 1902 // What theme are we in?
Chris@76 1903 $theme_name = basename($settings['theme_url']);
Chris@76 1904 if (empty($theme_name))
Chris@76 1905 $theme_name = 'unknown';
Chris@76 1906
Chris@76 1907 // For each file open it up and write it out!
Chris@76 1908 foreach (explode('+', $template_name) as $template)
Chris@76 1909 {
Chris@76 1910 // Obviously, the current theme is most important to check.
Chris@76 1911 $attempts = array(
Chris@76 1912 array($settings['theme_dir'], $template, $lang, $settings['theme_url']),
Chris@76 1913 array($settings['theme_dir'], $template, $language, $settings['theme_url']),
Chris@76 1914 );
Chris@76 1915
Chris@76 1916 // Do we have a base theme to worry about?
Chris@76 1917 if (isset($settings['base_theme_dir']))
Chris@76 1918 {
Chris@76 1919 $attempts[] = array($settings['base_theme_dir'], $template, $lang, $settings['base_theme_url']);
Chris@76 1920 $attempts[] = array($settings['base_theme_dir'], $template, $language, $settings['base_theme_url']);
Chris@76 1921 }
Chris@76 1922
Chris@76 1923 // Fall back on the default theme if necessary.
Chris@76 1924 $attempts[] = array($settings['default_theme_dir'], $template, $lang, $settings['default_theme_url']);
Chris@76 1925 $attempts[] = array($settings['default_theme_dir'], $template, $language, $settings['default_theme_url']);
Chris@76 1926
Chris@76 1927 // Fall back on the English language if none of the preferred languages can be found.
Chris@76 1928 if (!in_array('english', array($lang, $language)))
Chris@76 1929 {
Chris@76 1930 $attempts[] = array($settings['theme_dir'], $template, 'english', $settings['theme_url']);
Chris@76 1931 $attempts[] = array($settings['default_theme_dir'], $template, 'english', $settings['default_theme_url']);
Chris@76 1932 }
Chris@76 1933
Chris@76 1934 // Try to find the language file.
Chris@76 1935 $found = false;
Chris@76 1936 foreach ($attempts as $k => $file)
Chris@76 1937 {
Chris@76 1938 if (file_exists($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php'))
Chris@76 1939 {
Chris@76 1940 // Include it!
Chris@76 1941 template_include($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php');
Chris@76 1942
Chris@76 1943 // Note that we found it.
Chris@76 1944 $found = true;
Chris@76 1945
Chris@76 1946 break;
Chris@76 1947 }
Chris@76 1948 }
Chris@76 1949
Chris@76 1950 // That couldn't be found! Log the error, but *try* to continue normally.
Chris@76 1951 if (!$found && $fatal)
Chris@76 1952 {
Chris@76 1953 log_error(sprintf($txt['theme_language_error'], $template_name . '.' . $lang, 'template'));
Chris@76 1954 break;
Chris@76 1955 }
Chris@76 1956 }
Chris@76 1957
Chris@76 1958 // Keep track of what we're up to soldier.
Chris@76 1959 if ($db_show_debug === true)
Chris@76 1960 $context['debug']['language_files'][] = $template_name . '.' . $lang . ' (' . $theme_name . ')';
Chris@76 1961
Chris@76 1962 // Remember what we have loaded, and in which language.
Chris@76 1963 $already_loaded[$template_name] = $lang;
Chris@76 1964
Chris@76 1965 // Return the language actually loaded.
Chris@76 1966 return $lang;
Chris@76 1967 }
Chris@76 1968
Chris@76 1969 // Get all parent boards (requires first parent as parameter)
Chris@76 1970 function getBoardParents($id_parent)
Chris@76 1971 {
Chris@76 1972 global $scripturl, $smcFunc;
Chris@76 1973
Chris@76 1974 // First check if we have this cached already.
Chris@76 1975 if (($boards = cache_get_data('board_parents-' . $id_parent, 480)) === null)
Chris@76 1976 {
Chris@76 1977 $boards = array();
Chris@76 1978 $original_parent = $id_parent;
Chris@76 1979
Chris@76 1980 // Loop while the parent is non-zero.
Chris@76 1981 while ($id_parent != 0)
Chris@76 1982 {
Chris@76 1983 $result = $smcFunc['db_query']('', '
Chris@76 1984 SELECT
Chris@76 1985 b.id_parent, b.name, {int:board_parent} AS id_board, IFNULL(mem.id_member, 0) AS id_moderator,
Chris@76 1986 mem.real_name, b.child_level
Chris@76 1987 FROM {db_prefix}boards AS b
Chris@76 1988 LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board)
Chris@76 1989 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
Chris@76 1990 WHERE b.id_board = {int:board_parent}',
Chris@76 1991 array(
Chris@76 1992 'board_parent' => $id_parent,
Chris@76 1993 )
Chris@76 1994 );
Chris@76 1995 // In the EXTREMELY unlikely event this happens, give an error message.
Chris@76 1996 if ($smcFunc['db_num_rows']($result) == 0)
Chris@76 1997 fatal_lang_error('parent_not_found', 'critical');
Chris@76 1998 while ($row = $smcFunc['db_fetch_assoc']($result))
Chris@76 1999 {
Chris@76 2000 if (!isset($boards[$row['id_board']]))
Chris@76 2001 {
Chris@76 2002 $id_parent = $row['id_parent'];
Chris@76 2003 $boards[$row['id_board']] = array(
Chris@76 2004 'url' => $scripturl . '?board=' . $row['id_board'] . '.0',
Chris@76 2005 'name' => $row['name'],
Chris@76 2006 'level' => $row['child_level'],
Chris@76 2007 'moderators' => array()
Chris@76 2008 );
Chris@76 2009 }
Chris@76 2010 // If a moderator exists for this board, add that moderator for all children too.
Chris@76 2011 if (!empty($row['id_moderator']))
Chris@76 2012 foreach ($boards as $id => $dummy)
Chris@76 2013 {
Chris@76 2014 $boards[$id]['moderators'][$row['id_moderator']] = array(
Chris@76 2015 'id' => $row['id_moderator'],
Chris@76 2016 'name' => $row['real_name'],
Chris@76 2017 'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'],
Chris@76 2018 'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>'
Chris@76 2019 );
Chris@76 2020 }
Chris@76 2021 }
Chris@76 2022 $smcFunc['db_free_result']($result);
Chris@76 2023 }
Chris@76 2024
Chris@76 2025 cache_put_data('board_parents-' . $original_parent, $boards, 480);
Chris@76 2026 }
Chris@76 2027
Chris@76 2028 return $boards;
Chris@76 2029 }
Chris@76 2030
Chris@76 2031 // Attempt to reload our languages.
Chris@76 2032 function getLanguages($use_cache = true, $favor_utf8 = true)
Chris@76 2033 {
Chris@76 2034 global $context, $smcFunc, $settings, $modSettings;
Chris@76 2035
Chris@76 2036 // Either we don't use the cache, or its expired.
Chris@76 2037 if (!$use_cache || ($context['languages'] = cache_get_data('known_languages' . ($favor_utf8 ? '' : '_all'), !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600)) == null)
Chris@76 2038 {
Chris@76 2039 // If we don't have our theme information yet, lets get it.
Chris@76 2040 if (empty($settings['default_theme_dir']))
Chris@76 2041 loadTheme(0, false);
Chris@76 2042
Chris@76 2043 // Default language directories to try.
Chris@76 2044 $language_directories = array(
Chris@76 2045 $settings['default_theme_dir'] . '/languages',
Chris@76 2046 $settings['actual_theme_dir'] . '/languages',
Chris@76 2047 );
Chris@76 2048
Chris@76 2049 // We possibly have a base theme directory.
Chris@76 2050 if (!empty($settings['base_theme_dir']))
Chris@76 2051 $language_directories[] = $settings['base_theme_dir'] . '/languages';
Chris@76 2052
Chris@76 2053 // Remove any duplicates.
Chris@76 2054 $language_directories = array_unique($language_directories);
Chris@76 2055
Chris@76 2056 foreach ($language_directories as $language_dir)
Chris@76 2057 {
Chris@76 2058 // Can't look in here... doesn't exist!
Chris@76 2059 if (!file_exists($language_dir))
Chris@76 2060 continue;
Chris@76 2061
Chris@76 2062 $dir = dir($language_dir);
Chris@76 2063 while ($entry = $dir->read())
Chris@76 2064 {
Chris@76 2065 // Look for the index language file....
Chris@76 2066 if (!preg_match('~^index\.(.+)\.php$~', $entry, $matches))
Chris@76 2067 continue;
Chris@76 2068
Chris@76 2069 $context['languages'][$matches[1]] = array(
Chris@76 2070 'name' => $smcFunc['ucwords'](strtr($matches[1], array('_' => ' '))),
Chris@76 2071 'selected' => false,
Chris@76 2072 'filename' => $matches[1],
Chris@76 2073 'location' => $language_dir . '/index.' . $matches[1] . '.php',
Chris@76 2074 );
Chris@76 2075
Chris@76 2076 }
Chris@76 2077 $dir->close();
Chris@76 2078 }
Chris@76 2079
Chris@76 2080 // Favoring UTF8? Then prevent us from selecting non-UTF8 versions.
Chris@76 2081 if ($favor_utf8)
Chris@76 2082 {
Chris@76 2083 foreach ($context['languages'] as $lang)
Chris@76 2084 if (substr($lang['filename'], strlen($lang['filename']) - 5, 5) != '-utf8' && isset($context['languages'][$lang['filename'] . '-utf8']))
Chris@76 2085 unset($context['languages'][$lang['filename']]);
Chris@76 2086 }
Chris@76 2087
Chris@76 2088 // Lets cash in on this deal.
Chris@76 2089 if (!empty($modSettings['cache_enable']))
Chris@76 2090 cache_put_data('known_languages' . ($favor_utf8 ? '' : '_all'), $context['languages'], !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
Chris@76 2091 }
Chris@76 2092
Chris@76 2093 return $context['languages'];
Chris@76 2094 }
Chris@76 2095
Chris@76 2096 // Replace all vulgar words with respective proper words. (substring or whole words..)
Chris@76 2097 function &censorText(&$text, $force = false)
Chris@76 2098 {
Chris@76 2099 global $modSettings, $options, $settings, $txt;
Chris@76 2100 static $censor_vulgar = null, $censor_proper;
Chris@76 2101
Chris@76 2102 if ((!empty($options['show_no_censored']) && $settings['allow_no_censored'] && !$force) || empty($modSettings['censor_vulgar']))
Chris@76 2103 return $text;
Chris@76 2104
Chris@76 2105 // If they haven't yet been loaded, load them.
Chris@76 2106 if ($censor_vulgar == null)
Chris@76 2107 {
Chris@76 2108 $censor_vulgar = explode("\n", $modSettings['censor_vulgar']);
Chris@76 2109 $censor_proper = explode("\n", $modSettings['censor_proper']);
Chris@76 2110
Chris@76 2111 // Quote them for use in regular expressions.
Chris@76 2112 for ($i = 0, $n = count($censor_vulgar); $i < $n; $i++)
Chris@76 2113 {
Chris@76 2114 $censor_vulgar[$i] = strtr(preg_quote($censor_vulgar[$i], '/'), array('\\\\\\*' => '[*]', '\\*' => '[^\s]*?', '&' => '&amp;'));
Chris@76 2115 $censor_vulgar[$i] = (empty($modSettings['censorWholeWord']) ? '/' . $censor_vulgar[$i] . '/' : '/(?<=^|\W)' . $censor_vulgar[$i] . '(?=$|\W)/') . (empty($modSettings['censorIgnoreCase']) ? '' : 'i') . ((empty($modSettings['global_character_set']) ? $txt['lang_character_set'] : $modSettings['global_character_set']) === 'UTF-8' ? 'u' : '');
Chris@76 2116
Chris@76 2117 if (strpos($censor_vulgar[$i], '\'') !== false)
Chris@76 2118 {
Chris@76 2119 $censor_proper[count($censor_vulgar)] = $censor_proper[$i];
Chris@76 2120 $censor_vulgar[count($censor_vulgar)] = strtr($censor_vulgar[$i], array('\'' => '&#039;'));
Chris@76 2121 }
Chris@76 2122 }
Chris@76 2123 }
Chris@76 2124
Chris@76 2125 // Censoring isn't so very complicated :P.
Chris@76 2126 $text = preg_replace($censor_vulgar, $censor_proper, $text);
Chris@76 2127 return $text;
Chris@76 2128 }
Chris@76 2129
Chris@76 2130 // Load the template/language file using eval or require? (with eval we can show an error message!)
Chris@76 2131 function template_include($filename, $once = false)
Chris@76 2132 {
Chris@76 2133 global $context, $settings, $options, $txt, $scripturl, $modSettings;
Chris@76 2134 global $user_info, $boardurl, $boarddir, $sourcedir;
Chris@76 2135 global $maintenance, $mtitle, $mmessage;
Chris@76 2136 static $templates = array();
Chris@76 2137
Chris@76 2138 // We want to be able to figure out any errors...
Chris@76 2139 @ini_set('track_errors', '1');
Chris@76 2140
Chris@76 2141 // Don't include the file more than once, if $once is true.
Chris@76 2142 if ($once && in_array($filename, $templates))
Chris@76 2143 return;
Chris@76 2144 // Add this file to the include list, whether $once is true or not.
Chris@76 2145 else
Chris@76 2146 $templates[] = $filename;
Chris@76 2147
Chris@76 2148 // Are we going to use eval?
Chris@76 2149 if (empty($modSettings['disableTemplateEval']))
Chris@76 2150 {
Chris@76 2151 $file_found = file_exists($filename) && eval('?' . '>' . rtrim(file_get_contents($filename))) !== false;
Chris@76 2152 $settings['current_include_filename'] = $filename;
Chris@76 2153 }
Chris@76 2154 else
Chris@76 2155 {
Chris@76 2156 $file_found = file_exists($filename);
Chris@76 2157
Chris@76 2158 if ($once && $file_found)
Chris@76 2159 require_once($filename);
Chris@76 2160 elseif ($file_found)
Chris@76 2161 require($filename);
Chris@76 2162 }
Chris@76 2163
Chris@76 2164 if ($file_found !== true)
Chris@76 2165 {
Chris@76 2166 ob_end_clean();
Chris@76 2167 if (!empty($modSettings['enableCompressedOutput']))
Chris@76 2168 @ob_start('ob_gzhandler');
Chris@76 2169 else
Chris@76 2170 ob_start();
Chris@76 2171
Chris@76 2172 if (isset($_GET['debug']) && !WIRELESS)
Chris@76 2173 header('Content-Type: application/xhtml+xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
Chris@76 2174
Chris@76 2175 // Don't cache error pages!!
Chris@76 2176 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
Chris@76 2177 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
Chris@76 2178 header('Cache-Control: no-cache');
Chris@76 2179
Chris@76 2180 if (!isset($txt['template_parse_error']))
Chris@76 2181 {
Chris@76 2182 $txt['template_parse_error'] = 'Template Parse Error!';
Chris@76 2183 $txt['template_parse_error_message'] = 'It seems something has gone sour on the forum with the template system. This problem should only be temporary, so please come back later and try again. If you continue to see this message, please contact the administrator.<br /><br />You can also try <a href="javascript:location.reload();">refreshing this page</a>.';
Chris@76 2184 $txt['template_parse_error_details'] = 'There was a problem loading the <tt><strong>%1$s</strong></tt> template or language file. Please check the syntax and try again - remember, single quotes (<tt>\'</tt>) often have to be escaped with a slash (<tt>\\</tt>). To see more specific error information from PHP, try <a href="' . $boardurl . '%1$s" class="extern">accessing the file directly</a>.<br /><br />You may want to try to <a href="javascript:location.reload();">refresh this page</a> or <a href="' . $scripturl . '?theme=1">use the default theme</a>.';
Chris@76 2185 }
Chris@76 2186
Chris@76 2187 // First, let's get the doctype and language information out of the way.
Chris@76 2188 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Chris@76 2189 <html xmlns="http://www.w3.org/1999/xhtml"', !empty($context['right_to_left']) ? ' dir="rtl"' : '', '>
Chris@76 2190 <head>';
Chris@76 2191 if (isset($context['character_set']))
Chris@76 2192 echo '
Chris@76 2193 <meta http-equiv="Content-Type" content="text/html; charset=', $context['character_set'], '" />';
Chris@76 2194
Chris@76 2195 if (!empty($maintenance) && !allowedTo('admin_forum'))
Chris@76 2196 echo '
Chris@76 2197 <title>', $mtitle, '</title>
Chris@76 2198 </head>
Chris@76 2199 <body>
Chris@76 2200 <h3>', $mtitle, '</h3>
Chris@76 2201 ', $mmessage, '
Chris@76 2202 </body>
Chris@76 2203 </html>';
Chris@76 2204 elseif (!allowedTo('admin_forum'))
Chris@76 2205 echo '
Chris@76 2206 <title>', $txt['template_parse_error'], '</title>
Chris@76 2207 </head>
Chris@76 2208 <body>
Chris@76 2209 <h3>', $txt['template_parse_error'], '</h3>
Chris@76 2210 ', $txt['template_parse_error_message'], '
Chris@76 2211 </body>
Chris@76 2212 </html>';
Chris@76 2213 else
Chris@76 2214 {
Chris@76 2215 require_once($sourcedir . '/Subs-Package.php');
Chris@76 2216
Chris@76 2217 $error = fetch_web_data($boardurl . strtr($filename, array($boarddir => '', strtr($boarddir, '\\', '/') => '')));
Chris@76 2218 if (empty($error))
Chris@76 2219 $error = $php_errormsg;
Chris@76 2220
Chris@76 2221 $error = strtr($error, array('<b>' => '<strong>', '</b>' => '</strong>'));
Chris@76 2222
Chris@76 2223 echo '
Chris@76 2224 <title>', $txt['template_parse_error'], '</title>
Chris@76 2225 </head>
Chris@76 2226 <body>
Chris@76 2227 <h3>', $txt['template_parse_error'], '</h3>
Chris@76 2228 ', sprintf($txt['template_parse_error_details'], strtr($filename, array($boarddir => '', strtr($boarddir, '\\', '/') => '')));
Chris@76 2229
Chris@76 2230 if (!empty($error))
Chris@76 2231 echo '
Chris@76 2232 <hr />
Chris@76 2233
Chris@76 2234 <div style="margin: 0 20px;"><tt>', strtr(strtr($error, array('<strong>' . $boarddir => '<strong>...', '<strong>' . strtr($boarddir, '\\', '/') => '<strong>...')), '\\', '/'), '</tt></div>';
Chris@76 2235
Chris@76 2236 // I know, I know... this is VERY COMPLICATED. Still, it's good.
Chris@76 2237 if (preg_match('~ <strong>(\d+)</strong><br( /)?' . '>$~i', $error, $match) != 0)
Chris@76 2238 {
Chris@76 2239 $data = file($filename);
Chris@76 2240 $data2 = highlight_php_code(implode('', $data));
Chris@76 2241 $data2 = preg_split('~\<br( /)?\>~', $data2);
Chris@76 2242
Chris@76 2243 // Fix the PHP code stuff...
Chris@76 2244 if ($context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'])
Chris@76 2245 $data2 = str_replace("\t", '<pre style="display: inline;">' . "\t" . '</pre>', $data2);
Chris@76 2246 elseif (!$context['browser']['is_gecko'])
Chris@76 2247 $data2 = str_replace("\t", '<span style="white-space: pre;">' . "\t" . '</span>', $data2);
Chris@76 2248 else
Chris@76 2249 $data2 = str_replace('<pre style="display: inline;">' . "\t" . '</pre>', "\t", $data2);
Chris@76 2250
Chris@76 2251 // Now we get to work around a bug in PHP where it doesn't escape <br />s!
Chris@76 2252 $j = -1;
Chris@76 2253 foreach ($data as $line)
Chris@76 2254 {
Chris@76 2255 $j++;
Chris@76 2256
Chris@76 2257 if (substr_count($line, '<br />') == 0)
Chris@76 2258 continue;
Chris@76 2259
Chris@76 2260 $n = substr_count($line, '<br />');
Chris@76 2261 for ($i = 0; $i < $n; $i++)
Chris@76 2262 {
Chris@76 2263 $data2[$j] .= '&lt;br /&gt;' . $data2[$j + $i + 1];
Chris@76 2264 unset($data2[$j + $i + 1]);
Chris@76 2265 }
Chris@76 2266 $j += $n;
Chris@76 2267 }
Chris@76 2268 $data2 = array_values($data2);
Chris@76 2269 array_unshift($data2, '');
Chris@76 2270
Chris@76 2271 echo '
Chris@76 2272 <div style="margin: 2ex 20px; width: 96%; overflow: auto;"><pre style="margin: 0;">';
Chris@76 2273
Chris@76 2274 // Figure out what the color coding was before...
Chris@76 2275 $line = max($match[1] - 9, 1);
Chris@76 2276 $last_line = '';
Chris@76 2277 for ($line2 = $line - 1; $line2 > 1; $line2--)
Chris@76 2278 if (strpos($data2[$line2], '<') !== false)
Chris@76 2279 {
Chris@76 2280 if (preg_match('~(<[^/>]+>)[^<]*$~', $data2[$line2], $color_match) != 0)
Chris@76 2281 $last_line = $color_match[1];
Chris@76 2282 break;
Chris@76 2283 }
Chris@76 2284
Chris@76 2285 // Show the relevant lines...
Chris@76 2286 for ($n = min($match[1] + 4, count($data2) + 1); $line <= $n; $line++)
Chris@76 2287 {
Chris@76 2288 if ($line == $match[1])
Chris@76 2289 echo '</pre><div style="background-color: #ffb0b5;"><pre style="margin: 0;">';
Chris@76 2290
Chris@76 2291 echo '<span style="color: black;">', sprintf('%' . strlen($n) . 's', $line), ':</span> ';
Chris@76 2292 if (isset($data2[$line]) && $data2[$line] != '')
Chris@76 2293 echo substr($data2[$line], 0, 2) == '</' ? preg_replace('~^</[^>]+>~', '', $data2[$line]) : $last_line . $data2[$line];
Chris@76 2294
Chris@76 2295 if (isset($data2[$line]) && preg_match('~(<[^/>]+>)[^<]*$~', $data2[$line], $color_match) != 0)
Chris@76 2296 {
Chris@76 2297 $last_line = $color_match[1];
Chris@76 2298 echo '</', substr($last_line, 1, 4), '>';
Chris@76 2299 }
Chris@76 2300 elseif ($last_line != '' && strpos($data2[$line], '<') !== false)
Chris@76 2301 $last_line = '';
Chris@76 2302 elseif ($last_line != '' && $data2[$line] != '')
Chris@76 2303 echo '</', substr($last_line, 1, 4), '>';
Chris@76 2304
Chris@76 2305 if ($line == $match[1])
Chris@76 2306 echo '</pre></div><pre style="margin: 0;">';
Chris@76 2307 else
Chris@76 2308 echo "\n";
Chris@76 2309 }
Chris@76 2310
Chris@76 2311 echo '</pre></div>';
Chris@76 2312 }
Chris@76 2313
Chris@76 2314 echo '
Chris@76 2315 </body>
Chris@76 2316 </html>';
Chris@76 2317 }
Chris@76 2318
Chris@76 2319 die;
Chris@76 2320 }
Chris@76 2321 }
Chris@76 2322
Chris@76 2323 // Attempt to start the session, unless it already has been.
Chris@76 2324 function loadSession()
Chris@76 2325 {
Chris@76 2326 global $HTTP_SESSION_VARS, $modSettings, $boardurl, $sc;
Chris@76 2327
Chris@76 2328 // Attempt to change a few PHP settings.
Chris@76 2329 @ini_set('session.use_cookies', true);
Chris@76 2330 @ini_set('session.use_only_cookies', false);
Chris@76 2331 @ini_set('url_rewriter.tags', '');
Chris@76 2332 @ini_set('session.use_trans_sid', false);
Chris@76 2333 @ini_set('arg_separator.output', '&amp;');
Chris@76 2334
Chris@76 2335 if (!empty($modSettings['globalCookies']))
Chris@76 2336 {
Chris@76 2337 $parsed_url = parse_url($boardurl);
Chris@76 2338
Chris@76 2339 if (preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0 && preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1)
Chris@76 2340 @ini_set('session.cookie_domain', '.' . $parts[1]);
Chris@76 2341 }
Chris@76 2342 // !!! Set the session cookie path?
Chris@76 2343
Chris@76 2344 // If it's already been started... probably best to skip this.
Chris@76 2345 if ((@ini_get('session.auto_start') == 1 && !empty($modSettings['databaseSession_enable'])) || session_id() == '')
Chris@76 2346 {
Chris@76 2347 // Attempt to end the already-started session.
Chris@76 2348 if (@ini_get('session.auto_start') == 1)
Chris@76 2349 @session_write_close();
Chris@76 2350
Chris@76 2351 // This is here to stop people from using bad junky PHPSESSIDs.
Chris@76 2352 if (isset($_REQUEST[session_name()]) && preg_match('~^[A-Za-z0-9,-]{16,32}$~', $_REQUEST[session_name()]) == 0 && !isset($_COOKIE[session_name()]))
Chris@76 2353 {
Chris@76 2354 $session_id = md5(md5('smf_sess_' . time()) . mt_rand());
Chris@76 2355 $_REQUEST[session_name()] = $session_id;
Chris@76 2356 $_GET[session_name()] = $session_id;
Chris@76 2357 $_POST[session_name()] = $session_id;
Chris@76 2358 }
Chris@76 2359
Chris@76 2360 // Use database sessions? (they don't work in 4.1.x!)
Chris@76 2361 if (!empty($modSettings['databaseSession_enable']) && @version_compare(PHP_VERSION, '4.2.0') != -1)
Chris@76 2362 {
Chris@76 2363 session_set_save_handler('sessionOpen', 'sessionClose', 'sessionRead', 'sessionWrite', 'sessionDestroy', 'sessionGC');
Chris@76 2364 @ini_set('session.gc_probability', '1');
Chris@76 2365 }
Chris@76 2366 elseif (@ini_get('session.gc_maxlifetime') <= 1440 && !empty($modSettings['databaseSession_lifetime']))
Chris@76 2367 @ini_set('session.gc_maxlifetime', max($modSettings['databaseSession_lifetime'], 60));
Chris@76 2368
Chris@76 2369 // Use cache setting sessions?
Chris@76 2370 if (empty($modSettings['databaseSession_enable']) && !empty($modSettings['cache_enable']) && php_sapi_name() != 'cli')
Chris@76 2371 {
Chris@76 2372 if (function_exists('mmcache_set_session_handlers'))
Chris@76 2373 mmcache_set_session_handlers();
Chris@76 2374 elseif (function_exists('eaccelerator_set_session_handlers'))
Chris@76 2375 eaccelerator_set_session_handlers();
Chris@76 2376 }
Chris@76 2377
Chris@76 2378 session_start();
Chris@76 2379
Chris@76 2380 // Change it so the cache settings are a little looser than default.
Chris@76 2381 if (!empty($modSettings['databaseSession_loose']))
Chris@76 2382 header('Cache-Control: private');
Chris@76 2383 }
Chris@76 2384
Chris@76 2385 // While PHP 4.1.x should use $_SESSION, it seems to need this to do it right.
Chris@76 2386 if (@version_compare(PHP_VERSION, '4.2.0') == -1)
Chris@76 2387 $HTTP_SESSION_VARS['php_412_bugfix'] = true;
Chris@76 2388
Chris@76 2389 // Set the randomly generated code.
Chris@76 2390 if (!isset($_SESSION['session_var']))
Chris@76 2391 {
Chris@76 2392 $_SESSION['session_value'] = md5(session_id() . mt_rand());
Chris@76 2393 $_SESSION['session_var'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, rand(7, 12));
Chris@76 2394 }
Chris@76 2395 $sc = $_SESSION['session_value'];
Chris@76 2396 }
Chris@76 2397
Chris@76 2398 function sessionOpen($save_path, $session_name)
Chris@76 2399 {
Chris@76 2400 return true;
Chris@76 2401 }
Chris@76 2402
Chris@76 2403 function sessionClose()
Chris@76 2404 {
Chris@76 2405 return true;
Chris@76 2406 }
Chris@76 2407
Chris@76 2408 function sessionRead($session_id)
Chris@76 2409 {
Chris@76 2410 global $smcFunc;
Chris@76 2411
Chris@76 2412 if (preg_match('~^[A-Za-z0-9,-]{16,32}$~', $session_id) == 0)
Chris@76 2413 return false;
Chris@76 2414
Chris@76 2415 // Look for it in the database.
Chris@76 2416 $result = $smcFunc['db_query']('', '
Chris@76 2417 SELECT data
Chris@76 2418 FROM {db_prefix}sessions
Chris@76 2419 WHERE session_id = {string:session_id}
Chris@76 2420 LIMIT 1',
Chris@76 2421 array(
Chris@76 2422 'session_id' => $session_id,
Chris@76 2423 )
Chris@76 2424 );
Chris@76 2425 list ($sess_data) = $smcFunc['db_fetch_row']($result);
Chris@76 2426 $smcFunc['db_free_result']($result);
Chris@76 2427
Chris@76 2428 return $sess_data;
Chris@76 2429 }
Chris@76 2430
Chris@76 2431 function sessionWrite($session_id, $data)
Chris@76 2432 {
Chris@76 2433 global $smcFunc;
Chris@76 2434
Chris@76 2435 if (preg_match('~^[A-Za-z0-9,-]{16,32}$~', $session_id) == 0)
Chris@76 2436 return false;
Chris@76 2437
Chris@76 2438 // First try to update an existing row...
Chris@76 2439 $result = $smcFunc['db_query']('', '
Chris@76 2440 UPDATE {db_prefix}sessions
Chris@76 2441 SET data = {string:data}, last_update = {int:last_update}
Chris@76 2442 WHERE session_id = {string:session_id}',
Chris@76 2443 array(
Chris@76 2444 'last_update' => time(),
Chris@76 2445 'data' => $data,
Chris@76 2446 'session_id' => $session_id,
Chris@76 2447 )
Chris@76 2448 );
Chris@76 2449
Chris@76 2450 // If that didn't work, try inserting a new one.
Chris@76 2451 if ($smcFunc['db_affected_rows']() == 0)
Chris@76 2452 $result = $smcFunc['db_insert']('ignore',
Chris@76 2453 '{db_prefix}sessions',
Chris@76 2454 array('session_id' => 'string', 'data' => 'string', 'last_update' => 'int'),
Chris@76 2455 array($session_id, $data, time()),
Chris@76 2456 array('session_id')
Chris@76 2457 );
Chris@76 2458
Chris@76 2459 return $result;
Chris@76 2460 }
Chris@76 2461
Chris@76 2462 function sessionDestroy($session_id)
Chris@76 2463 {
Chris@76 2464 global $smcFunc;
Chris@76 2465
Chris@76 2466 if (preg_match('~^[A-Za-z0-9,-]{16,32}$~', $session_id) == 0)
Chris@76 2467 return false;
Chris@76 2468
Chris@76 2469 // Just delete the row...
Chris@76 2470 return $smcFunc['db_query']('', '
Chris@76 2471 DELETE FROM {db_prefix}sessions
Chris@76 2472 WHERE session_id = {string:session_id}',
Chris@76 2473 array(
Chris@76 2474 'session_id' => $session_id,
Chris@76 2475 )
Chris@76 2476 );
Chris@76 2477 }
Chris@76 2478
Chris@76 2479 function sessionGC($max_lifetime)
Chris@76 2480 {
Chris@76 2481 global $modSettings, $smcFunc;
Chris@76 2482
Chris@76 2483 // Just set to the default or lower? Ignore it for a higher value. (hopefully)
Chris@76 2484 if (!empty($modSettings['databaseSession_lifetime']) && ($max_lifetime <= 1440 || $modSettings['databaseSession_lifetime'] > $max_lifetime))
Chris@76 2485 $max_lifetime = max($modSettings['databaseSession_lifetime'], 60);
Chris@76 2486
Chris@76 2487 // Clean up ;).
Chris@76 2488 return $smcFunc['db_query']('', '
Chris@76 2489 DELETE FROM {db_prefix}sessions
Chris@76 2490 WHERE last_update < {int:last_update}',
Chris@76 2491 array(
Chris@76 2492 'last_update' => time() - $max_lifetime,
Chris@76 2493 )
Chris@76 2494 );
Chris@76 2495 }
Chris@76 2496
Chris@76 2497 // Load up a database connection.
Chris@76 2498 function loadDatabase()
Chris@76 2499 {
Chris@76 2500 global $db_persist, $db_connection, $db_server, $db_user, $db_passwd;
Chris@76 2501 global $db_type, $db_name, $ssi_db_user, $ssi_db_passwd, $sourcedir, $db_prefix;
Chris@76 2502
Chris@76 2503 // Figure out what type of database we are using.
Chris@76 2504 if (empty($db_type) || !file_exists($sourcedir . '/Subs-Db-' . $db_type . '.php'))
Chris@76 2505 $db_type = 'mysql';
Chris@76 2506
Chris@76 2507 // Load the file for the database.
Chris@76 2508 require_once($sourcedir . '/Subs-Db-' . $db_type . '.php');
Chris@76 2509
Chris@76 2510 // If we are in SSI try them first, but don't worry if it doesn't work, we have the normal username and password we can use.
Chris@76 2511 if (SMF == 'SSI' && !empty($ssi_db_user) && !empty($ssi_db_passwd))
Chris@76 2512 $db_connection = smf_db_initiate($db_server, $db_name, $ssi_db_user, $ssi_db_passwd, $db_prefix, array('persist' => $db_persist, 'non_fatal' => true, 'dont_select_db' => true));
Chris@76 2513
Chris@76 2514 // Either we aren't in SSI mode, or it failed.
Chris@76 2515 if (empty($db_connection))
Chris@76 2516 $db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist, 'dont_select_db' => SMF == 'SSI'));
Chris@76 2517
Chris@76 2518 // Safe guard here, if there isn't a valid connection lets put a stop to it.
Chris@76 2519 if (!$db_connection)
Chris@76 2520 db_fatal_error();
Chris@76 2521
Chris@76 2522 // If in SSI mode fix up the prefix.
Chris@76 2523 if (SMF == 'SSI')
Chris@76 2524 db_fix_prefix($db_prefix, $db_name);
Chris@76 2525 }
Chris@76 2526
Chris@76 2527 // Try to retrieve a cache entry. On failure, call the appropriate function.
Chris@76 2528 function cache_quick_get($key, $file, $function, $params, $level = 1)
Chris@76 2529 {
Chris@76 2530 global $modSettings, $sourcedir;
Chris@76 2531
Chris@76 2532 // Refresh the cache if either:
Chris@76 2533 // 1. Caching is disabled.
Chris@76 2534 // 2. The cache level isn't high enough.
Chris@76 2535 // 3. The item has not been cached or the cached item expired.
Chris@76 2536 // 4. The cached item has a custom expiration condition evaluating to true.
Chris@76 2537 // 5. The expire time set in the cache item has passed (needed for Zend).
Chris@76 2538 if (empty($modSettings['cache_enable']) || $modSettings['cache_enable'] < $level || !is_array($cache_block = cache_get_data($key, 3600)) || (!empty($cache_block['refresh_eval']) && eval($cache_block['refresh_eval'])) || (!empty($cache_block['expires']) && $cache_block['expires'] < time()))
Chris@76 2539 {
Chris@76 2540 require_once($sourcedir . '/' . $file);
Chris@76 2541 $cache_block = call_user_func_array($function, $params);
Chris@76 2542
Chris@76 2543 if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= $level)
Chris@76 2544 cache_put_data($key, $cache_block, $cache_block['expires'] - time());
Chris@76 2545 }
Chris@76 2546
Chris@76 2547 // Some cached data may need a freshening up after retrieval.
Chris@76 2548 if (!empty($cache_block['post_retri_eval']))
Chris@76 2549 eval($cache_block['post_retri_eval']);
Chris@76 2550
Chris@76 2551 return $cache_block['data'];
Chris@76 2552 }
Chris@76 2553
Chris@76 2554 function cache_put_data($key, $value, $ttl = 120)
Chris@76 2555 {
Chris@76 2556 global $boardurl, $sourcedir, $modSettings, $memcached;
Chris@76 2557 global $cache_hits, $cache_count, $db_show_debug, $cachedir;
Chris@76 2558
Chris@76 2559 if (empty($modSettings['cache_enable']) && !empty($modSettings))
Chris@76 2560 return;
Chris@76 2561
Chris@76 2562 $cache_count = isset($cache_count) ? $cache_count + 1 : 1;
Chris@76 2563 if (isset($db_show_debug) && $db_show_debug === true)
Chris@76 2564 {
Chris@76 2565 $cache_hits[$cache_count] = array('k' => $key, 'd' => 'put', 's' => $value === null ? 0 : strlen(serialize($value)));
Chris@76 2566 $st = microtime();
Chris@76 2567 }
Chris@76 2568
Chris@76 2569 $key = md5($boardurl . filemtime($sourcedir . '/Load.php')) . '-SMF-' . strtr($key, ':', '-');
Chris@76 2570 $value = $value === null ? null : serialize($value);
Chris@76 2571
Chris@76 2572 // The simple yet efficient memcached.
Chris@76 2573 if (function_exists('memcache_set') && isset($modSettings['cache_memcached']) && trim($modSettings['cache_memcached']) != '')
Chris@76 2574 {
Chris@76 2575 // Not connected yet?
Chris@76 2576 if (empty($memcached))
Chris@76 2577 get_memcached_server();
Chris@76 2578 if (!$memcached)
Chris@76 2579 return;
Chris@76 2580
Chris@76 2581 memcache_set($memcached, $key, $value, 0, $ttl);
Chris@76 2582 }
Chris@76 2583 // eAccelerator...
Chris@76 2584 elseif (function_exists('eaccelerator_put'))
Chris@76 2585 {
Chris@76 2586 if (mt_rand(0, 10) == 1)
Chris@76 2587 eaccelerator_gc();
Chris@76 2588
Chris@76 2589 if ($value === null)
Chris@76 2590 @eaccelerator_rm($key);
Chris@76 2591 else
Chris@76 2592 eaccelerator_put($key, $value, $ttl);
Chris@76 2593 }
Chris@76 2594 // Turck MMCache?
Chris@76 2595 elseif (function_exists('mmcache_put'))
Chris@76 2596 {
Chris@76 2597 if (mt_rand(0, 10) == 1)
Chris@76 2598 mmcache_gc();
Chris@76 2599
Chris@76 2600 if ($value === null)
Chris@76 2601 @mmcache_rm($key);
Chris@76 2602 else
Chris@76 2603 mmcache_put($key, $value, $ttl);
Chris@76 2604 }
Chris@76 2605 // Alternative PHP Cache, ahoy!
Chris@76 2606 elseif (function_exists('apc_store'))
Chris@76 2607 {
Chris@76 2608 // An extended key is needed to counteract a bug in APC.
Chris@76 2609 if ($value === null)
Chris@76 2610 apc_delete($key . 'smf');
Chris@76 2611 else
Chris@76 2612 apc_store($key . 'smf', $value, $ttl);
Chris@76 2613 }
Chris@76 2614 // Zend Platform/ZPS/etc.
Chris@76 2615 elseif (function_exists('output_cache_put'))
Chris@76 2616 output_cache_put($key, $value);
Chris@76 2617 elseif (function_exists('xcache_set') && ini_get('xcache.var_size') > 0)
Chris@76 2618 {
Chris@76 2619 if ($value === null)
Chris@76 2620 xcache_unset($key);
Chris@76 2621 else
Chris@76 2622 xcache_set($key, $value, $ttl);
Chris@76 2623 }
Chris@76 2624 // Otherwise custom cache?
Chris@76 2625 else
Chris@76 2626 {
Chris@76 2627 if ($value === null)
Chris@76 2628 @unlink($cachedir . '/data_' . $key . '.php');
Chris@76 2629 else
Chris@76 2630 {
Chris@76 2631 $cache_data = '<' . '?' . 'php if (!defined(\'SMF\')) die; if (' . (time() + $ttl) . ' < time()) $expired = true; else{$expired = false; $value = \'' . addcslashes($value, '\\\'') . '\';}' . '?' . '>';
Chris@76 2632 $fh = @fopen($cachedir . '/data_' . $key . '.php', 'w');
Chris@76 2633 if ($fh)
Chris@76 2634 {
Chris@76 2635 // Write the file.
Chris@76 2636 set_file_buffer($fh, 0);
Chris@76 2637 flock($fh, LOCK_EX);
Chris@76 2638 $cache_bytes = fwrite($fh, $cache_data);
Chris@76 2639 flock($fh, LOCK_UN);
Chris@76 2640 fclose($fh);
Chris@76 2641
Chris@76 2642 // Check that the cache write was successful; all the data should be written
Chris@76 2643 // If it fails due to low diskspace, remove the cache file
Chris@76 2644 if ($cache_bytes != strlen($cache_data))
Chris@76 2645 @unlink($cachedir . '/data_' . $key . '.php');
Chris@76 2646 }
Chris@76 2647 }
Chris@76 2648 }
Chris@76 2649
Chris@76 2650 if (isset($db_show_debug) && $db_show_debug === true)
Chris@76 2651 $cache_hits[$cache_count]['t'] = array_sum(explode(' ', microtime())) - array_sum(explode(' ', $st));
Chris@76 2652 }
Chris@76 2653
Chris@76 2654 function cache_get_data($key, $ttl = 120)
Chris@76 2655 {
Chris@76 2656 global $boardurl, $sourcedir, $modSettings, $memcached;
Chris@76 2657 global $cache_hits, $cache_count, $db_show_debug, $cachedir;
Chris@76 2658
Chris@76 2659 if (empty($modSettings['cache_enable']) && !empty($modSettings))
Chris@76 2660 return;
Chris@76 2661
Chris@76 2662 $cache_count = isset($cache_count) ? $cache_count + 1 : 1;
Chris@76 2663 if (isset($db_show_debug) && $db_show_debug === true)
Chris@76 2664 {
Chris@76 2665 $cache_hits[$cache_count] = array('k' => $key, 'd' => 'get');
Chris@76 2666 $st = microtime();
Chris@76 2667 }
Chris@76 2668
Chris@76 2669 $key = md5($boardurl . filemtime($sourcedir . '/Load.php')) . '-SMF-' . strtr($key, ':', '-');
Chris@76 2670
Chris@76 2671 // Okay, let's go for it memcached!
Chris@76 2672 if (function_exists('memcache_get') && isset($modSettings['cache_memcached']) && trim($modSettings['cache_memcached']) != '')
Chris@76 2673 {
Chris@76 2674 // Not connected yet?
Chris@76 2675 if (empty($memcached))
Chris@76 2676 get_memcached_server();
Chris@76 2677 if (!$memcached)
Chris@76 2678 return;
Chris@76 2679
Chris@76 2680 $value = memcache_get($memcached, $key);
Chris@76 2681 }
Chris@76 2682 // Again, eAccelerator.
Chris@76 2683 elseif (function_exists('eaccelerator_get'))
Chris@76 2684 $value = eaccelerator_get($key);
Chris@76 2685 // The older, but ever-stable, Turck MMCache...
Chris@76 2686 elseif (function_exists('mmcache_get'))
Chris@76 2687 $value = mmcache_get($key);
Chris@76 2688 // This is the free APC from PECL.
Chris@76 2689 elseif (function_exists('apc_fetch'))
Chris@76 2690 $value = apc_fetch($key . 'smf');
Chris@76 2691 // Zend's pricey stuff.
Chris@76 2692 elseif (function_exists('output_cache_get'))
Chris@76 2693 $value = output_cache_get($key, $ttl);
Chris@76 2694 elseif (function_exists('xcache_get') && ini_get('xcache.var_size') > 0)
Chris@76 2695 $value = xcache_get($key);
Chris@76 2696 // Otherwise it's SMF data!
Chris@76 2697 elseif (file_exists($cachedir . '/data_' . $key . '.php') && filesize($cachedir . '/data_' . $key . '.php') > 10)
Chris@76 2698 {
Chris@76 2699 require($cachedir . '/data_' . $key . '.php');
Chris@76 2700 if (!empty($expired) && isset($value))
Chris@76 2701 {
Chris@76 2702 @unlink($cachedir . '/data_' . $key . '.php');
Chris@76 2703 unset($value);
Chris@76 2704 }
Chris@76 2705 }
Chris@76 2706
Chris@76 2707 if (isset($db_show_debug) && $db_show_debug === true)
Chris@76 2708 {
Chris@76 2709 $cache_hits[$cache_count]['t'] = array_sum(explode(' ', microtime())) - array_sum(explode(' ', $st));
Chris@76 2710 $cache_hits[$cache_count]['s'] = isset($value) ? strlen($value) : 0;
Chris@76 2711 }
Chris@76 2712
Chris@76 2713 if (empty($value))
Chris@76 2714 return null;
Chris@76 2715 // If it's broke, it's broke... so give up on it.
Chris@76 2716 else
Chris@76 2717 return @unserialize($value);
Chris@76 2718 }
Chris@76 2719
Chris@76 2720 function get_memcached_server($level = 3)
Chris@76 2721 {
Chris@76 2722 global $modSettings, $memcached, $db_persist;
Chris@76 2723
Chris@76 2724 $servers = explode(',', $modSettings['cache_memcached']);
Chris@76 2725 $server = explode(':', trim($servers[array_rand($servers)]));
Chris@76 2726
Chris@76 2727 // Don't try more times than we have servers!
Chris@76 2728 $level = min(count($servers), $level);
Chris@76 2729
Chris@76 2730 // Don't wait too long: yes, we want the server, but we might be able to run the query faster!
Chris@76 2731 if (empty($db_persist))
Chris@76 2732 $memcached = memcache_connect($server[0], empty($server[1]) ? 11211 : $server[1]);
Chris@76 2733 else
Chris@76 2734 $memcached = memcache_pconnect($server[0], empty($server[1]) ? 11211 : $server[1]);
Chris@76 2735
Chris@76 2736 if (!$memcached && $level > 0)
Chris@76 2737 get_memcached_server($level - 1);
Chris@76 2738 }
Chris@76 2739
Chris@76 2740 ?>