1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file has the hefty job of loading information for the forum. |
5
|
|
|
* |
6
|
|
|
* @name ElkArte Forum |
7
|
|
|
* @copyright ElkArte Forum contributors |
8
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause |
9
|
|
|
* |
10
|
|
|
* This file contains code covered by: |
11
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
12
|
|
|
* license: BSD, See included LICENSE.TXT for terms and conditions. |
13
|
|
|
* |
14
|
|
|
* @version 1.1 beta 1 |
15
|
|
|
* |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
if (!defined('ELK')) |
19
|
|
|
die('No access...'); |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Load the $modSettings array and many necessary forum settings. |
23
|
|
|
* |
24
|
|
|
* What it does: |
25
|
|
|
* - load the settings from cache if available, otherwise from the database. |
26
|
|
|
* - sets the timezone |
27
|
|
|
* - checks the load average settings if available. |
28
|
|
|
* - check whether post moderation is enabled. |
29
|
|
|
* - calls add_integration_function |
30
|
|
|
* - calls integrate_pre_include, integrate_pre_load, |
31
|
|
|
* |
32
|
|
|
* @global array $modSettings is a giant array of all of the forum-wide settings and statistics. |
33
|
|
|
*/ |
34
|
|
|
function reloadSettings() |
35
|
|
|
{ |
36
|
|
|
global $modSettings; |
37
|
|
|
|
38
|
|
|
$db = database(); |
39
|
|
|
$cache = Cache::instance(); |
40
|
|
|
$hooks = Hooks::get(); |
41
|
|
|
|
42
|
|
|
// Try to load it from the cache first; it'll never get cached if the setting is off. |
43
|
|
|
if (!$cache->getVar($modSettings, 'modSettings', 90)) |
44
|
|
|
{ |
45
|
|
|
$request = $db->query('', ' |
46
|
|
|
SELECT variable, value |
47
|
|
|
FROM {db_prefix}settings', |
48
|
|
|
array( |
49
|
|
|
) |
50
|
|
|
); |
51
|
|
|
$modSettings = array(); |
52
|
1 |
|
if (!$request) |
53
|
|
|
Errors::instance()->display_db_error(); |
54
|
|
|
while ($row = $db->fetch_row($request)) |
55
|
|
|
$modSettings[$row[0]] = $row[1]; |
56
|
|
|
$db->free_result($request); |
57
|
|
|
|
58
|
|
|
// Do a few things to protect against missing settings or settings with invalid values... |
59
|
|
View Code Duplication |
if (empty($modSettings['defaultMaxTopics']) || $modSettings['defaultMaxTopics'] <= 0 || $modSettings['defaultMaxTopics'] > 999) |
60
|
|
|
$modSettings['defaultMaxTopics'] = 20; |
61
|
|
View Code Duplication |
if (empty($modSettings['defaultMaxMessages']) || $modSettings['defaultMaxMessages'] <= 0 || $modSettings['defaultMaxMessages'] > 999) |
62
|
|
|
$modSettings['defaultMaxMessages'] = 15; |
63
|
|
View Code Duplication |
if (empty($modSettings['defaultMaxMembers']) || $modSettings['defaultMaxMembers'] <= 0 || $modSettings['defaultMaxMembers'] > 999) |
64
|
|
|
$modSettings['defaultMaxMembers'] = 30; |
65
|
|
|
if (empty($modSettings['subject_length'])) |
66
|
|
|
$modSettings['subject_length'] = 24; |
67
|
|
|
|
68
|
|
|
$modSettings['warning_enable'] = $modSettings['warning_settings'][0]; |
69
|
|
|
|
70
|
|
|
$cache->put('modSettings', $modSettings, 90); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$hooks->loadIntegrations(); |
74
|
|
|
|
75
|
|
|
// Setting the timezone is a requirement for some functions in PHP >= 5.1. |
76
|
|
|
if (isset($modSettings['default_timezone'])) |
77
|
|
|
date_default_timezone_set($modSettings['default_timezone']); |
78
|
|
|
|
79
|
|
|
// Check the load averages? |
80
|
|
|
if (!empty($modSettings['loadavg_enable'])) |
81
|
|
|
{ |
82
|
|
|
if (!$cache->getVar($modSettings['load_average'], 'loadavg', 90)) |
83
|
|
|
{ |
84
|
|
|
require_once(SUBSDIR . '/Server.subs.php'); |
85
|
|
|
$modSettings['load_average'] = detectServerLoad(); |
86
|
|
|
|
87
|
|
|
$cache->put('loadavg', $modSettings['load_average'], 90); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if ($modSettings['load_average'] !== false) |
91
|
|
|
call_integration_hook('integrate_load_average', array($modSettings['load_average'])); |
92
|
|
|
|
93
|
|
|
// Let's have at least a zero |
94
|
|
|
if (empty($modSettings['loadavg_forum']) || $modSettings['load_average'] === false) |
95
|
|
|
$modSettings['current_load'] = 0; |
96
|
|
|
else |
97
|
|
|
$modSettings['current_load'] = $modSettings['load_average']; |
98
|
|
|
|
99
|
|
|
if (!empty($modSettings['loadavg_forum']) && $modSettings['current_load'] >= $modSettings['loadavg_forum']) |
100
|
|
|
Errors::instance()->display_loadavg_error(); |
101
|
|
|
} |
102
|
|
|
else |
103
|
|
|
$modSettings['current_load'] = 0; |
104
|
|
|
|
105
|
|
|
// Is post moderation alive and well? |
106
|
|
|
$modSettings['postmod_active'] = isset($modSettings['admin_features']) ? in_array('pm', explode(',', $modSettings['admin_features'])) : true; |
107
|
|
|
|
108
|
|
|
// @deprecated since 1.0.6 compatibility setting for migration |
109
|
|
|
if (!isset($modSettings['avatar_max_height'])) |
110
|
|
|
$modSettings['avatar_max_height'] = $modSettings['avatar_max_height_external']; |
111
|
|
|
if (!isset($modSettings['avatar_max_width'])) |
112
|
|
|
$modSettings['avatar_max_width'] = $modSettings['avatar_max_width_external']; |
113
|
|
|
|
114
|
|
|
// Here to justify the name of this function. :P |
115
|
|
|
// It should be added to the install and upgrade scripts. |
116
|
|
|
// But since the converters need to be updated also. This is easier. |
117
|
|
|
if (empty($modSettings['currentAttachmentUploadDir'])) |
118
|
|
|
{ |
119
|
|
|
updateSettings(array( |
120
|
|
|
'attachmentUploadDir' => serialize(array(1 => $modSettings['attachmentUploadDir'])), |
121
|
|
|
'currentAttachmentUploadDir' => 1, |
122
|
|
|
)); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
// Integration is cool. |
126
|
|
|
if (defined('ELK_INTEGRATION_SETTINGS')) |
127
|
|
|
{ |
128
|
|
|
$integration_settings = unserialize(ELK_INTEGRATION_SETTINGS); |
129
|
|
|
foreach ($integration_settings as $hook => $function) |
130
|
|
|
add_integration_function($hook, $function); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
// Any files to pre include? |
134
|
|
|
call_integration_include_hook('integrate_pre_include'); |
135
|
|
|
|
136
|
|
|
// Call pre load integration functions. |
137
|
|
|
call_integration_hook('integrate_pre_load'); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Load all the important user information. |
142
|
|
|
* |
143
|
|
|
* What it does: |
144
|
|
|
* - sets up the $user_info array |
145
|
|
|
* - assigns $user_info['query_wanna_see_board'] for what boards the user can see. |
146
|
|
|
* - first checks for cookie or integration validation. |
147
|
|
|
* - uses the current session if no integration function or cookie is found. |
148
|
|
|
* - checks password length, if member is activated and the login span isn't over. |
149
|
|
|
* - if validation fails for the user, $id_member is set to 0. |
150
|
|
|
* - updates the last visit time when needed. |
151
|
|
|
*/ |
152
|
|
|
function loadUserSettings() |
|
|
|
|
153
|
|
|
{ |
154
|
|
|
global $context, $modSettings, $user_settings, $cookiename, $user_info, $language; |
155
|
|
|
|
156
|
|
|
$db = database(); |
157
|
|
|
$cache = Cache::instance(); |
158
|
|
|
|
159
|
|
|
// Check first the integration, then the cookie, and last the session. |
160
|
|
|
if (count($integration_ids = call_integration_hook('integrate_verify_user')) > 0) |
161
|
|
|
{ |
162
|
|
|
$id_member = 0; |
163
|
|
|
foreach ($integration_ids as $integration_id) |
164
|
|
|
{ |
165
|
|
|
$integration_id = (int) $integration_id; |
166
|
|
|
if ($integration_id > 0) |
167
|
|
|
{ |
168
|
|
|
$id_member = $integration_id; |
169
|
|
|
$already_verified = true; |
170
|
|
|
break; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
} |
174
|
|
|
else |
175
|
|
|
$id_member = 0; |
176
|
|
|
|
177
|
|
|
// We'll need IPs and user agent and stuff, they came to visit us with! |
178
|
|
|
$req = request(); |
179
|
|
|
|
180
|
|
|
if (empty($id_member) && isset($_COOKIE[$cookiename])) |
181
|
|
|
{ |
182
|
|
|
// Fix a security hole in PHP 4.3.9 and below... |
183
|
|
|
if (preg_match('~^a:[34]:\{i:0;i:\d{1,8};i:1;s:(0|64):"([a-fA-F0-9]{64})?";i:2;[id]:\d{1,14};(i:3;i:\d;)?\}$~i', $_COOKIE[$cookiename]) == 1) |
184
|
|
|
{ |
185
|
|
|
list ($id_member, $password) = @unserialize($_COOKIE[$cookiename]); |
|
|
|
|
186
|
|
|
$id_member = !empty($id_member) && strlen($password) > 0 ? (int) $id_member : 0; |
187
|
|
|
} |
188
|
|
|
else |
189
|
|
|
$id_member = 0; |
190
|
|
|
} |
191
|
|
|
elseif (empty($id_member) && isset($_SESSION['login_' . $cookiename]) && ($_SESSION['USER_AGENT'] == $req->user_agent() || !empty($modSettings['disableCheckUA']))) |
192
|
|
|
{ |
193
|
|
|
// @todo Perhaps we can do some more checking on this, such as on the first octet of the IP? |
194
|
|
|
list ($id_member, $password, $login_span) = @unserialize($_SESSION['login_' . $cookiename]); |
195
|
|
|
$id_member = !empty($id_member) && strlen($password) == 64 && $login_span > time() ? (int) $id_member : 0; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
// Only load this stuff if the user isn't a guest. |
199
|
|
|
if ($id_member != 0) |
200
|
|
|
{ |
201
|
|
|
// Is the member data cached? |
202
|
|
|
if (!$cache->checkLevel(2) || !$cache->getVar($user_settings, 'user_settings-' . $id_member, 60)) |
203
|
|
|
{ |
204
|
|
|
list ($user_settings) = $db->fetchQuery(' |
205
|
|
|
SELECT mem.*, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type |
206
|
|
|
FROM {db_prefix}members AS mem |
207
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = {int:id_member}) |
208
|
|
|
WHERE mem.id_member = {int:id_member} |
209
|
|
|
LIMIT 1', |
210
|
|
|
array( |
211
|
|
|
'id_member' => $id_member, |
212
|
|
|
) |
213
|
|
|
); |
214
|
|
|
|
215
|
|
|
// Make the ID specifically an integer |
216
|
|
|
$user_settings['id_member'] = (int) $user_settings['id_member']; |
217
|
|
|
|
218
|
|
|
if ($cache->checkLevel(2)) |
219
|
|
|
$cache->put('user_settings-' . $id_member, $user_settings, 60); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
// Did we find 'im? If not, junk it. |
223
|
|
|
if (!empty($user_settings)) |
224
|
|
|
{ |
225
|
|
|
// As much as the password should be right, we can assume the integration set things up. |
226
|
|
|
if (!empty($already_verified) && $already_verified === true) |
227
|
|
|
$check = true; |
228
|
|
|
// SHA-256 passwords should be 64 characters long. |
229
|
|
|
elseif (strlen($password) == 64) |
|
|
|
|
230
|
|
|
$check = hash('sha256', ($user_settings['passwd'] . $user_settings['password_salt'])) == $password; |
231
|
|
|
else |
232
|
|
|
$check = false; |
233
|
|
|
|
234
|
|
|
// Wrong password or not activated - either way, you're going nowhere. |
235
|
|
|
$id_member = $check && ($user_settings['is_activated'] == 1 || $user_settings['is_activated'] == 11) ? (int) $user_settings['id_member'] : 0; |
236
|
|
|
} |
237
|
|
|
else |
238
|
|
|
$id_member = 0; |
239
|
|
|
|
240
|
|
|
// If we no longer have the member maybe they're being all hackey, stop brute force! |
241
|
|
|
if (!$id_member) |
242
|
|
|
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); |
|
|
|
|
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
// Found 'im, let's set up the variables. |
246
|
|
|
if ($id_member != 0) |
247
|
|
|
{ |
248
|
|
|
// Let's not update the last visit time in these cases... |
249
|
|
|
// 1. SSI doesn't count as visiting the forum. |
250
|
|
|
// 2. RSS feeds and XMLHTTP requests don't count either. |
251
|
|
|
// 3. If it was set within this session, no need to set it again. |
252
|
|
|
// 4. New session, yet updated < five hours ago? Maybe cache can help. |
253
|
|
|
if (ELK != 'SSI' && !isset($_REQUEST['xml']) && (!isset($_REQUEST['action']) || $_REQUEST['action'] != '.xml') && empty($_SESSION['id_msg_last_visit']) && (!$cache->isEnabled() || !$cache->getVar($_SESSION['id_msg_last_visit'], 'user_last_visit-' . $id_member, 5 * 3600))) |
254
|
|
|
{ |
255
|
|
|
// @todo can this be cached? |
256
|
|
|
// Do a quick query to make sure this isn't a mistake. |
257
|
|
|
require_once(SUBSDIR . '/Messages.subs.php'); |
258
|
|
|
$visitOpt = basicMessageInfo($user_settings['id_msg_last_visit'], true); |
259
|
|
|
|
260
|
|
|
$_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit']; |
261
|
|
|
|
262
|
|
|
// If it was *at least* five hours ago... |
263
|
|
|
if ($visitOpt['poster_time'] < time() - 5 * 3600) |
264
|
|
|
{ |
265
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
266
|
|
|
updateMemberData($id_member, array('id_msg_last_visit' => (int) $modSettings['maxMsgID'], 'last_login' => time(), 'member_ip' => $req->client_ip(), 'member_ip2' => $req->ban_ip())); |
267
|
|
|
$user_settings['last_login'] = time(); |
268
|
|
|
|
269
|
|
|
if ($cache->checkLevel(2)) |
270
|
|
|
$cache->put('user_settings-' . $id_member, $user_settings, 60); |
271
|
|
|
|
272
|
|
|
$cache->put('user_last_visit-' . $id_member, $_SESSION['id_msg_last_visit'], 5 * 3600); |
273
|
|
|
} |
274
|
|
|
} |
275
|
|
|
elseif (empty($_SESSION['id_msg_last_visit'])) |
276
|
|
|
$_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit']; |
277
|
|
|
|
278
|
|
|
$username = $user_settings['member_name']; |
279
|
|
|
|
280
|
|
|
if (empty($user_settings['additional_groups'])) |
281
|
|
|
$user_info = array( |
282
|
|
|
'groups' => array($user_settings['id_group'], $user_settings['id_post_group']) |
283
|
|
|
); |
284
|
|
|
else |
285
|
|
|
$user_info = array( |
286
|
|
|
'groups' => array_merge( |
287
|
|
|
array($user_settings['id_group'], $user_settings['id_post_group']), |
288
|
|
|
explode(',', $user_settings['additional_groups']) |
289
|
|
|
) |
290
|
|
|
); |
291
|
|
|
|
292
|
|
|
// Because history has proven that it is possible for groups to go bad - clean up in case. |
293
|
|
|
foreach ($user_info['groups'] as $k => $v) |
294
|
|
|
$user_info['groups'][$k] = (int) $v; |
295
|
|
|
|
296
|
|
|
// This is a logged in user, so definitely not a spider. |
297
|
|
|
$user_info['possibly_robot'] = false; |
298
|
|
|
} |
299
|
|
|
// If the user is a guest, initialize all the critical user settings. |
300
|
|
|
else |
301
|
|
|
{ |
302
|
|
|
// This is what a guest's variables should be. |
303
|
|
|
$username = ''; |
304
|
|
|
$user_info = array('groups' => array(-1)); |
305
|
|
|
$user_settings = array(); |
306
|
|
|
|
307
|
|
|
if (isset($_COOKIE[$cookiename])) |
308
|
|
|
$_COOKIE[$cookiename] = ''; |
309
|
|
|
|
310
|
|
|
// Create a login token if it doesn't exist yet. |
311
|
|
|
if (!isset($_SESSION['token']['post-login'])) |
312
|
|
|
createToken('login'); |
313
|
|
|
else |
314
|
|
|
list ($context['login_token_var'],,, $context['login_token']) = $_SESSION['token']['post-login']; |
315
|
|
|
|
316
|
|
|
// Do we perhaps think this is a search robot? Check every five minutes just in case... |
317
|
|
|
if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300)) |
318
|
|
|
{ |
319
|
|
|
require_once(SUBSDIR . '/SearchEngines.subs.php'); |
320
|
|
|
$user_info['possibly_robot'] = spiderCheck(); |
321
|
|
|
} |
322
|
|
|
elseif (!empty($modSettings['spider_mode'])) |
323
|
|
|
$user_info['possibly_robot'] = isset($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0; |
324
|
|
|
// If we haven't turned on proper spider hunts then have a guess! |
325
|
|
|
else |
326
|
|
|
{ |
327
|
|
|
$ci_user_agent = strtolower($req->user_agent()); |
328
|
|
|
$user_info['possibly_robot'] = (strpos($ci_user_agent, 'mozilla') === false && strpos($ci_user_agent, 'opera') === false) || preg_match('~(googlebot|slurp|crawl|msnbot|yandex|bingbot|baidu)~u', $ci_user_agent) == 1; |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
// Set up the $user_info array. |
333
|
|
|
$user_info += array( |
334
|
|
|
'id' => $id_member, |
335
|
|
|
'username' => $username, |
336
|
|
|
'name' => isset($user_settings['real_name']) ? $user_settings['real_name'] : '', |
337
|
|
|
'email' => isset($user_settings['email_address']) ? $user_settings['email_address'] : '', |
338
|
|
|
'passwd' => isset($user_settings['passwd']) ? $user_settings['passwd'] : '', |
339
|
|
|
'language' => empty($user_settings['lngfile']) || empty($modSettings['userLanguage']) ? $language : $user_settings['lngfile'], |
340
|
|
|
'is_guest' => $id_member == 0, |
341
|
|
|
'is_admin' => in_array(1, $user_info['groups']), |
342
|
|
|
'theme' => empty($user_settings['id_theme']) ? 0 : $user_settings['id_theme'], |
343
|
|
|
'last_login' => empty($user_settings['last_login']) ? 0 : $user_settings['last_login'], |
344
|
|
|
'ip' => $req->client_ip(), |
345
|
|
|
'ip2' => $req->ban_ip(), |
346
|
|
|
'posts' => empty($user_settings['posts']) ? 0 : $user_settings['posts'], |
347
|
|
|
'time_format' => empty($user_settings['time_format']) ? $modSettings['time_format'] : $user_settings['time_format'], |
348
|
|
|
'time_offset' => empty($user_settings['time_offset']) ? 0 : $user_settings['time_offset'], |
349
|
|
|
'avatar' => array_merge(array( |
350
|
|
|
'url' => isset($user_settings['avatar']) ? $user_settings['avatar'] : '', |
351
|
|
|
'filename' => empty($user_settings['filename']) ? '' : $user_settings['filename'], |
352
|
|
|
'custom_dir' => !empty($user_settings['attachment_type']) && $user_settings['attachment_type'] == 1, |
353
|
|
|
'id_attach' => isset($user_settings['id_attach']) ? $user_settings['id_attach'] : 0 |
354
|
|
|
), determineAvatar($user_settings)), |
355
|
|
|
'smiley_set' => isset($user_settings['smiley_set']) ? $user_settings['smiley_set'] : '', |
356
|
|
|
'messages' => empty($user_settings['personal_messages']) ? 0 : $user_settings['personal_messages'], |
357
|
|
|
'mentions' => empty($user_settings['mentions']) ? 0 : max(0, $user_settings['mentions']), |
358
|
|
|
'unread_messages' => empty($user_settings['unread_messages']) ? 0 : $user_settings['unread_messages'], |
359
|
|
|
'total_time_logged_in' => empty($user_settings['total_time_logged_in']) ? 0 : $user_settings['total_time_logged_in'], |
360
|
|
|
'buddies' => !empty($modSettings['enable_buddylist']) && !empty($user_settings['buddy_list']) ? explode(',', $user_settings['buddy_list']) : array(), |
361
|
|
|
'ignoreboards' => !empty($user_settings['ignore_boards']) && !empty($modSettings['allow_ignore_boards']) ? explode(',', $user_settings['ignore_boards']) : array(), |
362
|
|
|
'ignoreusers' => !empty($user_settings['pm_ignore_list']) ? explode(',', $user_settings['pm_ignore_list']) : array(), |
363
|
|
|
'warning' => isset($user_settings['warning']) ? $user_settings['warning'] : 0, |
364
|
|
|
'permissions' => array(), |
365
|
|
|
); |
366
|
|
|
$user_info['groups'] = array_unique($user_info['groups']); |
367
|
|
|
|
368
|
|
|
// 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. |
369
|
|
|
if (!empty($user_info['ignoreboards']) && empty($user_info['ignoreboards'][$tmp = count($user_info['ignoreboards']) - 1])) |
370
|
|
|
unset($user_info['ignoreboards'][$tmp]); |
371
|
|
|
|
372
|
|
|
// Do we have any languages to validate this? |
373
|
|
|
if (!empty($modSettings['userLanguage']) && (!empty($_GET['language']) || !empty($_SESSION['language']))) |
374
|
|
|
$languages = getLanguages(); |
375
|
|
|
|
376
|
|
|
// Allow the user to change their language if its valid. |
377
|
|
|
if (!empty($modSettings['userLanguage']) && !empty($_GET['language']) && isset($languages[strtr($_GET['language'], './\\:', '____')])) |
378
|
|
|
{ |
379
|
|
|
$user_info['language'] = strtr($_GET['language'], './\\:', '____'); |
380
|
|
|
$_SESSION['language'] = $user_info['language']; |
381
|
|
|
} |
382
|
|
|
elseif (!empty($modSettings['userLanguage']) && !empty($_SESSION['language']) && isset($languages[strtr($_SESSION['language'], './\\:', '____')])) |
383
|
|
|
$user_info['language'] = strtr($_SESSION['language'], './\\:', '____'); |
384
|
|
|
|
385
|
|
|
// Just build this here, it makes it easier to change/use - administrators can see all boards. |
386
|
|
|
if ($user_info['is_admin']) |
387
|
|
|
$user_info['query_see_board'] = '1=1'; |
388
|
|
|
// Otherwise just the groups in $user_info['groups']. |
389
|
|
|
else |
390
|
|
|
$user_info['query_see_board'] = '((FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0)' . (!empty($modSettings['deny_boards_access']) ? ' AND (FIND_IN_SET(' . implode(', b.deny_member_groups) = 0 AND FIND_IN_SET(', $user_info['groups']) . ', b.deny_member_groups) = 0)' : '') . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')'; |
391
|
|
|
// Build the list of boards they WANT to see. |
392
|
|
|
// This will take the place of query_see_boards in certain spots, so it better include the boards they can see also |
393
|
|
|
|
394
|
|
|
// If they aren't ignoring any boards then they want to see all the boards they can see |
395
|
|
|
if (empty($user_info['ignoreboards'])) |
396
|
|
|
$user_info['query_wanna_see_board'] = $user_info['query_see_board']; |
397
|
|
|
// Ok I guess they don't want to see all the boards |
398
|
|
|
else |
399
|
|
|
$user_info['query_wanna_see_board'] = '(' . $user_info['query_see_board'] . ' AND b.id_board NOT IN (' . implode(',', $user_info['ignoreboards']) . '))'; |
400
|
|
|
|
401
|
|
|
call_integration_hook('integrate_user_info'); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Check for moderators and see if they have access to the board. |
406
|
|
|
* |
407
|
|
|
* What it does: |
408
|
|
|
* - sets up the $board_info array for current board information. |
409
|
|
|
* - if cache is enabled, the $board_info array is stored in cache. |
410
|
|
|
* - redirects to appropriate post if only message id is requested. |
411
|
|
|
* - is only used when inside a topic or board. |
412
|
|
|
* - determines the local moderators for the board. |
413
|
|
|
* - adds group id 3 if the user is a local moderator for the board they are in. |
414
|
|
|
* - prevents access if user is not in proper group nor a local moderator of the board. |
415
|
|
|
*/ |
416
|
|
|
function loadBoard() |
|
|
|
|
417
|
|
|
{ |
418
|
|
|
global $txt, $scripturl, $context, $modSettings; |
419
|
|
|
global $board_info, $board, $topic, $user_info; |
420
|
|
|
|
421
|
|
|
$db = database(); |
422
|
|
|
$cache = Cache::instance(); |
423
|
|
|
|
424
|
|
|
// Assume they are not a moderator. |
425
|
|
|
$user_info['is_mod'] = false; |
426
|
|
|
// @since 1.0.5 - is_mod takes into account only local (board) moderators, |
427
|
|
|
// and not global moderators, is_moderator is meant to take into account both. |
428
|
|
|
$user_info['is_moderator'] = false; |
429
|
|
|
|
430
|
|
|
// Start the linktree off empty.. |
431
|
|
|
$context['linktree'] = array(); |
432
|
|
|
|
433
|
|
|
// Have they by chance specified a message id but nothing else? |
434
|
|
|
if (empty($_REQUEST['action']) && empty($topic) && empty($board) && !empty($_REQUEST['msg'])) |
435
|
|
|
{ |
436
|
|
|
// Make sure the message id is really an int. |
437
|
|
|
$_REQUEST['msg'] = (int) $_REQUEST['msg']; |
438
|
|
|
|
439
|
|
|
// Looking through the message table can be slow, so try using the cache first. |
440
|
|
|
if (!$cache->getVar($topic, 'msg_topic-' . $_REQUEST['msg'], 120)) |
441
|
|
|
{ |
442
|
|
|
require_once(SUBSDIR . '/Messages.subs.php'); |
443
|
|
|
$topic = associatedTopic($_REQUEST['msg']); |
444
|
|
|
|
445
|
|
|
// So did it find anything? |
446
|
|
|
if ($topic !== false) |
447
|
|
|
{ |
448
|
|
|
// Save save save. |
449
|
|
|
$cache->put('msg_topic-' . $_REQUEST['msg'], $topic, 120); |
450
|
|
|
} |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
// Remember redirection is the key to avoiding fallout from your bosses. |
454
|
|
|
if (!empty($topic)) |
455
|
|
|
redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg']); |
456
|
|
|
else |
457
|
|
|
{ |
458
|
|
|
loadPermissions(); |
459
|
|
|
loadTheme(); |
460
|
|
|
Errors::instance()->fatal_lang_error('topic_gone', false); |
461
|
|
|
} |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
// Load this board only if it is specified. |
465
|
|
|
if (empty($board) && empty($topic)) |
466
|
|
|
{ |
467
|
|
|
$board_info = array('moderators' => array()); |
468
|
|
|
return; |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
if ($cache->isEnabled() && (empty($topic) || $cache->checkLevel(3))) |
472
|
|
|
{ |
473
|
|
|
// @todo SLOW? |
474
|
|
|
if (!empty($topic)) |
475
|
|
|
$temp = $cache->get('topic_board-' . $topic, 120); |
476
|
|
|
else |
477
|
|
|
$temp = $cache->get('board-' . $board, 120); |
478
|
|
|
|
479
|
|
|
if (!empty($temp)) |
480
|
|
|
{ |
481
|
|
|
$board_info = $temp; |
482
|
|
|
$board = (int) $board_info['id']; |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
if (empty($temp)) |
487
|
|
|
{ |
488
|
|
|
$select_columns = array(); |
489
|
|
|
$select_tables = array(); |
490
|
|
|
// Wanna grab something more from the boards table or another table at all? |
491
|
|
|
call_integration_hook('integrate_load_board_query', array(&$select_columns, &$select_tables)); |
492
|
|
|
|
493
|
|
|
$request = $db->query('', ' |
494
|
|
|
SELECT |
495
|
|
|
c.id_cat, b.name AS bname, b.description, b.num_topics, b.member_groups, b.deny_member_groups, |
496
|
|
|
b.id_parent, c.name AS cname, IFNULL(mem.id_member, 0) AS id_moderator, |
497
|
|
|
mem.real_name' . (!empty($topic) ? ', b.id_board' : '') . ', b.child_level, |
498
|
|
|
b.id_theme, b.override_theme, b.count_posts, b.id_profile, b.redirect, |
499
|
|
|
b.unapproved_topics, b.unapproved_posts' . (!empty($topic) ? ', t.approved, t.id_member_started' : '') . (!empty($select_columns) ? ', ' . implode(', ', $select_columns) : '') . ' |
500
|
|
|
FROM {db_prefix}boards AS b' . (!empty($topic) ? ' |
501
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})' : '') . (!empty($select_tables) ? ' |
502
|
|
|
' . implode("\n\t\t\t\t", $select_tables) : '') . ' |
503
|
|
|
LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat) |
504
|
|
|
LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = {raw:board_link}) |
505
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member) |
506
|
|
|
WHERE b.id_board = {raw:board_link}', |
507
|
|
|
array( |
508
|
|
|
'current_topic' => $topic, |
509
|
|
|
'board_link' => empty($topic) ? $db->quote('{int:current_board}', array('current_board' => $board)) : 't.id_board', |
510
|
|
|
) |
511
|
|
|
); |
512
|
|
|
// If there aren't any, skip. |
513
|
|
|
if ($db->num_rows($request) > 0) |
514
|
|
|
{ |
515
|
|
|
$row = $db->fetch_assoc($request); |
516
|
|
|
|
517
|
|
|
// Set the current board. |
518
|
|
|
if (!empty($row['id_board'])) |
519
|
|
|
$board = (int) $row['id_board']; |
520
|
|
|
|
521
|
|
|
// Basic operating information. (globals... :/) |
522
|
|
|
$board_info = array( |
523
|
|
|
'id' => $board, |
524
|
|
|
'moderators' => array(), |
525
|
|
|
'cat' => array( |
526
|
|
|
'id' => $row['id_cat'], |
527
|
|
|
'name' => $row['cname'] |
528
|
|
|
), |
529
|
|
|
'name' => $row['bname'], |
530
|
|
|
'raw_description' => $row['description'], |
531
|
|
|
'description' => $row['description'], |
532
|
|
|
'num_topics' => $row['num_topics'], |
533
|
|
|
'unapproved_topics' => $row['unapproved_topics'], |
534
|
|
|
'unapproved_posts' => $row['unapproved_posts'], |
535
|
|
|
'unapproved_user_topics' => 0, |
536
|
|
|
'parent_boards' => getBoardParents($row['id_parent']), |
537
|
|
|
'parent' => $row['id_parent'], |
538
|
|
|
'child_level' => $row['child_level'], |
539
|
|
|
'theme' => $row['id_theme'], |
540
|
|
|
'override_theme' => !empty($row['override_theme']), |
541
|
|
|
'profile' => $row['id_profile'], |
542
|
|
|
'redirect' => $row['redirect'], |
543
|
|
|
'posts_count' => empty($row['count_posts']), |
544
|
|
|
'cur_topic_approved' => empty($topic) || $row['approved'], |
545
|
|
|
'cur_topic_starter' => empty($topic) ? 0 : $row['id_member_started'], |
546
|
|
|
); |
547
|
|
|
|
548
|
|
|
// Load the membergroups allowed, and check permissions. |
549
|
|
|
$board_info['groups'] = $row['member_groups'] == '' ? array() : explode(',', $row['member_groups']); |
550
|
|
|
$board_info['deny_groups'] = $row['deny_member_groups'] == '' ? array() : explode(',', $row['deny_member_groups']); |
551
|
|
|
|
552
|
|
|
do |
553
|
|
|
{ |
554
|
|
|
if (!empty($row['id_moderator'])) |
555
|
|
|
$board_info['moderators'][$row['id_moderator']] = array( |
556
|
|
|
'id' => $row['id_moderator'], |
557
|
|
|
'name' => $row['real_name'], |
558
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'], |
559
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>' |
560
|
|
|
); |
561
|
|
|
} |
562
|
|
|
while ($row = $db->fetch_assoc($request)); |
563
|
|
|
|
564
|
|
|
// If the board only contains unapproved posts and the user can't approve then they can't see any topics. |
565
|
|
|
// If that is the case do an additional check to see if they have any topics waiting to be approved. |
566
|
|
|
if ($board_info['num_topics'] == 0 && $modSettings['postmod_active'] && !allowedTo('approve_posts')) |
567
|
|
|
{ |
568
|
|
|
// Free the previous result |
569
|
|
|
$db->free_result($request); |
570
|
|
|
|
571
|
|
|
// @todo why is this using id_topic? |
572
|
|
|
// @todo Can this get cached? |
573
|
|
|
$request = $db->query('', ' |
574
|
|
|
SELECT COUNT(id_topic) |
575
|
|
|
FROM {db_prefix}topics |
576
|
|
|
WHERE id_member_started={int:id_member} |
577
|
|
|
AND approved = {int:unapproved} |
578
|
|
|
AND id_board = {int:board}', |
579
|
|
|
array( |
580
|
|
|
'id_member' => $user_info['id'], |
581
|
|
|
'unapproved' => 0, |
582
|
|
|
'board' => $board, |
583
|
|
|
) |
584
|
|
|
); |
585
|
|
|
|
586
|
|
|
list ($board_info['unapproved_user_topics']) = $db->fetch_row($request); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
call_integration_hook('integrate_loaded_board', array(&$board_info, &$row)); |
590
|
|
|
|
591
|
|
|
if ($cache->isEnabled() && (empty($topic) || $cache->checkLevel(3))) |
592
|
|
|
{ |
593
|
|
|
// @todo SLOW? |
594
|
|
|
if (!empty($topic)) |
595
|
|
|
$cache->put('topic_board-' . $topic, $board_info, 120); |
596
|
|
|
$cache->put('board-' . $board, $board_info, 120); |
597
|
|
|
} |
598
|
|
|
} |
599
|
|
|
else |
600
|
|
|
{ |
601
|
|
|
// Otherwise the topic is invalid, there are no moderators, etc. |
602
|
|
|
$board_info = array( |
603
|
|
|
'moderators' => array(), |
604
|
|
|
'error' => 'exist' |
605
|
|
|
); |
606
|
|
|
$topic = null; |
607
|
|
|
$board = 0; |
608
|
|
|
} |
609
|
|
|
$db->free_result($request); |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
if (!empty($topic)) |
613
|
|
|
$_GET['board'] = (int) $board; |
614
|
|
|
|
615
|
|
|
if (!empty($board)) |
616
|
|
|
{ |
617
|
|
|
// Now check if the user is a moderator. |
618
|
|
|
$user_info['is_mod'] = isset($board_info['moderators'][$user_info['id']]); |
619
|
|
|
|
620
|
|
View Code Duplication |
if (count(array_intersect($user_info['groups'], $board_info['groups'])) == 0 && !$user_info['is_admin']) |
621
|
|
|
$board_info['error'] = 'access'; |
622
|
|
View Code Duplication |
if (!empty($modSettings['deny_boards_access']) && count(array_intersect($user_info['groups'], $board_info['deny_groups'])) != 0 && !$user_info['is_admin']) |
623
|
|
|
$board_info['error'] = 'access'; |
624
|
|
|
|
625
|
|
|
// Build up the linktree. |
626
|
|
|
$context['linktree'] = array_merge( |
627
|
|
|
$context['linktree'], |
628
|
|
|
array(array( |
629
|
|
|
'url' => $scripturl . '#c' . $board_info['cat']['id'], |
630
|
|
|
'name' => $board_info['cat']['name'] |
631
|
|
|
)), |
632
|
|
|
array_reverse($board_info['parent_boards']), |
633
|
|
|
array(array( |
634
|
|
|
'url' => $scripturl . '?board=' . $board . '.0', |
635
|
|
|
'name' => $board_info['name'] |
636
|
|
|
)) |
637
|
|
|
); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
// Set the template contextual information. |
641
|
|
|
$context['user']['is_mod'] = &$user_info['is_mod']; |
642
|
|
|
$context['user']['is_moderator'] = &$user_info['is_moderator']; |
643
|
|
|
$context['current_topic'] = $topic; |
644
|
|
|
$context['current_board'] = $board; |
645
|
|
|
|
646
|
|
|
// Hacker... you can't see this topic, I'll tell you that. (but moderators can!) |
647
|
|
|
if (!empty($board_info['error']) && (!empty($modSettings['deny_boards_access']) || $board_info['error'] != 'access' || !$user_info['is_moderator'])) |
648
|
|
|
{ |
649
|
|
|
// The permissions and theme need loading, just to make sure everything goes smoothly. |
650
|
|
|
loadPermissions(); |
651
|
|
|
loadTheme(); |
652
|
|
|
|
653
|
|
|
$_GET['board'] = ''; |
654
|
|
|
$_GET['topic'] = ''; |
655
|
|
|
|
656
|
|
|
// The linktree should not give the game away mate! |
657
|
|
|
$context['linktree'] = array( |
658
|
|
|
array( |
659
|
|
|
'url' => $scripturl, |
660
|
|
|
'name' => $context['forum_name_html_safe'] |
661
|
|
|
) |
662
|
|
|
); |
663
|
|
|
|
664
|
|
|
// If it's a prefetching agent, stop it |
665
|
|
|
stop_prefetching(); |
666
|
|
|
|
667
|
|
|
// If we're requesting an attachment. |
668
|
|
|
if (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach') |
|
|
|
|
669
|
|
|
{ |
670
|
|
|
ob_end_clean(); |
671
|
|
|
header('HTTP/1.1 403 Forbidden'); |
672
|
|
|
exit; |
|
|
|
|
673
|
|
|
} |
674
|
|
|
elseif ($user_info['is_guest']) |
675
|
|
|
{ |
676
|
|
|
loadLanguage('Errors'); |
677
|
|
|
is_not_guest($txt['topic_gone']); |
678
|
|
|
} |
679
|
|
|
else |
680
|
|
|
Errors::instance()->fatal_lang_error('topic_gone', false); |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
if ($user_info['is_mod']) |
684
|
|
|
$user_info['groups'][] = 3; |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
/** |
688
|
|
|
* Load this user's permissions. |
689
|
|
|
* |
690
|
|
|
* What it does: |
691
|
|
|
* - If the user is an admin, validate that they have not been banned. |
692
|
|
|
* - Attempt to load permissions from cache for cache level > 2 |
693
|
|
|
* - See if the user is possibly a robot and apply added permissions as needed |
694
|
|
|
* - Load permissions from the general permissions table. |
695
|
|
|
* - If inside a board load the necessary board permissions. |
696
|
|
|
* - If the user is not a guest, identify what other boards they have access to. |
697
|
|
|
*/ |
698
|
|
|
function loadPermissions() |
|
|
|
|
699
|
|
|
{ |
700
|
|
|
global $user_info, $board, $board_info, $modSettings; |
701
|
|
|
|
702
|
|
|
$db = database(); |
703
|
|
|
|
704
|
|
|
if ($user_info['is_admin']) |
705
|
|
|
{ |
706
|
|
|
banPermissions(); |
707
|
|
|
return; |
708
|
|
|
} |
709
|
|
|
|
710
|
|
|
$removals = array(); |
711
|
|
|
|
712
|
|
|
$cache = Cache::instance(); |
713
|
|
|
|
714
|
|
|
if ($cache->isEnabled()) |
715
|
|
|
{ |
716
|
|
|
$cache_groups = $user_info['groups']; |
717
|
|
|
asort($cache_groups); |
718
|
|
|
$cache_groups = implode(',', $cache_groups); |
719
|
|
|
|
720
|
|
|
// If it's a spider then cache it different. |
721
|
|
|
if ($user_info['possibly_robot']) |
722
|
|
|
$cache_groups .= '-spider'; |
723
|
|
|
|
724
|
|
|
if ($cache->checkLevel(2) && !empty($board) && $cache->getVar($temp, 'permissions:' . $cache_groups . ':' . $board, 240) && time() - 240 > $modSettings['settings_updated']) |
725
|
|
|
{ |
726
|
|
|
list ($user_info['permissions']) = $temp; |
|
|
|
|
727
|
|
|
banPermissions(); |
728
|
|
|
|
729
|
|
|
return; |
730
|
|
|
} |
731
|
|
|
elseif ($cache->getVar($temp, 'permissions:' . $cache_groups, 240) && time() - 240 > $modSettings['settings_updated']) |
732
|
|
|
list ($user_info['permissions'], $removals) = $temp; |
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
// If it is detected as a robot, and we are restricting permissions as a special group - then implement this. |
736
|
|
|
$spider_restrict = $user_info['possibly_robot'] && !empty($modSettings['spider_group']) ? ' OR (id_group = {int:spider_group} AND add_deny = 0)' : ''; |
737
|
|
|
|
738
|
|
|
if (empty($user_info['permissions'])) |
739
|
|
|
{ |
740
|
|
|
// Get the general permissions. |
741
|
|
|
$request = $db->query('', ' |
742
|
|
|
SELECT permission, add_deny |
743
|
|
|
FROM {db_prefix}permissions |
744
|
|
|
WHERE id_group IN ({array_int:member_groups}) |
745
|
|
|
' . $spider_restrict, |
746
|
|
|
array( |
747
|
|
|
'member_groups' => $user_info['groups'], |
748
|
|
|
'spider_group' => !empty($modSettings['spider_group']) && $modSettings['spider_group'] != 1 ? $modSettings['spider_group'] : 0, |
749
|
|
|
) |
750
|
|
|
); |
751
|
|
View Code Duplication |
while ($row = $db->fetch_assoc($request)) |
752
|
|
|
{ |
753
|
|
|
if (empty($row['add_deny'])) |
754
|
|
|
$removals[] = $row['permission']; |
755
|
|
|
else |
756
|
|
|
$user_info['permissions'][] = $row['permission']; |
757
|
|
|
} |
758
|
|
|
$db->free_result($request); |
759
|
|
|
|
760
|
|
|
if (isset($cache_groups)) |
761
|
|
|
$cache->put('permissions:' . $cache_groups, array($user_info['permissions'], $removals), 240); |
762
|
|
|
} |
763
|
|
|
|
764
|
|
|
// Get the board permissions. |
765
|
|
|
if (!empty($board)) |
766
|
|
|
{ |
767
|
|
|
// Make sure the board (if any) has been loaded by loadBoard(). |
768
|
|
|
if (!isset($board_info['profile'])) |
769
|
|
|
Errors::instance()->fatal_lang_error('no_board'); |
770
|
|
|
|
771
|
|
|
$request = $db->query('', ' |
772
|
|
|
SELECT permission, add_deny |
773
|
|
|
FROM {db_prefix}board_permissions |
774
|
|
|
WHERE (id_group IN ({array_int:member_groups}) |
775
|
|
|
' . $spider_restrict . ') |
776
|
|
|
AND id_profile = {int:id_profile}', |
777
|
|
|
array( |
778
|
|
|
'member_groups' => $user_info['groups'], |
779
|
|
|
'id_profile' => $board_info['profile'], |
780
|
|
|
'spider_group' => !empty($modSettings['spider_group']) && $modSettings['spider_group'] != 1 ? $modSettings['spider_group'] : 0, |
781
|
|
|
) |
782
|
|
|
); |
783
|
|
View Code Duplication |
while ($row = $db->fetch_assoc($request)) |
784
|
|
|
{ |
785
|
|
|
if (empty($row['add_deny'])) |
786
|
|
|
$removals[] = $row['permission']; |
787
|
|
|
else |
788
|
|
|
$user_info['permissions'][] = $row['permission']; |
789
|
|
|
} |
790
|
|
|
$db->free_result($request); |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
// Remove all the permissions they shouldn't have ;). |
794
|
|
View Code Duplication |
if (!empty($modSettings['permission_enable_deny'])) |
795
|
|
|
$user_info['permissions'] = array_diff($user_info['permissions'], $removals); |
796
|
|
|
|
797
|
|
|
if (isset($cache_groups) && !empty($board) && $cache->checkLevel(2)) |
798
|
|
|
$cache->put('permissions:' . $cache_groups . ':' . $board, array($user_info['permissions'], null), 240); |
799
|
|
|
|
800
|
|
|
// Banned? Watch, don't touch.. |
801
|
|
|
banPermissions(); |
802
|
|
|
|
803
|
|
|
// Load the mod cache so we can know what additional boards they should see, but no sense in doing it for guests |
804
|
|
|
if (!$user_info['is_guest']) |
805
|
|
|
{ |
806
|
|
|
$user_info['is_moderator'] = $user_info['is_mod'] || allowedTo('moderate_board'); |
807
|
|
|
if (!isset($_SESSION['mc']) || $_SESSION['mc']['time'] <= $modSettings['settings_updated']) |
808
|
|
|
{ |
809
|
|
|
require_once(SUBSDIR . '/Auth.subs.php'); |
810
|
|
|
rebuildModCache(); |
811
|
|
|
} |
812
|
|
|
else |
813
|
|
|
$user_info['mod_cache'] = $_SESSION['mc']; |
814
|
|
|
} |
815
|
|
|
} |
816
|
|
|
|
817
|
|
|
/** |
818
|
|
|
* Loads an array of users' data by ID or member_name. |
819
|
|
|
* |
820
|
|
|
* @param int[]|int|string[]|string $users An array of users by id or name |
821
|
|
|
* @param bool $is_name = false $users is by name or by id |
822
|
|
|
* @param string $set = 'normal' What kind of data to load (normal, profile, minimal) |
823
|
|
|
* @return array|bool The ids of the members loaded or false |
824
|
|
|
*/ |
825
|
|
|
function loadMemberData($users, $is_name = false, $set = 'normal') |
826
|
|
|
{ |
827
|
1 |
|
global $user_profile, $modSettings, $board_info, $context; |
828
|
|
|
|
829
|
1 |
|
$db = database(); |
830
|
1 |
|
$cache = Cache::instance(); |
831
|
|
|
|
832
|
|
|
// Can't just look for no users :P. |
833
|
1 |
|
if (empty($users)) |
834
|
1 |
|
return false; |
835
|
|
|
|
836
|
|
|
// Pass the set value |
837
|
1 |
|
$context['loadMemberContext_set'] = $set; |
838
|
|
|
|
839
|
|
|
// Make sure it's an array. |
840
|
1 |
|
$users = !is_array($users) ? array($users) : array_unique($users); |
841
|
1 |
|
$loaded_ids = array(); |
842
|
|
|
|
843
|
1 |
|
if (!$is_name && $cache->isEnabled() && $cache->checkLevel(3)) |
844
|
1 |
|
{ |
845
|
|
|
$users = array_values($users); |
846
|
|
|
for ($i = 0, $n = count($users); $i < $n; $i++) |
847
|
|
|
{ |
848
|
|
|
$data = $cache->get('member_data-' . $set . '-' . $users[$i], 240); |
849
|
|
|
if ($cache->isMiss()) |
850
|
|
|
continue; |
851
|
|
|
|
852
|
|
|
$loaded_ids[] = $data['id_member']; |
853
|
|
|
$user_profile[$data['id_member']] = $data; |
854
|
|
|
unset($users[$i]); |
855
|
|
|
} |
856
|
|
|
} |
857
|
|
|
|
858
|
|
|
// Used by default |
859
|
|
|
$select_columns = ' |
860
|
|
|
IFNULL(lo.log_time, 0) AS is_online, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type, |
861
|
|
|
mem.signature, mem.avatar, mem.id_member, mem.member_name, |
862
|
|
|
mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, mem.website_title, mem.website_url, |
863
|
|
|
mem.birthdate, mem.member_ip, mem.member_ip2, mem.posts, mem.last_login, mem.likes_given, mem.likes_received, |
864
|
|
|
mem.karma_good, mem.id_post_group, mem.karma_bad, mem.lngfile, mem.id_group, mem.time_offset, mem.show_online, |
865
|
|
|
mg.online_color AS member_group_color, IFNULL(mg.group_name, {string:blank_string}) AS member_group, |
866
|
|
|
pg.online_color AS post_group_color, IFNULL(pg.group_name, {string:blank_string}) AS post_group, |
867
|
1 |
|
mem.is_activated, mem.warning, ' . (!empty($modSettings['titlesEnable']) ? 'mem.usertitle, ' : '') . ' |
868
|
1 |
|
CASE WHEN mem.id_group = 0 OR mg.icons = {string:blank_string} THEN pg.icons ELSE mg.icons END AS icons'; |
869
|
|
|
$select_tables = ' |
870
|
|
|
LEFT JOIN {db_prefix}log_online AS lo ON (lo.id_member = mem.id_member) |
871
|
|
|
LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = mem.id_member) |
872
|
|
|
LEFT JOIN {db_prefix}membergroups AS pg ON (pg.id_group = mem.id_post_group) |
873
|
1 |
|
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)'; |
874
|
|
|
|
875
|
|
|
// We add or replace according to the set |
876
|
|
|
switch ($set) |
877
|
|
|
{ |
878
|
1 |
|
case 'normal': |
879
|
|
|
$select_columns .= ', mem.buddy_list'; |
880
|
|
|
break; |
881
|
1 |
|
case 'profile': |
882
|
|
|
$select_columns .= ', mem.openid_uri, mem.id_theme, mem.pm_ignore_list, mem.pm_email_notify, mem.receive_from, |
883
|
|
|
mem.time_format, mem.secret_question, mem.additional_groups, mem.smiley_set, |
884
|
|
|
mem.total_time_logged_in, mem.notify_announcements, mem.notify_regularity, mem.notify_send_body, |
885
|
1 |
|
mem.notify_types, lo.url, mem.ignore_boards, mem.password_salt, mem.pm_prefs, mem.buddy_list, mem.otp_secret, mem.enable_otp'; |
886
|
1 |
|
break; |
887
|
|
|
case 'minimal': |
888
|
|
|
$select_columns = ' |
889
|
|
|
mem.id_member, mem.member_name, mem.real_name, mem.email_address, mem.hide_email, mem.date_registered, |
890
|
|
|
mem.posts, mem.last_login, mem.member_ip, mem.member_ip2, mem.lngfile, mem.id_group'; |
891
|
|
|
$select_tables = ''; |
892
|
|
|
break; |
893
|
|
|
default: |
894
|
|
|
trigger_error('loadMemberData(): Invalid member data set \'' . $set . '\'', E_USER_WARNING); |
895
|
|
|
} |
896
|
|
|
|
897
|
|
|
// Allow addons to easily add to the selected member data |
898
|
1 |
|
call_integration_hook('integrate_load_member_data', array(&$select_columns, &$select_tables, $set)); |
899
|
|
|
|
900
|
1 |
|
if (!empty($users)) |
901
|
1 |
|
{ |
902
|
|
|
// Load the member's data. |
903
|
1 |
|
$request = $db->query('', ' |
904
|
1 |
|
SELECT' . $select_columns . ' |
905
|
1 |
|
FROM {db_prefix}members AS mem' . $select_tables . ' |
906
|
1 |
|
WHERE mem.' . ($is_name ? 'member_name' : 'id_member') . (count($users) == 1 ? ' = {' . ($is_name ? 'string' : 'int') . ':users}' : ' IN ({' . ($is_name ? 'array_string' : 'array_int') . ':users})'), |
907
|
|
|
array( |
908
|
1 |
|
'blank_string' => '', |
909
|
1 |
|
'users' => count($users) == 1 ? current($users) : $users, |
910
|
|
|
) |
911
|
1 |
|
); |
912
|
1 |
|
$new_loaded_ids = array(); |
913
|
1 |
|
while ($row = $db->fetch_assoc($request)) |
914
|
|
|
{ |
915
|
1 |
|
$new_loaded_ids[] = $row['id_member']; |
916
|
1 |
|
$loaded_ids[] = $row['id_member']; |
917
|
1 |
|
$row['options'] = array(); |
918
|
1 |
|
$user_profile[$row['id_member']] = $row; |
919
|
1 |
|
} |
920
|
1 |
|
$db->free_result($request); |
921
|
1 |
|
} |
922
|
|
|
|
923
|
|
|
// Custom profile fields as well |
924
|
1 |
|
if (!empty($new_loaded_ids) && $set !== 'minimal' && (in_array('cp', $context['admin_features']))) |
925
|
1 |
|
{ |
926
|
|
|
$request = $db->query('', ' |
927
|
|
|
SELECT id_member, variable, value |
928
|
|
|
FROM {db_prefix}custom_fields_data |
929
|
|
|
WHERE id_member' . (count($new_loaded_ids) == 1 ? ' = {int:loaded_ids}' : ' IN ({array_int:loaded_ids})'), |
930
|
|
|
array( |
931
|
|
|
'loaded_ids' => count($new_loaded_ids) == 1 ? $new_loaded_ids[0] : $new_loaded_ids, |
932
|
|
|
) |
933
|
|
|
); |
934
|
|
|
while ($row = $db->fetch_assoc($request)) |
935
|
|
|
$user_profile[$row['id_member']]['options'][$row['variable']] = $row['value']; |
936
|
|
|
$db->free_result($request); |
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
// Anything else integration may want to add to the user_profile array |
940
|
1 |
|
if (!empty($new_loaded_ids)) |
941
|
1 |
|
call_integration_hook('integrate_add_member_data', array($new_loaded_ids, $set)); |
942
|
|
|
|
943
|
1 |
|
if (!empty($new_loaded_ids) && $cache->checkLevel(3)) |
944
|
1 |
|
{ |
945
|
|
|
for ($i = 0, $n = count($new_loaded_ids); $i < $n; $i++) |
946
|
|
|
$cache->put('member_data-' . $set . '-' . $new_loaded_ids[$i], $user_profile[$new_loaded_ids[$i]], 240); |
947
|
|
|
} |
948
|
|
|
|
949
|
|
|
// Are we loading any moderators? If so, fix their group data... |
950
|
1 |
|
if (!empty($loaded_ids) && !empty($board_info['moderators']) && $set === 'normal' && count($temp_mods = array_intersect($loaded_ids, array_keys($board_info['moderators']))) !== 0) |
951
|
1 |
|
{ |
952
|
|
|
if (!$cache->getVar($group_info, 'moderator_group_info', 480)) |
|
|
|
|
953
|
|
|
{ |
954
|
|
|
require_once(SUBSDIR . '/Membergroups.subs.php'); |
955
|
|
|
$group_info = membergroupById(3, true); |
956
|
|
|
|
957
|
|
|
$cache->put('moderator_group_info', $group_info, 480); |
958
|
|
|
} |
959
|
|
|
|
960
|
|
|
foreach ($temp_mods as $id) |
961
|
|
|
{ |
962
|
|
|
// By popular demand, don't show admins or global moderators as moderators. |
963
|
|
|
if ($user_profile[$id]['id_group'] != 1 && $user_profile[$id]['id_group'] != 2) |
964
|
|
|
$user_profile[$id]['member_group'] = $group_info['group_name']; |
|
|
|
|
965
|
|
|
|
966
|
|
|
// If the Moderator group has no color or icons, but their group does... don't overwrite. |
967
|
|
|
if (!empty($group_info['icons'])) |
968
|
|
|
$user_profile[$id]['icons'] = $group_info['icons']; |
969
|
|
|
if (!empty($group_info['online_color'])) |
970
|
|
|
$user_profile[$id]['member_group_color'] = $group_info['online_color']; |
971
|
|
|
} |
972
|
|
|
} |
973
|
|
|
|
974
|
1 |
|
return empty($loaded_ids) ? false : $loaded_ids; |
975
|
|
|
} |
976
|
|
|
|
977
|
|
|
/** |
978
|
|
|
* Loads the user's basic values... meant for template/theme usage. |
979
|
|
|
* |
980
|
|
|
* What it does: |
981
|
|
|
* - Always loads the minimal values of username, name, id, href, link, email, show_email, registered, registered_timestamp |
982
|
|
|
* - if $context['loadMemberContext_set'] is not minimal it will load in full a full set of user information |
983
|
|
|
* - prepares signature for display (censoring if enabled) |
984
|
|
|
* - loads in the members custom fields if any |
985
|
|
|
* - prepares the users buddy list, including reverse buddy flags |
986
|
|
|
* |
987
|
|
|
* @param int $user |
988
|
|
|
* @param bool $display_custom_fields = false |
989
|
|
|
* @return boolean |
990
|
|
|
*/ |
991
|
|
|
function loadMemberContext($user, $display_custom_fields = false) |
992
|
|
|
{ |
993
|
|
|
global $memberContext, $user_profile, $txt, $scripturl, $user_info; |
994
|
|
|
global $context, $modSettings, $settings; |
995
|
|
|
static $dataLoaded = array(); |
996
|
|
|
|
997
|
|
|
// If this person's data is already loaded, skip it. |
998
|
|
|
if (isset($dataLoaded[$user])) |
999
|
|
|
return true; |
1000
|
|
|
|
1001
|
|
|
// We can't load guests or members not loaded by loadMemberData()! |
1002
|
|
|
if ($user == 0) |
1003
|
|
|
return false; |
1004
|
|
|
|
1005
|
|
|
if (!isset($user_profile[$user])) |
1006
|
|
|
{ |
1007
|
|
|
trigger_error('loadMemberContext(): member id ' . $user . ' not previously loaded by loadMemberData()', E_USER_WARNING); |
1008
|
|
|
return false; |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
$parsers = \BBC\ParserWrapper::getInstance(); |
1012
|
|
|
|
1013
|
|
|
// Well, it's loaded now anyhow. |
1014
|
|
|
$dataLoaded[$user] = true; |
1015
|
|
|
$profile = $user_profile[$user]; |
1016
|
|
|
|
1017
|
|
|
// Censor everything. |
1018
|
|
|
$profile['signature'] = censor($profile['signature']); |
1019
|
|
|
|
1020
|
|
|
// TODO: We should look into a censoring toggle for custom fields |
1021
|
|
|
|
1022
|
|
|
// Set things up to be used before hand. |
1023
|
|
|
$profile['signature'] = str_replace(array("\n", "\r"), array('<br />', ''), $profile['signature']); |
1024
|
|
|
$profile['signature'] = $parsers->parseSignature($profile['signature'], true); |
1025
|
|
|
$profile['is_online'] = (!empty($profile['show_online']) || allowedTo('moderate_forum')) && $profile['is_online'] > 0; |
1026
|
|
|
$profile['icons'] = empty($profile['icons']) ? array('', '') : explode('#', $profile['icons']); |
1027
|
|
|
|
1028
|
|
|
// Setup the buddy status here (One whole in_array call saved :P) |
1029
|
|
|
$profile['buddy'] = in_array($profile['id_member'], $user_info['buddies']); |
1030
|
|
|
$buddy_list = !empty($profile['buddy_list']) ? explode(',', $profile['buddy_list']) : array(); |
1031
|
|
|
|
1032
|
|
|
// These minimal values are always loaded |
1033
|
|
|
$memberContext[$user] = array( |
1034
|
|
|
'username' => $profile['member_name'], |
1035
|
|
|
'name' => $profile['real_name'], |
1036
|
|
|
'id' => $profile['id_member'], |
1037
|
|
|
'href' => $scripturl . '?action=profile;u=' . $profile['id_member'], |
1038
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $profile['id_member'] . '" title="' . $txt['profile_of'] . ' ' . trim($profile['real_name']) . '">' . $profile['real_name'] . '</a>', |
1039
|
|
|
'email' => $profile['email_address'], |
1040
|
|
|
'show_email' => showEmailAddress(!empty($profile['hide_email']), $profile['id_member']), |
1041
|
|
|
'registered' => empty($profile['date_registered']) ? $txt['not_applicable'] : standardTime($profile['date_registered']), |
1042
|
|
|
'registered_timestamp' => empty($profile['date_registered']) ? 0 : forum_time(true, $profile['date_registered']), |
1043
|
|
|
); |
1044
|
|
|
|
1045
|
|
|
// If the set isn't minimal then load the monstrous array. |
1046
|
|
|
if ($context['loadMemberContext_set'] !== 'minimal') |
1047
|
|
|
{ |
1048
|
|
|
$memberContext[$user] += array( |
1049
|
|
|
'username_color' => '<span '. (!empty($profile['member_group_color']) ? 'style="color:' . $profile['member_group_color'] .';"' : '') . '>' . $profile['member_name'] .'</span>', |
1050
|
|
|
'name_color' => '<span '. (!empty($profile['member_group_color']) ? 'style="color:' . $profile['member_group_color'] .';"' : '') . '>' . $profile['real_name'] .'</span>', |
1051
|
|
|
'link_color' => '<a href="' . $scripturl . '?action=profile;u=' . $profile['id_member'] . '" title="' . $txt['profile_of'] . ' ' . $profile['real_name'] . '" ' . (!empty($profile['member_group_color']) ? 'style="color:' . $profile['member_group_color'] . ';"' : '') . '>' . $profile['real_name'] . '</a>', |
1052
|
|
|
'is_buddy' => $profile['buddy'], |
1053
|
|
|
'is_reverse_buddy' => in_array($user_info['id'], $buddy_list), |
1054
|
|
|
'buddies' => $buddy_list, |
1055
|
|
|
'title' => !empty($modSettings['titlesEnable']) ? $profile['usertitle'] : '', |
1056
|
|
|
'website' => array( |
1057
|
|
|
'title' => $profile['website_title'], |
1058
|
|
|
'url' => $profile['website_url'], |
1059
|
|
|
), |
1060
|
|
|
'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']), |
1061
|
|
|
'signature' => $profile['signature'], |
1062
|
|
|
'real_posts' => $profile['posts'], |
1063
|
|
|
'posts' => comma_format($profile['posts']), |
1064
|
|
|
'avatar' => determineAvatar($profile), |
1065
|
|
|
'last_login' => empty($profile['last_login']) ? $txt['never'] : standardTime($profile['last_login']), |
1066
|
|
|
'last_login_timestamp' => empty($profile['last_login']) ? 0 : forum_time(false, $profile['last_login']), |
1067
|
|
|
'karma' => array( |
1068
|
|
|
'good' => $profile['karma_good'], |
1069
|
|
|
'bad' => $profile['karma_bad'], |
1070
|
|
|
'allow' => !$user_info['is_guest'] && !empty($modSettings['karmaMode']) && $user_info['id'] != $user && allowedTo('karma_edit') && |
1071
|
|
|
($user_info['posts'] >= $modSettings['karmaMinPosts'] || $user_info['is_admin']), |
1072
|
|
|
), |
1073
|
|
|
'likes' => array( |
1074
|
|
|
'given' => $profile['likes_given'], |
1075
|
|
|
'received' => $profile['likes_received'] |
1076
|
|
|
), |
1077
|
|
|
'ip' => htmlspecialchars($profile['member_ip'], ENT_COMPAT, 'UTF-8'), |
1078
|
|
|
'ip2' => htmlspecialchars($profile['member_ip2'], ENT_COMPAT, 'UTF-8'), |
1079
|
|
|
'online' => array( |
1080
|
|
|
'is_online' => $profile['is_online'], |
1081
|
|
|
'text' => Util::htmlspecialchars($txt[$profile['is_online'] ? 'online' : 'offline']), |
1082
|
|
|
'member_online_text' => sprintf($txt[$profile['is_online'] ? 'member_is_online' : 'member_is_offline'], Util::htmlspecialchars($profile['real_name'])), |
1083
|
|
|
'href' => $scripturl . '?action=pm;sa=send;u=' . $profile['id_member'], |
1084
|
|
|
'link' => '<a href="' . $scripturl . '?action=pm;sa=send;u=' . $profile['id_member'] . '">' . $txt[$profile['is_online'] ? 'online' : 'offline'] . '</a>', |
1085
|
|
|
'image_href' => $settings['images_url'] . '/profile/' . ($profile['buddy'] ? 'buddy_' : '') . ($profile['is_online'] ? 'useron' : 'useroff') . '.png', |
1086
|
|
|
'label' => $txt[$profile['is_online'] ? 'online' : 'offline'] |
1087
|
|
|
), |
1088
|
|
|
'language' => Util::ucwords(strtr($profile['lngfile'], array('_' => ' '))), |
1089
|
|
|
'is_activated' => isset($profile['is_activated']) ? $profile['is_activated'] : 1, |
1090
|
|
|
'is_banned' => isset($profile['is_activated']) ? $profile['is_activated'] >= 10 : 0, |
1091
|
|
|
'options' => $profile['options'], |
1092
|
|
|
'is_guest' => false, |
1093
|
|
|
'group' => $profile['member_group'], |
1094
|
|
|
'group_color' => $profile['member_group_color'], |
1095
|
|
|
'group_id' => $profile['id_group'], |
1096
|
|
|
'post_group' => $profile['post_group'], |
1097
|
|
|
'post_group_color' => $profile['post_group_color'], |
1098
|
|
|
'group_icons' => str_repeat('<img src="' . str_replace('$language', $context['user']['language'], isset($profile['icons'][1]) ? $settings['images_url'] . '/group_icons/' . $profile['icons'][1] : '') . '" alt="[*]" />', empty($profile['icons'][0]) || empty($profile['icons'][1]) ? 0 : $profile['icons'][0]), |
1099
|
|
|
'warning' => $profile['warning'], |
1100
|
|
|
'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' : (''))), |
1101
|
|
|
'local_time' => standardTime(time() + ($profile['time_offset'] - $user_info['time_offset']) * 3600, false), |
1102
|
|
|
'custom_fields' => array(), |
1103
|
|
|
); |
1104
|
|
|
} |
1105
|
|
|
|
1106
|
|
|
// Are we also loading the members custom fields into context? |
1107
|
|
|
if ($display_custom_fields && !empty($modSettings['displayFields'])) |
1108
|
|
|
{ |
1109
|
|
|
if (!isset($context['display_fields'])) |
1110
|
|
|
$context['display_fields'] = unserialize($modSettings['displayFields']); |
1111
|
|
|
|
1112
|
|
|
foreach ($context['display_fields'] as $custom) |
1113
|
|
|
{ |
1114
|
|
|
if (!isset($custom['title']) || trim($custom['title']) == '' || empty($profile['options'][$custom['colname']])) |
1115
|
|
|
continue; |
1116
|
|
|
|
1117
|
|
|
$value = $profile['options'][$custom['colname']]; |
1118
|
|
|
|
1119
|
|
|
// BBC? |
1120
|
|
|
if ($custom['bbc']) |
1121
|
|
|
$value = $parsers->parseCustomFields($value); |
1122
|
|
|
// ... or checkbox? |
|
|
|
|
1123
|
|
|
elseif (isset($custom['type']) && $custom['type'] == 'check') |
1124
|
|
|
$value = $value ? $txt['yes'] : $txt['no']; |
1125
|
|
|
|
1126
|
|
|
// Enclosing the user input within some other text? |
1127
|
|
View Code Duplication |
if (!empty($custom['enclose'])) |
1128
|
|
|
$value = strtr($custom['enclose'], array( |
1129
|
|
|
'{SCRIPTURL}' => $scripturl, |
1130
|
|
|
'{IMAGES_URL}' => $settings['images_url'], |
1131
|
|
|
'{DEFAULT_IMAGES_URL}' => $settings['default_images_url'], |
1132
|
|
|
'{INPUT}' => $value, |
1133
|
|
|
)); |
1134
|
|
|
|
1135
|
|
|
$memberContext[$user]['custom_fields'][] = array( |
1136
|
|
|
'title' => $custom['title'], |
1137
|
|
|
'colname' => $custom['colname'], |
1138
|
|
|
'value' => $value, |
1139
|
|
|
'placement' => !empty($custom['placement']) ? $custom['placement'] : 0, |
1140
|
|
|
); |
1141
|
|
|
} |
1142
|
|
|
} |
1143
|
|
|
|
1144
|
|
|
call_integration_hook('integrate_member_context', array($user, $display_custom_fields)); |
1145
|
|
|
return true; |
1146
|
|
|
} |
1147
|
|
|
|
1148
|
|
|
/** |
1149
|
|
|
* Loads information about what browser the user is viewing with and places it in $context |
1150
|
|
|
* |
1151
|
|
|
* @uses the class from BrowserDetect.class.php |
1152
|
|
|
*/ |
1153
|
|
|
function detectBrowser() |
1154
|
|
|
{ |
1155
|
|
|
// Load the current user's browser of choice |
1156
|
1 |
|
$detector = new Browser_Detector; |
1157
|
1 |
|
$detector->detectBrowser(); |
1158
|
1 |
|
} |
1159
|
|
|
|
1160
|
|
|
/** |
1161
|
|
|
* Get the id of a theme |
1162
|
|
|
* |
1163
|
|
|
* @param int $id_theme |
1164
|
|
|
* @return int |
1165
|
|
|
*/ |
1166
|
|
|
function getThemeId($id_theme = 0) |
|
|
|
|
1167
|
|
|
{ |
1168
|
1 |
|
global $modSettings, $user_info, $board_info, $ssi_theme; |
1169
|
|
|
|
1170
|
|
|
// The theme was specified by parameter. |
1171
|
1 |
|
if (!empty($id_theme)) |
1172
|
1 |
|
$id_theme = (int) $id_theme; |
1173
|
|
|
// The theme was specified by REQUEST. |
1174
|
1 |
View Code Duplication |
elseif (!empty($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) |
1175
|
|
|
{ |
1176
|
|
|
$id_theme = (int) $_REQUEST['theme']; |
1177
|
|
|
$_SESSION['id_theme'] = $id_theme; |
1178
|
|
|
} |
1179
|
|
|
// The theme was specified by REQUEST... previously. |
1180
|
1 |
View Code Duplication |
elseif (!empty($_SESSION['id_theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) |
1181
|
|
|
$id_theme = (int) $_SESSION['id_theme']; |
1182
|
|
|
// The theme is just the user's choice. (might use ?board=1;theme=0 to force board theme.) |
1183
|
1 |
View Code Duplication |
elseif (!empty($user_info['theme']) && !isset($_REQUEST['theme']) && (!empty($modSettings['theme_allow']) || allowedTo('admin_forum'))) |
1184
|
|
|
$id_theme = $user_info['theme']; |
1185
|
|
|
// The theme was specified by the board. |
1186
|
1 |
|
elseif (!empty($board_info['theme'])) |
1187
|
|
|
$id_theme = $board_info['theme']; |
1188
|
|
|
// The theme is the forum's default. |
1189
|
|
|
else |
1190
|
1 |
|
$id_theme = $modSettings['theme_guests']; |
1191
|
|
|
|
1192
|
|
|
// Verify the id_theme... no foul play. |
1193
|
|
|
// Always allow the board specific theme, if they are overriding. |
1194
|
1 |
|
if (!empty($board_info['theme']) && $board_info['override_theme']) |
1195
|
1 |
|
$id_theme = $board_info['theme']; |
1196
|
|
|
// If they have specified a particular theme to use with SSI allow it to be used. |
1197
|
1 |
|
elseif (!empty($ssi_theme) && $id_theme == $ssi_theme) |
1198
|
|
|
$id_theme = (int) $id_theme; |
1199
|
1 |
View Code Duplication |
elseif (!empty($modSettings['knownThemes']) && !allowedTo('admin_forum')) |
1200
|
|
|
{ |
1201
|
1 |
|
$themes = explode(',', $modSettings['knownThemes']); |
1202
|
1 |
|
if (!in_array($id_theme, $themes)) |
1203
|
1 |
|
$id_theme = $modSettings['theme_guests']; |
1204
|
|
|
else |
1205
|
1 |
|
$id_theme = (int) $id_theme; |
1206
|
1 |
|
} |
1207
|
|
|
else |
1208
|
|
|
$id_theme = (int) $id_theme; |
1209
|
|
|
|
1210
|
1 |
|
return $id_theme; |
1211
|
|
|
} |
1212
|
|
|
|
1213
|
|
|
/** |
1214
|
|
|
* Load in the theme variables for a given theme / member combination |
1215
|
|
|
* |
1216
|
|
|
* @param int $id_theme |
1217
|
|
|
* @param int $member |
1218
|
|
|
* |
1219
|
|
|
* @return array |
1220
|
|
|
*/ |
1221
|
|
|
function getThemeData($id_theme, $member) |
1222
|
|
|
{ |
1223
|
1 |
|
global $modSettings; |
1224
|
|
|
|
1225
|
1 |
|
$cache = Cache::instance(); |
1226
|
|
|
|
1227
|
|
|
// Do we already have this members theme data and specific options loaded (for aggressive cache settings) |
1228
|
1 |
|
if ($cache->checkLevel(2) && $cache->getVar($temp, 'theme_settings-' . $id_theme . ':' . $member, 60) && time() - 60 > $modSettings['settings_updated']) |
1229
|
1 |
|
{ |
1230
|
|
|
$themeData = $temp; |
|
|
|
|
1231
|
|
|
$flag = true; |
1232
|
|
|
} |
1233
|
|
|
// Or do we just have the system wide theme settings cached |
1234
|
1 |
|
elseif ($cache->getVar($temp, 'theme_settings-' . $id_theme, 90) && time() - 60 > $modSettings['settings_updated']) |
1235
|
|
|
$themeData = $temp + array($member => array()); |
1236
|
|
|
// Nothing at all then |
1237
|
|
|
else |
1238
|
1 |
|
$themeData = array(-1 => array(), 0 => array(), $member => array()); |
1239
|
|
|
|
1240
|
1 |
|
if (empty($flag)) |
1241
|
1 |
|
{ |
1242
|
1 |
|
$db = database(); |
1243
|
|
|
|
1244
|
|
|
// Load variables from the current or default theme, global or this user's. |
1245
|
1 |
|
$result = $db->query('', ' |
1246
|
|
|
SELECT variable, value, id_member, id_theme |
1247
|
|
|
FROM {db_prefix}themes |
1248
|
1 |
|
WHERE id_member' . (empty($themeData[0]) ? ' IN (-1, 0, {int:id_member})' : ' = {int:id_member}') . ' |
1249
|
1 |
|
AND id_theme' . ($id_theme == 1 ? ' = {int:id_theme}' : ' IN ({int:id_theme}, 1)'), |
1250
|
|
|
array( |
1251
|
1 |
|
'id_theme' => $id_theme, |
1252
|
1 |
|
'id_member' => $member, |
1253
|
|
|
) |
1254
|
1 |
|
); |
1255
|
|
|
|
1256
|
1 |
|
$immutable_theme_data = 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'); |
1257
|
|
|
|
1258
|
|
|
// Pick between $settings and $options depending on whose data it is. |
1259
|
1 |
|
while ($row = $db->fetch_assoc($result)) |
1260
|
|
|
{ |
1261
|
|
|
// There are just things we shouldn't be able to change as members. |
1262
|
1 |
|
if ($row['id_member'] != 0 && in_array($row['variable'], $immutable_theme_data)) |
1263
|
1 |
|
continue; |
1264
|
|
|
|
1265
|
|
|
// If this is the theme_dir of the default theme, store it. |
1266
|
1 |
|
if (in_array($row['variable'], array('theme_dir', 'theme_url', 'images_url')) && $row['id_theme'] == '1' && empty($row['id_member'])) |
1267
|
1 |
|
$themeData[0]['default_' . $row['variable']] = $row['value']; |
1268
|
|
|
|
1269
|
|
|
// If this isn't set yet, is a theme option, or is not the default theme.. |
1270
|
1 |
|
if (!isset($themeData[$row['id_member']][$row['variable']]) || $row['id_theme'] != '1') |
1271
|
1 |
|
$themeData[$row['id_member']][$row['variable']] = substr($row['variable'], 0, 5) == 'show_' ? $row['value'] == '1' : $row['value']; |
1272
|
1 |
|
} |
1273
|
1 |
|
$db->free_result($result); |
1274
|
|
|
|
1275
|
|
|
// Set the defaults if the user has not chosen on their own |
1276
|
1 |
|
if (!empty($themeData[-1])) |
1277
|
1 |
|
{ |
1278
|
1 |
|
foreach ($themeData[-1] as $k => $v) |
1279
|
|
|
{ |
1280
|
1 |
|
if (!isset($themeData[$member][$k])) |
1281
|
1 |
|
$themeData[$member][$k] = $v; |
1282
|
1 |
|
} |
1283
|
1 |
|
} |
1284
|
|
|
|
1285
|
|
|
// If being aggressive we save the site wide and member theme settings |
1286
|
1 |
|
if ($cache->checkLevel(2)) |
1287
|
1 |
|
$cache->put('theme_settings-' . $id_theme . ':' . $member, $themeData, 60); |
1288
|
|
|
// Only if we didn't already load that part of the cache... |
1289
|
1 |
|
elseif (!isset($temp)) |
1290
|
1 |
|
$cache->put('theme_settings-' . $id_theme, array(-1 => $themeData[-1], 0 => $themeData[0]), 90); |
1291
|
1 |
|
} |
1292
|
|
|
|
1293
|
1 |
|
return $themeData; |
1294
|
|
|
} |
1295
|
|
|
|
1296
|
|
|
/** |
1297
|
|
|
* Initialize a theme for use |
1298
|
|
|
* |
1299
|
|
|
* @param int $id_theme |
1300
|
|
|
*/ |
1301
|
|
|
function initTheme($id_theme = 0) |
1302
|
|
|
{ |
1303
|
1 |
|
global $user_info, $settings, $options, $context; |
1304
|
|
|
|
1305
|
|
|
// Validate / fetch the themes id |
1306
|
1 |
|
$id_theme = getThemeId($id_theme); |
1307
|
|
|
|
1308
|
|
|
// Need to know who we are loading the theme for |
1309
|
1 |
|
$member = empty($user_info['id']) ? -1 : $user_info['id']; |
1310
|
|
|
|
1311
|
|
|
// Load in the theme variables for them |
1312
|
1 |
|
$themeData = getThemeData($id_theme, $member); |
1313
|
|
|
|
1314
|
1 |
|
$settings = $themeData[0]; |
1315
|
1 |
|
$options = $themeData[$member]; |
1316
|
|
|
|
1317
|
1 |
|
$settings['theme_id'] = $id_theme; |
1318
|
1 |
|
$settings['actual_theme_url'] = $settings['theme_url']; |
1319
|
1 |
|
$settings['actual_images_url'] = $settings['images_url']; |
1320
|
1 |
|
$settings['actual_theme_dir'] = $settings['theme_dir']; |
1321
|
|
|
|
1322
|
|
|
// Reload the templates |
1323
|
1 |
|
Templates::getInstance()->reloadDirectories($settings); |
1324
|
|
|
|
1325
|
|
|
// Setup the default theme file. In the future, this won't exist and themes will just have to extend it if they want |
1326
|
1 |
|
require_once($settings['default_theme_dir'] . '/Theme.php'); |
1327
|
1 |
|
$context['default_theme_instance'] = new \Themes\DefaultTheme\Theme(1); |
1328
|
|
|
|
1329
|
|
|
// Check if there is a Theme file |
1330
|
1 |
|
if ($id_theme != 1 && !empty($settings['theme_dir']) && file_exists($settings['theme_dir'] . '/Theme.php')) |
1331
|
1 |
|
{ |
1332
|
|
|
require_once($settings['theme_dir'] . '/Theme.php'); |
1333
|
|
|
|
1334
|
|
|
$class = '\\Themes\\' . basename($settings['theme_dir']) . '\\Theme'; |
1335
|
|
|
|
1336
|
|
|
$theme = new $class($id_theme); |
1337
|
|
|
|
1338
|
|
|
$context['theme_instance'] = $theme; |
1339
|
|
|
} |
1340
|
|
|
else |
1341
|
|
|
{ |
1342
|
1 |
|
$context['theme_instance'] = $context['default_theme_instance']; |
1343
|
|
|
} |
1344
|
1 |
|
} |
1345
|
|
|
|
1346
|
|
|
/** |
1347
|
|
|
* Load a theme, by ID. |
1348
|
|
|
* |
1349
|
|
|
* What it does: |
1350
|
|
|
* - identify the theme to be loaded. |
1351
|
|
|
* - validate that the theme is valid and that the user has permission to use it |
1352
|
|
|
* - load the users theme settings and site settings into $options. |
1353
|
|
|
* - prepares the list of folders to search for template loading. |
1354
|
|
|
* - identify what smiley set to use. |
1355
|
|
|
* - sets up $context['user'] |
1356
|
|
|
* - detects the users browser and sets a mobile friendly environment if needed |
1357
|
|
|
* - loads default JS variables for use in every theme |
1358
|
|
|
* - loads default JS scripts for use in every theme |
1359
|
|
|
* |
1360
|
|
|
* @param int $id_theme = 0 |
1361
|
|
|
* @param bool $initialize = true |
1362
|
|
|
*/ |
1363
|
|
|
function loadTheme($id_theme = 0, $initialize = true) |
|
|
|
|
1364
|
|
|
{ |
1365
|
1 |
|
global $user_info, $user_settings; |
1366
|
1 |
|
global $txt, $scripturl, $mbname, $modSettings; |
1367
|
1 |
|
global $context, $settings, $options; |
1368
|
|
|
|
1369
|
1 |
|
initTheme($id_theme); |
1370
|
|
|
|
1371
|
1 |
|
if (!$initialize) |
1372
|
1 |
|
return; |
1373
|
|
|
|
1374
|
1 |
|
loadThemeUrls(); |
1375
|
|
|
|
1376
|
1 |
|
loadUserContext(); |
1377
|
|
|
|
1378
|
|
|
// Set up some additional interface preference context |
1379
|
1 |
|
$context['admin_preferences'] = !empty($options['admin_preferences']) ? unserialize($options['admin_preferences']) : array(); |
1380
|
|
|
|
1381
|
1 |
|
if (!$user_info['is_guest']) |
1382
|
1 |
|
$context['minmax_preferences'] = !empty($options['minmax_preferences']) ? unserialize($options['minmax_preferences']) : array(); |
1383
|
|
|
// Guest may have collapsed the header, check the cookie to prevent collapse jumping |
1384
|
1 |
|
elseif ($user_info['is_guest'] && isset($_COOKIE['upshrink'])) |
1385
|
|
|
$context['minmax_preferences'] = array('upshrink' => $_COOKIE['upshrink']); |
1386
|
|
|
|
1387
|
|
|
// @todo when are these set before loadTheme(0, true)? |
1388
|
1 |
|
loadThemeContext(); |
1389
|
|
|
|
1390
|
|
|
// @todo These really don't belong in loadTheme() since they are more general than the theme. |
1391
|
1 |
|
$context['session_var'] = $_SESSION['session_var']; |
1392
|
1 |
|
$context['session_id'] = $_SESSION['session_value']; |
1393
|
1 |
|
$context['forum_name'] = $mbname; |
1394
|
1 |
|
$context['forum_name_html_safe'] = $context['forum_name']; |
1395
|
1 |
|
$context['current_action'] = isset($_REQUEST['action']) ? $_REQUEST['action'] : null; |
1396
|
1 |
|
$context['current_subaction'] = isset($_REQUEST['sa']) ? $_REQUEST['sa'] : null; |
1397
|
|
|
|
1398
|
|
|
// Set some permission related settings. |
1399
|
1 |
|
if ($user_info['is_guest'] && !empty($modSettings['enableVBStyleLogin'])) |
1400
|
1 |
|
{ |
1401
|
1 |
|
$context['show_login_bar'] = true; |
1402
|
1 |
|
$context['theme_header_callbacks'][] = 'login_bar'; |
1403
|
1 |
|
loadJavascriptFile('sha256.js', array('defer' => true)); |
1404
|
1 |
|
} |
1405
|
|
|
|
1406
|
|
|
// This determines the server... not used in many places, except for login fixing. |
1407
|
1 |
|
detectServer(); |
1408
|
|
|
|
1409
|
|
|
// Detect the browser. This is separated out because it's also used in attachment downloads |
1410
|
1 |
|
detectBrowser(); |
1411
|
|
|
|
1412
|
|
|
// Set the top level linktree up. |
1413
|
1 |
|
array_unshift($context['linktree'], array( |
1414
|
1 |
|
'url' => $scripturl, |
1415
|
1 |
|
'name' => $context['forum_name'] |
1416
|
1 |
|
)); |
1417
|
|
|
|
1418
|
|
|
// Just some mobile-friendly settings |
1419
|
1 |
|
if ($context['browser_body_id'] == 'mobile') |
1420
|
1 |
|
{ |
1421
|
|
|
// Disable the preview text. |
1422
|
|
|
$modSettings['message_index_preview'] = 0; |
1423
|
|
|
// Force the usage of click menu instead of a hover menu. |
1424
|
|
|
$options['use_click_menu'] = 1; |
1425
|
|
|
// No space left for a sidebar |
1426
|
|
|
$options['use_sidebar_menu'] = false; |
1427
|
|
|
// Disable the search dropdown. |
1428
|
|
|
$modSettings['search_dropdown'] = false; |
1429
|
|
|
} |
1430
|
|
|
|
1431
|
1 |
|
if (!isset($txt)) |
1432
|
1 |
|
$txt = array(); |
1433
|
|
|
|
1434
|
|
|
// Load the basic layers |
1435
|
1 |
|
theme()->loadDefaultLayers(); |
1436
|
|
|
|
1437
|
|
|
// Defaults in case of odd things |
1438
|
1 |
|
$settings['avatars_on_indexes'] = 0; |
1439
|
|
|
|
1440
|
|
|
// Initialize the theme. |
1441
|
1 |
|
if (function_exists('template_init')) |
1442
|
1 |
|
$settings = array_merge($settings, template_init()); |
1443
|
|
|
|
1444
|
|
|
// Call initialization theme integration functions. |
1445
|
1 |
|
call_integration_hook('integrate_init_theme', array($id_theme, &$settings)); |
1446
|
|
|
|
1447
|
|
|
// Guests may still need a name. |
1448
|
1 |
View Code Duplication |
if ($context['user']['is_guest'] && empty($context['user']['name'])) |
1449
|
1 |
|
$context['user']['name'] = $txt['guest_title']; |
1450
|
|
|
|
1451
|
|
|
// Any theme-related strings that need to be loaded? |
1452
|
1 |
|
if (!empty($settings['require_theme_strings'])) |
1453
|
1 |
|
loadLanguage('ThemeStrings', '', false); |
1454
|
|
|
|
1455
|
|
|
// Load font Awesome fonts |
1456
|
1 |
|
loadCSSFile('font-awesome.min.css'); |
1457
|
|
|
|
1458
|
|
|
// We allow theme variants, because we're cool. |
1459
|
1 |
|
if (!empty($settings['theme_variants'])) |
1460
|
1 |
|
{ |
1461
|
1 |
|
theme()->loadThemeVariant(); |
1462
|
1 |
|
} |
1463
|
|
|
|
1464
|
|
|
// A bit lonely maybe, though I think it should be set up *after* the theme variants detection |
1465
|
1 |
|
$context['header_logo_url_html_safe'] = empty($settings['header_logo_url']) ? $settings['images_url'] . '/' . $context['theme_variant_url'] . 'logo_elk.png' : Util::htmlspecialchars($settings['header_logo_url']); |
1466
|
|
|
|
1467
|
|
|
// Allow overriding the board wide time/number formats. |
1468
|
1 |
|
if (empty($user_settings['time_format']) && !empty($txt['time_format'])) |
1469
|
1 |
|
$user_info['time_format'] = $txt['time_format']; |
1470
|
|
|
|
1471
|
1 |
View Code Duplication |
if (isset($settings['use_default_images']) && $settings['use_default_images'] == 'always') |
1472
|
1 |
|
{ |
1473
|
|
|
$settings['theme_url'] = $settings['default_theme_url']; |
1474
|
|
|
$settings['images_url'] = $settings['default_images_url']; |
1475
|
|
|
$settings['theme_dir'] = $settings['default_theme_dir']; |
1476
|
|
|
} |
1477
|
|
|
|
1478
|
|
|
// Make a special URL for the language. |
1479
|
1 |
|
$settings['lang_images_url'] = $settings['images_url'] . '/' . (!empty($txt['image_lang']) ? $txt['image_lang'] : $user_info['language']); |
1480
|
|
|
|
1481
|
|
|
// RTL languages require an additional stylesheet. |
1482
|
1 |
|
if ($context['right_to_left']) |
1483
|
1 |
|
loadCSSFile('rtl.css'); |
1484
|
|
|
|
1485
|
1 |
View Code Duplication |
if (!empty($context['theme_variant']) && $context['right_to_left']) |
1486
|
1 |
|
loadCSSFile($context['theme_variant'] . '/rtl' . $context['theme_variant'] . '.css'); |
1487
|
|
|
|
1488
|
|
|
// This allows us to change the way things look for the admin. |
1489
|
1 |
|
$context['admin_features'] = isset($modSettings['admin_features']) ? explode(',', $modSettings['admin_features']) : array('cd,cp,k,w,rg,ml,pm'); |
1490
|
|
|
|
1491
|
1 |
|
if (!empty($modSettings['xmlnews_enable']) && (!empty($modSettings['allow_guestAccess']) || $context['user']['is_logged'])) |
1492
|
1 |
|
$context['newsfeed_urls'] = array( |
1493
|
1 |
|
'rss' => $scripturl . '?action=.xml;type=rss2;limit=' . (!empty($modSettings['xmlnews_limit']) ? $modSettings['xmlnews_limit'] : 5), |
1494
|
1 |
|
'atom' => $scripturl . '?action=.xml;type=atom;limit=' . (!empty($modSettings['xmlnews_limit']) ? $modSettings['xmlnews_limit'] : 5) |
1495
|
1 |
|
); |
1496
|
|
|
|
1497
|
1 |
|
theme()->loadThemeJavascript(); |
1498
|
|
|
|
1499
|
1 |
|
Hooks::get()->newPath(array('$themedir' => $settings['theme_dir'])); |
1500
|
|
|
|
1501
|
|
|
// Any files to include at this point? |
1502
|
1 |
|
call_integration_include_hook('integrate_theme_include'); |
1503
|
|
|
|
1504
|
|
|
// Call load theme integration functions. |
1505
|
1 |
|
call_integration_hook('integrate_load_theme'); |
1506
|
|
|
|
1507
|
|
|
// We are ready to go. |
1508
|
1 |
|
$context['theme_loaded'] = true; |
1509
|
1 |
|
} |
1510
|
|
|
|
1511
|
|
|
function loadThemeUrls() |
|
|
|
|
1512
|
|
|
{ |
1513
|
1 |
|
global $scripturl, $boardurl, $modSettings; |
1514
|
|
|
|
1515
|
|
|
// Check to see if they're accessing it from the wrong place. |
1516
|
1 |
|
if (isset($_SERVER['HTTP_HOST']) || isset($_SERVER['SERVER_NAME'])) |
1517
|
1 |
|
{ |
1518
|
|
|
$detected_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 'https://' : 'http://'; |
1519
|
|
|
$detected_url .= empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST']; |
1520
|
|
|
$temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(dirname($_SERVER['PHP_SELF']), '\\', '/')); |
1521
|
|
|
if ($temp != '/') |
1522
|
|
|
$detected_url .= $temp; |
1523
|
|
|
} |
1524
|
|
|
|
1525
|
1 |
|
if (isset($detected_url) && $detected_url != $boardurl) |
1526
|
1 |
|
{ |
1527
|
|
|
// Try #1 - check if it's in a list of alias addresses. |
1528
|
|
|
if (!empty($modSettings['forum_alias_urls'])) |
1529
|
|
|
{ |
1530
|
|
|
$aliases = explode(',', $modSettings['forum_alias_urls']); |
1531
|
|
|
foreach ($aliases as $alias) |
1532
|
|
|
{ |
1533
|
|
|
// Rip off all the boring parts, spaces, etc. |
1534
|
|
|
if ($detected_url == trim($alias) || strtr($detected_url, array('http://' => '', 'https://' => '')) == trim($alias)) |
1535
|
|
|
$do_fix = true; |
1536
|
|
|
} |
1537
|
|
|
} |
1538
|
|
|
|
1539
|
|
|
// Hmm... check #2 - is it just different by a www? Send them to the correct place!! |
1540
|
|
|
if (empty($do_fix) && strtr($detected_url, array('://' => '://www.')) == $boardurl && (empty($_GET) || count($_GET) == 1) && ELK != 'SSI') |
1541
|
|
|
{ |
1542
|
|
|
// Okay, this seems weird, but we don't want an endless loop - this will make $_GET not empty ;). |
1543
|
|
|
if (empty($_GET)) |
1544
|
|
|
redirectexit('wwwRedirect'); |
1545
|
|
|
else |
1546
|
|
|
{ |
1547
|
|
|
list ($k, $v) = each($_GET); |
1548
|
|
|
if ($k != 'wwwRedirect') |
1549
|
|
|
redirectexit('wwwRedirect;' . $k . '=' . $v); |
1550
|
|
|
} |
1551
|
|
|
} |
1552
|
|
|
|
1553
|
|
|
// #3 is just a check for SSL... |
1554
|
|
|
if (strtr($detected_url, array('https://' => 'http://')) == $boardurl) |
1555
|
|
|
$do_fix = true; |
1556
|
|
|
|
1557
|
|
|
// Okay, #4 - perhaps it's an IP address? We're gonna want to use that one, then. (assuming it's the IP or something...) |
1558
|
|
|
if (!empty($do_fix) || preg_match('~^http[s]?://(?:[\d\.:]+|\[[\d:]+\](?::\d+)?)(?:$|/)~', $detected_url) == 1) |
1559
|
|
|
{ |
1560
|
|
|
fixThemeUrls($detected_url); |
1561
|
|
|
} |
1562
|
|
|
} |
1563
|
1 |
|
} |
1564
|
|
|
|
1565
|
|
|
function loadThemeContext() |
1566
|
|
|
{ |
1567
|
1 |
|
global $context, $settings, $modSettings; |
1568
|
|
|
|
1569
|
|
|
// Some basic information... |
1570
|
1 |
|
if (!isset($context['html_headers'])) |
1571
|
1 |
|
$context['html_headers'] = ''; |
1572
|
1 |
|
if (!isset($context['links'])) |
1573
|
1 |
|
$context['links'] = array(); |
1574
|
1 |
|
if (!isset($context['javascript_files'])) |
1575
|
1 |
|
$context['javascript_files'] = array(); |
1576
|
1 |
|
if (!isset($context['css_files'])) |
1577
|
1 |
|
$context['css_files'] = array(); |
1578
|
1 |
|
if (!isset($context['css_rules'])) |
1579
|
1 |
|
$context['css_rules'] = array(); |
1580
|
1 |
|
if (!isset($context['javascript_inline'])) |
1581
|
1 |
|
$context['javascript_inline'] = array('standard' => array(), 'defer' => array()); |
1582
|
1 |
|
if (!isset($context['javascript_vars'])) |
1583
|
1 |
|
$context['javascript_vars'] = array(); |
1584
|
|
|
|
1585
|
|
|
// Set a couple of bits for the template. |
1586
|
1 |
|
$context['right_to_left'] = !empty($txt['lang_rtl']); |
|
|
|
|
1587
|
1 |
|
$context['tabindex'] = 1; |
1588
|
|
|
|
1589
|
1 |
|
$context['theme_variant'] = ''; |
1590
|
1 |
|
$context['theme_variant_url'] = ''; |
1591
|
|
|
|
1592
|
1 |
|
$context['menu_separator'] = !empty($settings['use_image_buttons']) ? ' ' : ' | '; |
1593
|
1 |
|
$context['can_register'] = empty($modSettings['registration_method']) || $modSettings['registration_method'] != 3; |
1594
|
|
|
|
1595
|
1 |
|
foreach (array('theme_header', 'upper_content') as $call) |
1596
|
|
|
{ |
1597
|
1 |
|
if (!isset($context[$call . '_callbacks'])) |
1598
|
1 |
|
$context[$call . '_callbacks'] = array(); |
1599
|
1 |
|
} |
1600
|
|
|
|
1601
|
|
|
// This allows sticking some HTML on the page output - useful for controls. |
1602
|
1 |
|
$context['insert_after_template'] = ''; |
1603
|
1 |
|
} |
1604
|
|
|
|
1605
|
|
|
function loadUserContext() |
1606
|
|
|
{ |
1607
|
1 |
|
global $context, $user_info, $txt, $modSettings; |
1608
|
|
|
|
1609
|
|
|
// Set up the contextual user array. |
1610
|
1 |
|
$context['user'] = array( |
1611
|
1 |
|
'id' => $user_info['id'], |
1612
|
1 |
|
'is_logged' => !$user_info['is_guest'], |
1613
|
1 |
|
'is_guest' => &$user_info['is_guest'], |
1614
|
1 |
|
'is_admin' => &$user_info['is_admin'], |
1615
|
1 |
|
'is_mod' => &$user_info['is_mod'], |
1616
|
1 |
|
'is_moderator' => &$user_info['is_moderator'], |
1617
|
|
|
// A user can mod if they have permission to see the mod center, or they are a board/group/approval moderator. |
1618
|
1 |
|
'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'])))), |
1619
|
1 |
|
'username' => $user_info['username'], |
1620
|
1 |
|
'language' => $user_info['language'], |
1621
|
1 |
|
'email' => $user_info['email'], |
1622
|
1 |
|
'ignoreusers' => $user_info['ignoreusers'], |
1623
|
|
|
); |
1624
|
|
|
|
1625
|
|
|
// Something for the guests |
1626
|
1 |
|
if (!$context['user']['is_guest']) |
1627
|
1 |
|
$context['user']['name'] = $user_info['name']; |
1628
|
1 |
View Code Duplication |
elseif ($context['user']['is_guest'] && !empty($txt['guest_title'])) |
1629
|
1 |
|
$context['user']['name'] = $txt['guest_title']; |
1630
|
|
|
|
1631
|
1 |
|
$context['user']['smiley_set'] = determineSmileySet($user_info['smiley_set'], $modSettings['smiley_sets_known']); |
1632
|
1 |
|
$context['smiley_enabled'] = $user_info['smiley_set'] !== 'none'; |
1633
|
1 |
|
$context['user']['smiley_path'] = $modSettings['smileys_url'] . '/' . $context['user']['smiley_set'] . '/'; |
1634
|
1 |
|
} |
1635
|
|
|
|
1636
|
|
|
function fixThemeUrls($detected_url) |
|
|
|
|
1637
|
|
|
{ |
1638
|
|
|
global $boardurl, $scripturl, $settings, $modSettings, $context; |
1639
|
|
|
|
1640
|
|
|
// Caching is good ;). |
1641
|
|
|
$oldurl = $boardurl; |
1642
|
|
|
|
1643
|
|
|
// Fix $boardurl and $scripturl. |
1644
|
|
|
$boardurl = $detected_url; |
1645
|
|
|
$scripturl = strtr($scripturl, array($oldurl => $boardurl)); |
1646
|
|
|
$_SERVER['REQUEST_URL'] = strtr($_SERVER['REQUEST_URL'], array($oldurl => $boardurl)); |
1647
|
|
|
|
1648
|
|
|
// Fix the theme urls... |
1649
|
|
|
$settings['theme_url'] = strtr($settings['theme_url'], array($oldurl => $boardurl)); |
1650
|
|
|
$settings['default_theme_url'] = strtr($settings['default_theme_url'], array($oldurl => $boardurl)); |
1651
|
|
|
$settings['actual_theme_url'] = strtr($settings['actual_theme_url'], array($oldurl => $boardurl)); |
1652
|
|
|
$settings['images_url'] = strtr($settings['images_url'], array($oldurl => $boardurl)); |
1653
|
|
|
$settings['default_images_url'] = strtr($settings['default_images_url'], array($oldurl => $boardurl)); |
1654
|
|
|
$settings['actual_images_url'] = strtr($settings['actual_images_url'], array($oldurl => $boardurl)); |
1655
|
|
|
|
1656
|
|
|
// And just a few mod settings :). |
1657
|
|
|
$modSettings['smileys_url'] = strtr($modSettings['smileys_url'], array($oldurl => $boardurl)); |
1658
|
|
|
$modSettings['avatar_url'] = strtr($modSettings['avatar_url'], array($oldurl => $boardurl)); |
1659
|
|
|
|
1660
|
|
|
// Clean up after loadBoard(). |
1661
|
|
|
if (isset($board_info['moderators'])) |
|
|
|
|
1662
|
|
|
{ |
1663
|
|
|
foreach ($board_info['moderators'] as $k => $dummy) |
1664
|
|
|
{ |
1665
|
|
|
$board_info['moderators'][$k]['href'] = strtr($dummy['href'], array($oldurl => $boardurl)); |
1666
|
|
|
$board_info['moderators'][$k]['link'] = strtr($dummy['link'], array('"' . $oldurl => '"' . $boardurl)); |
1667
|
|
|
} |
1668
|
|
|
} |
1669
|
|
|
|
1670
|
|
|
foreach ($context['linktree'] as $k => $dummy) |
1671
|
|
|
$context['linktree'][$k]['url'] = strtr($dummy['url'], array($oldurl => $boardurl)); |
1672
|
|
|
} |
1673
|
|
|
|
1674
|
|
|
/** |
1675
|
|
|
* Determine the current user's smiley set |
1676
|
|
|
* |
1677
|
|
|
* @param mixed[] $user_smiley_set |
1678
|
|
|
* @param mixed[] $known_smiley_sets |
1679
|
|
|
* |
1680
|
|
|
* @return mixed |
1681
|
|
|
*/ |
1682
|
|
|
function determineSmileySet($user_smiley_set, $known_smiley_sets) |
1683
|
|
|
{ |
1684
|
1 |
|
global $modSettings, $settings; |
1685
|
|
|
|
1686
|
1 |
|
if ((!in_array($user_smiley_set, explode(',', $known_smiley_sets)) && $user_smiley_set !== 'none') || empty($modSettings['smiley_sets_enable'])) |
1687
|
1 |
|
{ |
1688
|
1 |
|
$set = !empty($settings['smiley_sets_default']) ? $settings['smiley_sets_default'] : $modSettings['smiley_sets_default']; |
1689
|
1 |
|
} |
1690
|
|
|
else |
1691
|
|
|
{ |
1692
|
|
|
$set = $user_smiley_set; |
1693
|
|
|
} |
1694
|
|
|
|
1695
|
1 |
|
return $set; |
1696
|
|
|
} |
1697
|
|
|
|
1698
|
|
|
/** |
1699
|
|
|
* This loads the bare minimum data. |
1700
|
|
|
* |
1701
|
|
|
* - Needed by scheduled tasks, |
1702
|
|
|
* - Needed by any other code that needs language files before the forum (the theme) is loaded. |
1703
|
|
|
*/ |
1704
|
|
|
function loadEssentialThemeData() |
1705
|
|
|
{ |
1706
|
|
|
global $settings, $modSettings, $mbname, $context; |
1707
|
|
|
|
1708
|
|
|
$db = database(); |
1709
|
|
|
|
1710
|
|
|
// Get all the default theme variables. |
1711
|
|
|
$db->fetchQueryCallback(' |
1712
|
|
|
SELECT id_theme, variable, value |
1713
|
|
|
FROM {db_prefix}themes |
1714
|
|
|
WHERE id_member = {int:no_member} |
1715
|
|
|
AND id_theme IN (1, {int:theme_guests})', |
1716
|
|
|
array( |
1717
|
|
|
'no_member' => 0, |
1718
|
|
|
'theme_guests' => $modSettings['theme_guests'], |
1719
|
|
|
), |
1720
|
|
|
function($row) |
1721
|
|
|
{ |
1722
|
|
|
global $settings; |
1723
|
|
|
|
1724
|
|
|
$settings[$row['variable']] = $row['value']; |
1725
|
|
|
|
1726
|
|
|
// Is this the default theme? |
1727
|
|
|
if (in_array($row['variable'], array('theme_dir', 'theme_url', 'images_url')) && $row['id_theme'] == '1') |
1728
|
|
|
$settings['default_' . $row['variable']] = $row['value']; |
1729
|
|
|
} |
1730
|
|
|
); |
1731
|
|
|
|
1732
|
|
|
// Check we have some directories setup. |
1733
|
|
|
if (!Templates::getInstance()->hasDirectories()) |
1734
|
|
|
{ |
1735
|
|
|
Templates::getInstance()->reloadDirectories($settings); |
1736
|
|
|
} |
1737
|
|
|
|
1738
|
|
|
// Assume we want this. |
1739
|
|
|
$context['forum_name'] = $mbname; |
1740
|
|
|
$context['forum_name_html_safe'] = $context['forum_name']; |
1741
|
|
|
|
1742
|
|
|
loadLanguage('index+Addons'); |
1743
|
|
|
} |
1744
|
|
|
|
1745
|
|
|
/** |
1746
|
|
|
* Load a template - if the theme doesn't include it, use the default. |
1747
|
|
|
* |
1748
|
|
|
* What it does: |
1749
|
|
|
* - loads a template file with the name template_name from the current, default, or base theme. |
1750
|
|
|
* - detects a wrong default theme directory and tries to work around it. |
1751
|
|
|
* - can be used to only load style sheets by using false as the template name |
1752
|
|
|
* loading of style sheets with this function is deprecated, use loadCSSFile instead |
1753
|
|
|
* - if $settings['template_dirs'] is empty, it delays the loading of the template |
1754
|
|
|
* |
1755
|
|
|
* @uses the requireTemplate() function to actually load the file. |
1756
|
|
|
* @param string|false $template_name |
1757
|
|
|
* @param string[]|string $style_sheets any style sheets to load with the template |
1758
|
|
|
* @param bool $fatal = true if fatal is true, dies with an error message if the template cannot be found |
1759
|
|
|
* |
1760
|
|
|
* @return boolean|null |
1761
|
|
|
*/ |
1762
|
|
|
function loadTemplate($template_name, $style_sheets = array(), $fatal = true) |
1763
|
|
|
{ |
1764
|
1 |
|
return Templates::getInstance()->load($template_name, $style_sheets, $fatal); |
1765
|
|
|
} |
1766
|
|
|
|
1767
|
|
|
/** |
1768
|
|
|
* Load a sub-template. |
1769
|
|
|
* |
1770
|
|
|
* What it does: |
1771
|
|
|
* - loads the sub template specified by sub_template_name, which must be in an already-loaded template. |
1772
|
|
|
* - if ?debug is in the query string, shows administrators a marker after every sub template |
1773
|
|
|
* for debugging purposes. |
1774
|
|
|
* |
1775
|
|
|
* @param string $sub_template_name |
1776
|
|
|
* @param bool|string $fatal = false |
1777
|
|
|
* - $fatal = true is for templates that shouldn't get a 'pretty' error screen |
1778
|
|
|
* - $fatal = 'ignore' to skip |
1779
|
|
|
*/ |
1780
|
|
|
function loadSubTemplate($sub_template_name, $fatal = false) |
1781
|
|
|
{ |
1782
|
|
|
return Templates::getInstance()->loadSubTemplate($sub_template_name, $fatal); |
1783
|
|
|
} |
1784
|
|
|
|
1785
|
|
|
/** |
1786
|
|
|
* Add a CSS file for output later |
1787
|
|
|
* |
1788
|
|
|
* @param string[]|string $filenames string or array of filenames to work on |
1789
|
|
|
* @param mixed[] $params = array() |
1790
|
|
|
* Keys are the following: |
1791
|
|
|
* - ['local'] (true/false): define if the file is local |
1792
|
|
|
* - ['fallback'] (true/false): if false will attempt to load the file |
1793
|
|
|
* from the default theme if not found in the current theme |
1794
|
|
|
* - ['stale'] (true/false/string): if true or null, use cache stale, |
1795
|
|
|
* false do not, or used a supplied string |
1796
|
|
|
* @param string $id optional id to use in html id="" |
1797
|
|
|
*/ |
1798
|
|
|
function loadCSSFile($filenames, $params = array(), $id = '') |
1799
|
|
|
{ |
1800
|
1 |
|
global $context; |
1801
|
|
|
|
1802
|
1 |
|
if (empty($filenames)) |
1803
|
1 |
|
return; |
1804
|
|
|
|
1805
|
1 |
|
if (!is_array($filenames)) |
1806
|
1 |
|
$filenames = array($filenames); |
1807
|
|
|
|
1808
|
1 |
|
if (in_array('admin.css', $filenames)) |
1809
|
1 |
|
$filenames[] = $context['theme_variant'] . '/admin' . $context['theme_variant'] . '.css'; |
1810
|
|
|
|
1811
|
1 |
|
$params['subdir'] = 'css'; |
1812
|
1 |
|
$params['extension'] = 'css'; |
1813
|
1 |
|
$params['index_name'] = 'css_files'; |
1814
|
1 |
|
$params['debug_index'] = 'sheets'; |
1815
|
|
|
|
1816
|
1 |
|
loadAssetFile($filenames, $params, $id); |
1817
|
1 |
|
} |
1818
|
|
|
|
1819
|
|
|
/** |
1820
|
|
|
* Add a Javascript file for output later |
1821
|
|
|
* |
1822
|
|
|
* What it does: |
1823
|
|
|
* - Can be passed an array of filenames, all which will have the same |
1824
|
|
|
* parameters applied, |
1825
|
|
|
* - if you need specific parameters on a per file basis, call it multiple times |
1826
|
|
|
* |
1827
|
|
|
* @param string[]|string $filenames string or array of filenames to work on |
1828
|
|
|
* @param mixed[] $params = array() |
1829
|
|
|
* Keys are the following: |
1830
|
|
|
* - ['local'] (true/false): define if the file is local, if file does not |
1831
|
|
|
* start with http its assumed local |
1832
|
|
|
* - ['defer'] (true/false): define if the file should load in <head> or before |
1833
|
|
|
* the closing <html> tag |
1834
|
|
|
* - ['fallback'] (true/false): if true will attempt to load the file from the |
1835
|
|
|
* default theme if not found in the current this is the default behavior |
1836
|
|
|
* if this is not supplied |
1837
|
|
|
* - ['async'] (true/false): if the script should be loaded asynchronously (HTML5) |
1838
|
|
|
* - ['stale'] (true/false/string): if true or null, use cache stale, false do |
1839
|
|
|
* not, or used a supplied string |
1840
|
|
|
* @param string $id = '' optional id to use in html id="" |
1841
|
|
|
*/ |
1842
|
|
|
function loadJavascriptFile($filenames, $params = array(), $id = '') |
1843
|
|
|
{ |
1844
|
1 |
|
if (empty($filenames)) |
1845
|
1 |
|
return; |
1846
|
|
|
|
1847
|
1 |
|
$params['subdir'] = 'scripts'; |
1848
|
1 |
|
$params['extension'] = 'js'; |
1849
|
1 |
|
$params['index_name'] = 'js_files'; |
1850
|
1 |
|
$params['debug_index'] = 'javascript'; |
1851
|
|
|
|
1852
|
1 |
|
loadAssetFile($filenames, $params, $id); |
1853
|
1 |
|
} |
1854
|
|
|
|
1855
|
|
|
/** |
1856
|
|
|
* Add an asset (css, js or other) file for output later |
1857
|
|
|
* |
1858
|
|
|
* What it does: |
1859
|
|
|
* - Can be passed an array of filenames, all which will have the same |
1860
|
|
|
* parameters applied, |
1861
|
|
|
* - If you need specific parameters on a per file basis, call it multiple times |
1862
|
|
|
* |
1863
|
|
|
* @param string[]|string $filenames string or array of filenames to work on |
1864
|
|
|
* @param mixed[] $params = array() |
1865
|
|
|
* Keys are the following: |
1866
|
|
|
* - ['subdir'] (string): the subdirectory of the theme dir the file is in |
1867
|
|
|
* - ['extension'] (string): the extension of the file (e.g. css) |
1868
|
|
|
* - ['index_name'] (string): the $context index that holds the array of loaded |
1869
|
|
|
* files |
1870
|
|
|
* - ['debug_index'] (string): the index that holds the array of loaded |
1871
|
|
|
* files for debugging debug |
1872
|
|
|
* - ['local'] (true/false): define if the file is local, if file does not |
1873
|
|
|
* start with http or // (schema-less URLs) its assumed local. |
1874
|
|
|
* The parameter is in fact useful only for files whose name starts with |
1875
|
|
|
* http, in any other case (e.g. passing a local URL) the parameter would |
1876
|
|
|
* fail in properly adding the file to the list. |
1877
|
|
|
* - ['defer'] (true/false): define if the file should load in <head> or before |
1878
|
|
|
* the closing <html> tag |
1879
|
|
|
* - ['fallback'] (true/false): if true will attempt to load the file from the |
1880
|
|
|
* default theme if not found in the current this is the default behavior |
1881
|
|
|
* if this is not supplied |
1882
|
|
|
* - ['async'] (true/false): if the script should be loaded asynchronously (HTML5) |
1883
|
|
|
* - ['stale'] (true/false/string): if true or null, use cache stale, false do |
1884
|
|
|
* not, or used a supplied string |
1885
|
|
|
* @param string $id = '' optional id to use in html id="" |
1886
|
|
|
*/ |
1887
|
|
|
function loadAssetFile($filenames, $params = array(), $id = '') |
1888
|
|
|
{ |
1889
|
1 |
|
global $settings, $context, $db_show_debug; |
1890
|
|
|
|
1891
|
1 |
|
if (empty($filenames)) |
1892
|
1 |
|
return; |
1893
|
|
|
|
1894
|
1 |
|
$cache = Cache::instance(); |
1895
|
|
|
|
1896
|
1 |
|
if (!is_array($filenames)) |
1897
|
1 |
|
$filenames = array($filenames); |
1898
|
|
|
|
1899
|
|
|
// Static values for all these settings |
1900
|
1 |
|
if (!isset($params['stale']) || $params['stale'] === true) |
1901
|
1 |
|
$staler_string = CACHE_STALE; |
1902
|
|
|
elseif (is_string($params['stale'])) |
1903
|
|
|
$staler_string = ($params['stale'][0] === '?' ? $params['stale'] : '?' . $params['stale']); |
1904
|
|
|
else |
1905
|
|
|
$staler_string = ''; |
1906
|
|
|
|
1907
|
1 |
|
$fallback = (!empty($params['fallback']) && ($params['fallback'] === false)) ? false : true; |
1908
|
1 |
|
$dir = '/' . $params['subdir'] . '/'; |
1909
|
|
|
|
1910
|
|
|
// Whoa ... we've done this before yes? |
1911
|
1 |
|
$cache_name = 'load_' . $params['extension'] . '_' . hash('md5', $settings['theme_dir'] . implode('_', $filenames)); |
1912
|
1 |
|
if ($cache->getVar($temp, $cache_name, 600)) |
1913
|
1 |
|
{ |
1914
|
|
|
if (empty($context[$params['index_name']])) |
1915
|
|
|
$context[$params['index_name']] = array(); |
1916
|
|
|
|
1917
|
|
|
$context[$params['index_name']] += $temp; |
|
|
|
|
1918
|
|
|
|
1919
|
|
|
if ($db_show_debug === true) |
1920
|
|
|
{ |
1921
|
|
|
foreach ($temp as $temp_params) |
1922
|
|
|
{ |
1923
|
|
|
$context['debug'][$params['debug_index']][] = $temp_params['options']['basename'] . '(' . (!empty($temp_params['options']['local']) ? (!empty($temp_params['options']['url']) ? basename($temp_params['options']['url']) : basename($temp_params['options']['dir'])) : '') . ')'; |
1924
|
|
|
} |
1925
|
|
|
} |
1926
|
|
|
} |
1927
|
|
|
else |
1928
|
|
|
{ |
1929
|
1 |
|
$this_build = array(); |
1930
|
|
|
|
1931
|
|
|
// All the files in this group use the above parameters |
1932
|
1 |
|
foreach ($filenames as $filename) |
1933
|
|
|
{ |
1934
|
|
|
// Account for shorthand like admin.ext?xyz11 filenames |
1935
|
1 |
|
$has_cache_staler = strpos($filename, '.' . $params['extension'] . '?'); |
1936
|
|
|
if ($has_cache_staler) |
1937
|
1 |
|
{ |
1938
|
|
|
$cache_staler = $staler_string; |
1939
|
|
|
$params['basename'] = substr($filename, 0, $has_cache_staler + strlen($params['extension']) + 1); |
1940
|
|
|
} |
1941
|
|
|
else |
1942
|
|
|
{ |
1943
|
1 |
|
$cache_staler = ''; |
1944
|
1 |
|
$params['basename'] = $filename; |
1945
|
|
|
} |
1946
|
1 |
|
$this_id = empty($id) ? strtr(basename($filename), '?', '_') : $id; |
1947
|
|
|
|
1948
|
|
|
// Is this a local file? |
1949
|
1 |
|
if (!empty($params['local']) || (substr($filename, 0, 4) !== 'http' && substr($filename, 0, 2) !== '//')) |
1950
|
1 |
|
{ |
1951
|
1 |
|
$params['local'] = true; |
1952
|
1 |
|
$params['dir'] = $settings['theme_dir'] . $dir; |
1953
|
1 |
|
$params['url'] = $settings['theme_url']; |
1954
|
|
|
|
1955
|
|
|
// Fallback if we are not already in the default theme |
1956
|
1 |
|
if ($fallback && ($settings['theme_dir'] !== $settings['default_theme_dir']) && !file_exists($settings['theme_dir'] . $dir . $params['basename'])) |
1957
|
1 |
|
{ |
1958
|
|
|
// Can't find it in this theme, how about the default? |
1959
|
|
|
if (file_exists($settings['default_theme_dir'] . $dir . $params['basename'])) |
1960
|
|
|
{ |
1961
|
|
|
$filename = $settings['default_theme_url'] . $dir . $params['basename'] . $cache_staler; |
1962
|
|
|
$params['dir'] = $settings['default_theme_dir'] . $dir; |
1963
|
|
|
$params['url'] = $settings['default_theme_url']; |
1964
|
|
|
} |
1965
|
|
|
else |
1966
|
|
|
$filename = false; |
1967
|
|
|
} |
1968
|
|
|
else |
1969
|
1 |
|
$filename = $settings['theme_url'] . $dir . $params['basename'] . $cache_staler; |
1970
|
1 |
|
} |
1971
|
|
|
|
1972
|
|
|
// Add it to the array for use in the template |
1973
|
1 |
|
if (!empty($filename)) |
1974
|
1 |
|
{ |
1975
|
1 |
|
$this_build[$this_id] = $context[$params['index_name']][$this_id] = array('filename' => $filename, 'options' => $params); |
1976
|
|
|
|
1977
|
1 |
|
if ($db_show_debug === true) |
1978
|
1 |
|
Debug::get()->add($params['debug_index'], $params['basename'] . '(' . (!empty($params['local']) ? (!empty($params['url']) ? basename($params['url']) : basename($params['dir'])) : '') . ')'); |
1979
|
1 |
|
} |
1980
|
|
|
|
1981
|
|
|
// Save it so we don't have to build this so often |
1982
|
1 |
|
$cache->put($cache_name, $this_build, 600); |
1983
|
1 |
|
} |
1984
|
|
|
} |
1985
|
1 |
|
} |
1986
|
|
|
|
1987
|
|
|
/** |
1988
|
|
|
* Add a Javascript variable for output later (for feeding text strings and similar to JS) |
1989
|
|
|
* |
1990
|
|
|
* @param mixed[] $vars array of vars to include in the output done as 'varname' => 'var value' |
1991
|
|
|
* @param bool $escape = false, whether or not to escape the value |
1992
|
|
|
*/ |
1993
|
|
|
function addJavascriptVar($vars, $escape = false) |
1994
|
|
|
{ |
1995
|
|
|
theme()->addJavascriptVar($vars, $escape); |
1996
|
|
|
} |
1997
|
|
|
|
1998
|
|
|
/** |
1999
|
|
|
* Add a block of inline Javascript code to be executed later |
2000
|
|
|
* |
2001
|
|
|
* What it does: |
2002
|
|
|
* - only use this if you have to, generally external JS files are better, but for very small scripts |
2003
|
|
|
* or for scripts that require help from PHP/whatever, this can be useful. |
2004
|
|
|
* - all code added with this function is added to the same <script> tag so do make sure your JS is clean! |
2005
|
|
|
* |
2006
|
|
|
* @param string $javascript |
2007
|
|
|
* @param bool $defer = false, define if the script should load in <head> or before the closing <html> tag |
2008
|
|
|
*/ |
2009
|
|
|
function addInlineJavascript($javascript, $defer = false) |
2010
|
|
|
{ |
2011
|
|
|
theme()->addInlineJavascript($javascript, $defer); |
2012
|
|
|
} |
2013
|
|
|
|
2014
|
|
|
/** |
2015
|
|
|
* Load a language file. |
2016
|
|
|
* |
2017
|
|
|
* - Tries the current and default themes as well as the user and global languages. |
2018
|
|
|
* |
2019
|
|
|
* @param string $template_name |
2020
|
|
|
* @param string $lang = '' |
2021
|
|
|
* @param bool $fatal = true |
2022
|
|
|
* @param bool $force_reload = false |
2023
|
|
|
* @return string The language actually loaded. |
2024
|
|
|
*/ |
2025
|
|
|
function loadLanguage($template_name, $lang = '', $fatal = true, $force_reload = false) |
2026
|
|
|
{ |
2027
|
28 |
|
global $user_info, $language, $settings, $modSettings; |
2028
|
28 |
|
global $db_show_debug, $txt; |
2029
|
28 |
|
static $already_loaded = array(); |
2030
|
|
|
|
2031
|
|
|
// Default to the user's language. |
2032
|
28 |
|
if ($lang == '') |
2033
|
28 |
|
$lang = isset($user_info['language']) ? $user_info['language'] : $language; |
2034
|
|
|
|
2035
|
28 |
|
if (!$force_reload && isset($already_loaded[$template_name]) && $already_loaded[$template_name] == $lang) |
2036
|
28 |
|
return $lang; |
2037
|
|
|
|
2038
|
|
|
// Do we want the English version of language file as fallback? |
2039
|
6 |
|
if (empty($modSettings['disable_language_fallback']) && $lang != 'english') |
2040
|
6 |
|
loadLanguage($template_name, 'english', false); |
2041
|
|
|
|
2042
|
|
|
// Make sure we have $settings - if not we're in trouble and need to find it! |
2043
|
6 |
|
if (empty($settings['default_theme_dir'])) |
2044
|
6 |
|
loadEssentialThemeData(); |
2045
|
|
|
|
2046
|
|
|
// What theme are we in? |
2047
|
6 |
|
$theme_name = basename($settings['theme_url']); |
2048
|
6 |
|
if (empty($theme_name)) |
2049
|
6 |
|
$theme_name = 'unknown'; |
2050
|
|
|
|
2051
|
6 |
|
$fix_arrays = false; |
2052
|
|
|
// For each file open it up and write it out! |
2053
|
6 |
|
foreach (explode('+', $template_name) as $template) |
2054
|
|
|
{ |
2055
|
6 |
|
if ($template === 'index') |
2056
|
6 |
|
$fix_arrays = true; |
2057
|
|
|
|
2058
|
|
|
// Obviously, the current theme is most important to check. |
2059
|
|
|
$attempts = array( |
2060
|
6 |
|
array($settings['theme_dir'], $template, $lang, $settings['theme_url']), |
2061
|
6 |
|
array($settings['theme_dir'], $template, $language, $settings['theme_url']), |
2062
|
6 |
|
); |
2063
|
|
|
|
2064
|
|
|
// Do we have a base theme to worry about? |
2065
|
6 |
|
if (isset($settings['base_theme_dir'])) |
2066
|
6 |
|
{ |
2067
|
|
|
$attempts[] = array($settings['base_theme_dir'], $template, $lang, $settings['base_theme_url']); |
2068
|
|
|
$attempts[] = array($settings['base_theme_dir'], $template, $language, $settings['base_theme_url']); |
2069
|
|
|
} |
2070
|
|
|
|
2071
|
|
|
// Fall back on the default theme if necessary. |
2072
|
6 |
|
$attempts[] = array($settings['default_theme_dir'], $template, $lang, $settings['default_theme_url']); |
2073
|
6 |
|
$attempts[] = array($settings['default_theme_dir'], $template, $language, $settings['default_theme_url']); |
2074
|
|
|
|
2075
|
|
|
// Fall back on the English language if none of the preferred languages can be found. |
2076
|
6 |
|
if (!in_array('english', array($lang, $language))) |
2077
|
6 |
|
{ |
2078
|
|
|
$attempts[] = array($settings['theme_dir'], $template, 'english', $settings['theme_url']); |
2079
|
|
|
$attempts[] = array($settings['default_theme_dir'], $template, 'english', $settings['default_theme_url']); |
2080
|
|
|
} |
2081
|
|
|
|
2082
|
6 |
|
$templates = Templates::getInstance(); |
2083
|
|
|
|
2084
|
|
|
// Try to find the language file. |
2085
|
6 |
|
$found = false; |
2086
|
6 |
|
foreach ($attempts as $k => $file) |
2087
|
|
|
{ |
2088
|
6 |
|
if (file_exists($file[0] . '/languages/' . $file[2] . '/' . $file[1] . '.' . $file[2] . '.php')) |
2089
|
6 |
|
{ |
2090
|
|
|
// Include it! |
2091
|
6 |
|
$templates->templateInclude($file[0] . '/languages/' . $file[2] . '/' . $file[1] . '.' . $file[2] . '.php'); |
2092
|
|
|
|
2093
|
|
|
// Note that we found it. |
2094
|
6 |
|
$found = true; |
2095
|
|
|
|
2096
|
6 |
|
break; |
2097
|
|
|
} |
2098
|
|
|
// @deprecated since 1.0 - old way of archiving language files, all in one directory |
2099
|
|
|
elseif (file_exists($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php')) |
2100
|
|
|
{ |
2101
|
|
|
// Include it! |
2102
|
|
|
$templates->templateInclude($file[0] . '/languages/' . $file[1] . '.' . $file[2] . '.php'); |
2103
|
|
|
|
2104
|
|
|
// Note that we found it. |
2105
|
|
|
$found = true; |
2106
|
|
|
|
2107
|
|
|
break; |
2108
|
|
|
} |
2109
|
6 |
|
} |
2110
|
|
|
|
2111
|
|
|
// That couldn't be found! Log the error, but *try* to continue normally. |
2112
|
6 |
|
if (!$found && $fatal) |
2113
|
6 |
|
{ |
2114
|
|
|
Errors::instance()->log_error(sprintf($txt['theme_language_error'], $template_name . '.' . $lang, 'template')); |
2115
|
|
|
break; |
2116
|
|
|
} |
2117
|
6 |
|
} |
2118
|
|
|
|
2119
|
|
|
if ($fix_arrays) |
2120
|
6 |
|
fix_calendar_text(); |
2121
|
|
|
|
2122
|
|
|
// Keep track of what we're up to soldier. |
2123
|
6 |
|
if ($db_show_debug === true) |
2124
|
6 |
|
Debug::get()->add('language_files', $template_name . '.' . $lang . ' (' . $theme_name . ')'); |
2125
|
|
|
|
2126
|
|
|
// Remember what we have loaded, and in which language. |
2127
|
6 |
|
$already_loaded[$template_name] = $lang; |
2128
|
|
|
|
2129
|
|
|
// Return the language actually loaded. |
2130
|
6 |
|
return $lang; |
2131
|
|
|
} |
2132
|
|
|
|
2133
|
|
|
/** |
2134
|
|
|
* Loads / Sets arrays for use in date display |
2135
|
|
|
*/ |
2136
|
|
|
function fix_calendar_text() |
2137
|
|
|
{ |
2138
|
|
|
global $txt; |
2139
|
|
|
|
2140
|
|
|
$txt['days'] = array( |
2141
|
|
|
$txt['sunday'], |
2142
|
|
|
$txt['monday'], |
2143
|
|
|
$txt['tuesday'], |
2144
|
|
|
$txt['wednesday'], |
2145
|
|
|
$txt['thursday'], |
2146
|
|
|
$txt['friday'], |
2147
|
|
|
$txt['saturday'], |
2148
|
|
|
); |
2149
|
|
|
$txt['days_short'] = array( |
2150
|
|
|
$txt['sunday_short'], |
2151
|
|
|
$txt['monday_short'], |
2152
|
|
|
$txt['tuesday_short'], |
2153
|
|
|
$txt['wednesday_short'], |
2154
|
|
|
$txt['thursday_short'], |
2155
|
|
|
$txt['friday_short'], |
2156
|
|
|
$txt['saturday_short'], |
2157
|
|
|
); |
2158
|
|
|
$txt['months'] = array( |
2159
|
|
|
1 => $txt['january'], |
2160
|
|
|
$txt['february'], |
2161
|
|
|
$txt['march'], |
2162
|
|
|
$txt['april'], |
2163
|
|
|
$txt['may'], |
2164
|
|
|
$txt['june'], |
2165
|
|
|
$txt['july'], |
2166
|
|
|
$txt['august'], |
2167
|
|
|
$txt['september'], |
2168
|
|
|
$txt['october'], |
2169
|
|
|
$txt['november'], |
2170
|
|
|
$txt['december'], |
2171
|
|
|
); |
2172
|
|
|
$txt['months_titles'] = array( |
2173
|
|
|
1 => $txt['january_titles'], |
2174
|
|
|
$txt['february_titles'], |
2175
|
|
|
$txt['march_titles'], |
2176
|
|
|
$txt['april_titles'], |
2177
|
|
|
$txt['may_titles'], |
2178
|
|
|
$txt['june_titles'], |
2179
|
|
|
$txt['july_titles'], |
2180
|
|
|
$txt['august_titles'], |
2181
|
|
|
$txt['september_titles'], |
2182
|
|
|
$txt['october_titles'], |
2183
|
|
|
$txt['november_titles'], |
2184
|
|
|
$txt['december_titles'], |
2185
|
|
|
); |
2186
|
|
|
$txt['months_short'] = array( |
2187
|
|
|
1 => $txt['january_short'], |
2188
|
|
|
$txt['february_short'], |
2189
|
|
|
$txt['march_short'], |
2190
|
|
|
$txt['april_short'], |
2191
|
|
|
$txt['may_short'], |
2192
|
|
|
$txt['june_short'], |
2193
|
|
|
$txt['july_short'], |
2194
|
|
|
$txt['august_short'], |
2195
|
|
|
$txt['september_short'], |
2196
|
|
|
$txt['october_short'], |
2197
|
|
|
$txt['november_short'], |
2198
|
|
|
$txt['december_short'], |
2199
|
|
|
); |
2200
|
|
|
} |
2201
|
|
|
|
2202
|
|
|
/** |
2203
|
|
|
* Get all parent boards (requires first parent as parameter) |
2204
|
|
|
* |
2205
|
|
|
* What it does: |
2206
|
|
|
* - It finds all the parents of id_parent, and that board itself. |
2207
|
|
|
* - Additionally, it detects the moderators of said boards. |
2208
|
|
|
* - Returns an array of information about the boards found. |
2209
|
|
|
* |
2210
|
|
|
* @param int $id_parent |
2211
|
|
|
*/ |
2212
|
|
|
function getBoardParents($id_parent) |
2213
|
|
|
{ |
2214
|
10 |
|
global $scripturl; |
2215
|
|
|
|
2216
|
10 |
|
$db = database(); |
2217
|
10 |
|
$cache = Cache::instance(); |
2218
|
|
|
|
2219
|
|
|
// First check if we have this cached already. |
2220
|
10 |
|
if (!$cache->getVar($boards, 'board_parents-' . $id_parent, 480)) |
|
|
|
|
2221
|
10 |
|
{ |
2222
|
10 |
|
$boards = array(); |
2223
|
10 |
|
$original_parent = $id_parent; |
2224
|
|
|
|
2225
|
|
|
// Loop while the parent is non-zero. |
2226
|
10 |
|
while ($id_parent != 0) |
2227
|
|
|
{ |
2228
|
10 |
|
$result = $db->query('', ' |
2229
|
|
|
SELECT |
2230
|
|
|
b.id_parent, b.name, {int:board_parent} AS id_board, IFNULL(mem.id_member, 0) AS id_moderator, |
2231
|
|
|
mem.real_name, b.child_level |
2232
|
|
|
FROM {db_prefix}boards AS b |
2233
|
|
|
LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board) |
2234
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member) |
2235
|
10 |
|
WHERE b.id_board = {int:board_parent}', |
2236
|
|
|
array( |
2237
|
10 |
|
'board_parent' => $id_parent, |
2238
|
|
|
) |
2239
|
10 |
|
); |
2240
|
|
|
// In the EXTREMELY unlikely event this happens, give an error message. |
2241
|
10 |
|
if ($db->num_rows($result) == 0) |
2242
|
10 |
|
Errors::instance()->fatal_lang_error('parent_not_found', 'critical'); |
2243
|
10 |
|
while ($row = $db->fetch_assoc($result)) |
2244
|
|
|
{ |
2245
|
10 |
|
if (!isset($boards[$row['id_board']])) |
2246
|
10 |
|
{ |
2247
|
10 |
|
$id_parent = $row['id_parent']; |
2248
|
10 |
|
$boards[$row['id_board']] = array( |
2249
|
10 |
|
'url' => $scripturl . '?board=' . $row['id_board'] . '.0', |
2250
|
10 |
|
'name' => $row['name'], |
2251
|
10 |
|
'level' => $row['child_level'], |
2252
|
10 |
|
'moderators' => array() |
2253
|
10 |
|
); |
2254
|
10 |
|
} |
2255
|
|
|
// If a moderator exists for this board, add that moderator for all children too. |
2256
|
10 |
|
if (!empty($row['id_moderator'])) |
2257
|
10 |
|
foreach ($boards as $id => $dummy) |
2258
|
|
|
{ |
2259
|
|
|
$boards[$id]['moderators'][$row['id_moderator']] = array( |
2260
|
|
|
'id' => $row['id_moderator'], |
2261
|
|
|
'name' => $row['real_name'], |
2262
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'], |
2263
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>' |
2264
|
|
|
); |
2265
|
|
|
} |
2266
|
10 |
|
} |
2267
|
10 |
|
$db->free_result($result); |
2268
|
10 |
|
} |
2269
|
|
|
|
2270
|
10 |
|
$cache->put('board_parents-' . $original_parent, $boards, 480); |
2271
|
10 |
|
} |
2272
|
|
|
|
2273
|
10 |
|
return $boards; |
|
|
|
|
2274
|
|
|
} |
2275
|
|
|
|
2276
|
|
|
/** |
2277
|
|
|
* Attempt to reload our known languages. |
2278
|
|
|
* |
2279
|
|
|
* @param bool $use_cache = true |
2280
|
|
|
*/ |
2281
|
|
|
function getLanguages($use_cache = true) |
2282
|
|
|
{ |
2283
|
|
|
global $settings; |
2284
|
|
|
|
2285
|
|
|
$cache = Cache::instance(); |
2286
|
|
|
|
2287
|
|
|
// Either we don't use the cache, or its expired. |
2288
|
|
|
$languages = array(); |
2289
|
|
|
|
2290
|
|
|
if (!$use_cache || !$cache->getVar($languages, 'known_languages', !$cache->checkLevel(1) ? 86400 : 3600)) |
2291
|
|
|
{ |
2292
|
|
|
// If we don't have our theme information yet, lets get it. |
2293
|
|
|
if (empty($settings['default_theme_dir'])) |
2294
|
|
|
loadTheme(0, false); |
2295
|
|
|
|
2296
|
|
|
// Default language directories to try. |
2297
|
|
|
$language_directories = array( |
2298
|
|
|
$settings['default_theme_dir'] . '/languages', |
2299
|
|
|
$settings['actual_theme_dir'] . '/languages', |
2300
|
|
|
); |
2301
|
|
|
|
2302
|
|
|
// We possibly have a base theme directory. |
2303
|
|
|
if (!empty($settings['base_theme_dir'])) |
2304
|
|
|
$language_directories[] = $settings['base_theme_dir'] . '/languages'; |
2305
|
|
|
|
2306
|
|
|
// Remove any duplicates. |
2307
|
|
|
$language_directories = array_unique($language_directories); |
2308
|
|
|
|
2309
|
|
|
foreach ($language_directories as $language_dir) |
2310
|
|
|
{ |
2311
|
|
|
// Can't look in here... doesn't exist! |
2312
|
|
|
if (!file_exists($language_dir)) |
2313
|
|
|
continue; |
2314
|
|
|
|
2315
|
|
|
$dir = dir($language_dir); |
2316
|
|
|
while ($entry = $dir->read()) |
2317
|
|
|
{ |
2318
|
|
|
// Only directories are interesting |
2319
|
|
|
if ($entry == '..' || !is_dir($dir->path . '/' . $entry)) |
|
|
|
|
2320
|
|
|
continue; |
2321
|
|
|
|
2322
|
|
|
// @todo at some point we may want to simplify that stuff (I mean scanning all the files just for index) |
2323
|
|
|
$file_dir = dir($dir->path . '/' . $entry); |
2324
|
|
|
while ($file_entry = $file_dir->read()) |
2325
|
|
|
{ |
2326
|
|
|
// Look for the index language file.... |
2327
|
|
|
if (!preg_match('~^index\.(.+)\.php$~', $file_entry, $matches)) |
2328
|
|
|
continue; |
2329
|
|
|
|
2330
|
|
|
$languages[$matches[1]] = array( |
2331
|
|
|
'name' => Util::ucwords(strtr($matches[1], array('_' => ' '))), |
2332
|
|
|
'selected' => false, |
2333
|
|
|
'filename' => $matches[1], |
2334
|
|
|
'location' => $language_dir . '/' . $entry . '/index.' . $matches[1] . '.php', |
2335
|
|
|
); |
2336
|
|
|
} |
2337
|
|
|
$file_dir->close(); |
2338
|
|
|
} |
2339
|
|
|
$dir->close(); |
2340
|
|
|
} |
2341
|
|
|
|
2342
|
|
|
// Lets cash in on this deal. |
2343
|
|
|
$cache->put('known_languages', $languages, $cache->isEnabled() && !Cache::instance()->checkLevel(1) ? 86400 : 3600); |
2344
|
|
|
} |
2345
|
|
|
|
2346
|
|
|
return $languages; |
2347
|
|
|
} |
2348
|
|
|
|
2349
|
|
|
/** |
2350
|
|
|
* Initialize a database connection. |
2351
|
|
|
*/ |
2352
|
|
|
function loadDatabase() |
2353
|
|
|
{ |
2354
|
|
|
global $db_persist, $db_server, $db_user, $db_passwd, $db_port; |
2355
|
|
|
global $db_type, $db_name, $ssi_db_user, $ssi_db_passwd, $db_prefix; |
2356
|
|
|
|
2357
|
|
|
// Database stuffs |
2358
|
|
|
require_once(SOURCEDIR . '/database/Database.subs.php'); |
2359
|
|
|
|
2360
|
|
|
// Figure out what type of database we are using. |
2361
|
|
|
if (empty($db_type) || !file_exists(SOURCEDIR . '/database/Db-' . $db_type . '.class.php')) |
2362
|
|
|
$db_type = 'mysql'; |
2363
|
|
|
|
2364
|
|
|
// 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. |
2365
|
|
|
if (ELK === 'SSI' && !empty($ssi_db_user) && !empty($ssi_db_passwd)) |
2366
|
|
|
$connection = elk_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, 'port' => $db_port), $db_type); |
|
|
|
|
2367
|
|
|
|
2368
|
|
|
// Either we aren't in SSI mode, or it failed. |
2369
|
|
|
if (empty($connection)) |
2370
|
|
|
$connection = elk_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist, 'dont_select_db' => ELK === 'SSI', 'port' => $db_port), $db_type); |
|
|
|
|
2371
|
|
|
|
2372
|
|
|
// Safe guard here, if there isn't a valid connection lets put a stop to it. |
2373
|
|
|
if (!$connection) |
2374
|
|
|
Errors::instance()->display_db_error(); |
2375
|
|
|
|
2376
|
|
|
// If in SSI mode fix up the prefix. |
2377
|
|
|
$db = database(); |
2378
|
|
|
if (ELK === 'SSI') |
2379
|
|
|
$db_prefix = $db->fix_prefix($db_prefix, $db_name); |
2380
|
|
|
|
2381
|
|
|
// Case sensitive database? Let's define a constant. |
2382
|
|
|
if ($db->db_case_sensitive() && !defined('DB_CASE_SENSITIVE')) |
2383
|
|
|
DEFINE('DB_CASE_SENSITIVE', '1'); |
2384
|
|
|
} |
2385
|
|
|
|
2386
|
|
|
/** |
2387
|
|
|
* Determine the user's avatar type and return the information as an array |
2388
|
|
|
* |
2389
|
|
|
* @todo this function seems more useful than expected, it should be improved. :P |
2390
|
|
|
* |
2391
|
|
|
* @param mixed[] $profile array containing the users profile data |
2392
|
|
|
* @return mixed[] $avatar |
2393
|
|
|
*/ |
2394
|
|
|
function determineAvatar($profile) |
2395
|
|
|
{ |
2396
|
1 |
|
global $modSettings, $scripturl, $settings; |
2397
|
|
|
|
2398
|
1 |
|
if (empty($profile)) |
2399
|
1 |
|
return array(); |
2400
|
|
|
|
2401
|
1 |
|
$avatar_protocol = substr(strtolower($profile['avatar']), 0, 7); |
2402
|
|
|
|
2403
|
|
|
// uploaded avatar? |
2404
|
1 |
|
if ($profile['id_attach'] > 0 && empty($profile['avatar'])) |
2405
|
1 |
|
{ |
2406
|
|
|
// where are those pesky avatars? |
2407
|
|
|
$avatar_url = empty($profile['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $profile['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $profile['filename']; |
2408
|
|
|
|
2409
|
|
|
$avatar = array( |
2410
|
|
|
'name' => $profile['avatar'], |
2411
|
|
|
'image' => '<img class="avatar avatarresize" src="' . $avatar_url . '" alt="" />', |
2412
|
|
|
'href' => $avatar_url, |
2413
|
|
|
'url' => '', |
2414
|
|
|
); |
2415
|
|
|
} |
2416
|
|
|
// remote avatar? |
2417
|
1 |
|
elseif ($avatar_protocol === 'http://' || $avatar_protocol === 'https:/') |
2418
|
|
|
{ |
2419
|
|
|
$avatar = array( |
2420
|
|
|
'name' => $profile['avatar'], |
2421
|
|
|
'image' => '<img class="avatar avatarresize" src="' . $profile['avatar'] . '" alt="" />', |
2422
|
|
|
'href' => $profile['avatar'], |
2423
|
|
|
'url' => $profile['avatar'], |
2424
|
|
|
); |
2425
|
|
|
} |
2426
|
|
|
// Gravatar instead? |
2427
|
1 |
|
elseif (!empty($profile['avatar']) && $profile['avatar'] === 'gravatar') |
2428
|
|
|
{ |
2429
|
|
|
// Gravatars URL. |
2430
|
|
|
$gravatar_url = '//www.gravatar.com/avatar/' . hash('md5', strtolower($profile['email_address'])) . '?s=' . $modSettings['avatar_max_height'] . (!empty($modSettings['gravatar_rating']) ? ('&r=' . $modSettings['gravatar_rating']) : ''); |
2431
|
|
|
|
2432
|
|
|
$avatar = array( |
2433
|
|
|
'name' => $profile['avatar'], |
2434
|
|
|
'image' => '<img class="avatar avatarresize" src="' . $gravatar_url . '" alt="" />', |
2435
|
|
|
'href' => $gravatar_url, |
2436
|
|
|
'url' => $gravatar_url, |
2437
|
|
|
); |
2438
|
|
|
} |
2439
|
|
|
// an avatar from the gallery? |
2440
|
1 |
|
elseif (!empty($profile['avatar']) && !($avatar_protocol === 'http://' || $avatar_protocol === 'https:/')) |
2441
|
|
|
{ |
2442
|
|
|
$avatar = array( |
2443
|
|
|
'name' => $profile['avatar'], |
2444
|
|
|
'image' => '<img class="avatar avatarresize" src="' . $modSettings['avatar_url'] . '/' . $profile['avatar'] . '" alt="" />', |
2445
|
|
|
'href' => $modSettings['avatar_url'] . '/' . $profile['avatar'], |
2446
|
|
|
'url' => $modSettings['avatar_url'] . '/' . $profile['avatar'], |
2447
|
|
|
); |
2448
|
|
|
} |
2449
|
|
|
// no custom avatar found yet, maybe a default avatar? |
2450
|
1 |
|
elseif (!empty($modSettings['avatar_default']) && empty($profile['avatar']) && empty($profile['filename'])) |
2451
|
|
|
{ |
2452
|
|
|
// $settings not initialized? We can't do anything further.. |
2453
|
|
|
if (!empty($settings)) |
2454
|
|
|
{ |
2455
|
|
|
// Let's proceed with the default avatar. |
2456
|
|
|
$avatar = array( |
2457
|
|
|
'name' => '', |
2458
|
|
|
'image' => '<img class="avatar avatarresize" src="' . $settings['images_url'] . '/default_avatar.png" alt="" />', |
2459
|
|
|
'href' => $settings['images_url'] . '/default_avatar.png', |
2460
|
|
|
'url' => 'http://', |
2461
|
|
|
); |
2462
|
|
|
} |
2463
|
|
|
else |
2464
|
|
|
{ |
2465
|
|
|
$avatar = array(); |
2466
|
|
|
} |
2467
|
|
|
} |
2468
|
|
|
// finally ... |
2469
|
|
|
else |
2470
|
|
|
$avatar = array( |
2471
|
1 |
|
'name' => '', |
2472
|
1 |
|
'image' => '', |
2473
|
1 |
|
'href' => '', |
2474
|
|
|
'url' => '' |
2475
|
1 |
|
); |
2476
|
|
|
|
2477
|
|
|
// Make sure there's a preview for gravatars available. |
2478
|
1 |
|
$avatar['gravatar_preview'] = '//www.gravatar.com/avatar/' . hash('md5', strtolower($profile['email_address'])) . '?s=' . $modSettings['avatar_max_height'] . (!empty($modSettings['gravatar_rating']) ? ('&r=' . $modSettings['gravatar_rating']) : ''); |
2479
|
|
|
|
2480
|
1 |
|
call_integration_hook('integrate_avatar', array(&$avatar, $profile)); |
2481
|
|
|
|
2482
|
1 |
|
return $avatar; |
2483
|
|
|
} |
2484
|
|
|
|
2485
|
|
|
/** |
2486
|
|
|
* Get information about the server |
2487
|
|
|
*/ |
2488
|
|
|
function detectServer() |
|
|
|
|
2489
|
|
|
{ |
2490
|
8 |
|
global $context; |
2491
|
8 |
|
static $server = null; |
2492
|
|
|
|
2493
|
8 |
|
if ($server === null) |
2494
|
8 |
|
{ |
2495
|
1 |
|
$server = new Server($_SERVER); |
2496
|
1 |
|
$servers = array('iis', 'apache', 'litespeed', 'lighttpd', 'nginx', 'cgi', 'windows'); |
2497
|
1 |
|
$context['server'] = array(); |
2498
|
1 |
|
foreach ($servers as $name) |
2499
|
|
|
{ |
2500
|
1 |
|
$context['server']['is_' . $name] = $server->is($name); |
2501
|
1 |
|
} |
2502
|
|
|
|
2503
|
1 |
|
$context['server']['iso_case_folding'] = $server->is('iso_case_folding'); |
2504
|
|
|
// A bug in some versions of IIS under CGI (older ones) makes cookie setting not work with Location: headers. |
2505
|
1 |
|
$context['server']['needs_login_fix'] = $server->is('needs_login_fix'); |
2506
|
1 |
|
} |
2507
|
|
|
|
2508
|
8 |
|
return $server; |
2509
|
|
|
} |
2510
|
|
|
|
2511
|
|
|
function serverIs($server) |
2512
|
|
|
{ |
2513
|
|
|
return detectServer()->is($server); |
2514
|
|
|
} |
2515
|
|
|
|
2516
|
|
|
/** |
2517
|
|
|
* Do some important security checks: |
2518
|
|
|
* |
2519
|
|
|
* What it does: |
2520
|
|
|
* - checks the existence of critical files e.g. install.php |
2521
|
|
|
* - checks for an active admin session. |
2522
|
|
|
* - checks cache directory is writable. |
2523
|
|
|
* - calls secureDirectory to protect attachments & cache. |
2524
|
|
|
* - checks if the forum is in maintenance mode. |
2525
|
|
|
*/ |
2526
|
|
|
function doSecurityChecks() |
|
|
|
|
2527
|
|
|
{ |
2528
|
|
|
global $modSettings, $context, $maintenance, $user_info, $txt, $scripturl, $user_settings, $options; |
2529
|
|
|
|
2530
|
|
|
$show_warnings = false; |
2531
|
|
|
|
2532
|
|
|
$cache = Cache::instance(); |
2533
|
|
|
|
2534
|
|
|
if (allowedTo('admin_forum') && !$user_info['is_guest']) |
2535
|
|
|
{ |
2536
|
|
|
// If agreement is enabled, at least the english version shall exists |
2537
|
|
View Code Duplication |
if ($modSettings['requireAgreement'] && !file_exists(BOARDDIR . '/agreement.txt')) |
2538
|
|
|
{ |
2539
|
|
|
$context['security_controls_files']['title'] = $txt['generic_warning']; |
2540
|
|
|
$context['security_controls_files']['errors']['agreement'] = $txt['agreement_missing']; |
2541
|
|
|
$show_warnings = true; |
2542
|
|
|
} |
2543
|
|
|
|
2544
|
|
|
// Cache directory writable? |
2545
|
|
View Code Duplication |
if ($cache->isEnabled() && !is_writable(CACHEDIR)) |
2546
|
|
|
{ |
2547
|
|
|
$context['security_controls_files']['title'] = $txt['generic_warning']; |
2548
|
|
|
$context['security_controls_files']['errors']['cache'] = $txt['cache_writable']; |
2549
|
|
|
$show_warnings = true; |
2550
|
|
|
} |
2551
|
|
|
|
2552
|
|
|
if (checkSecurityFiles()) |
2553
|
|
|
$show_warnings = true; |
2554
|
|
|
|
2555
|
|
|
// We are already checking so many files...just few more doesn't make any difference! :P |
2556
|
|
|
require_once(SUBSDIR . '/Attachments.subs.php'); |
2557
|
|
|
$path = getAttachmentPath(); |
2558
|
|
|
secureDirectory($path, true); |
2559
|
|
|
secureDirectory(CACHEDIR); |
2560
|
|
|
|
2561
|
|
|
// Active admin session? |
2562
|
|
|
if (isAdminSessionActive()) |
2563
|
|
|
$context['warning_controls']['admin_session'] = sprintf($txt['admin_session_active'], ($scripturl . '?action=admin;area=adminlogoff;redir;' . $context['session_var'] . '=' . $context['session_id'])); |
2564
|
|
|
|
2565
|
|
|
// Maintenance mode enabled? |
2566
|
|
|
if (!empty($maintenance)) |
2567
|
|
|
$context['warning_controls']['maintenance'] = sprintf($txt['admin_maintenance_active'], ($scripturl . '?action=admin;area=serversettings;' . $context['session_var'] . '=' . $context['session_id'])); |
2568
|
|
|
|
2569
|
|
|
// New updates |
2570
|
|
|
if (defined('FORUM_VERSION')) |
2571
|
|
|
{ |
2572
|
|
|
$index = 'new_in_' . str_replace(array('ElkArte ', '.'), array('', '_'), FORUM_VERSION); |
2573
|
|
|
if (!empty($modSettings[$index]) && empty($options['dismissed_' . $index])) |
2574
|
|
|
{ |
2575
|
|
|
$show_warnings = true; |
2576
|
|
|
$context['new_version_updates'] = array( |
2577
|
|
|
'title' => $txt['new_version_updates'], |
2578
|
|
|
'errors' => array(replaceBasicActionUrl($txt['new_version_updates_text'])), |
2579
|
|
|
); |
2580
|
|
|
} |
2581
|
|
|
} |
2582
|
|
|
} |
2583
|
|
|
|
2584
|
|
|
// Check for database errors. |
2585
|
|
|
if (!empty($_SESSION['query_command_denied'])) |
2586
|
|
|
{ |
2587
|
|
|
if ($user_info['is_admin']) |
2588
|
|
|
{ |
2589
|
|
|
$context['security_controls_query']['title'] = $txt['query_command_denied']; |
2590
|
|
|
$show_warnings = true; |
2591
|
|
View Code Duplication |
foreach ($_SESSION['query_command_denied'] as $command => $error) |
2592
|
|
|
$context['security_controls_query']['errors'][$command] = '<pre>' . Util::htmlspecialchars($error) . '</pre>'; |
2593
|
|
|
} |
2594
|
|
|
else |
2595
|
|
|
{ |
2596
|
|
|
$context['security_controls_query']['title'] = $txt['query_command_denied_guests']; |
2597
|
|
View Code Duplication |
foreach ($_SESSION['query_command_denied'] as $command => $error) |
2598
|
|
|
$context['security_controls_query']['errors'][$command] = '<pre>' . sprintf($txt['query_command_denied_guests_msg'], Util::htmlspecialchars($command)) . '</pre>'; |
2599
|
|
|
} |
2600
|
|
|
} |
2601
|
|
|
|
2602
|
|
|
// Are there any members waiting for approval? |
2603
|
|
|
if (allowedTo('moderate_forum') && ((!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2) || !empty($modSettings['approveAccountDeletion'])) && !empty($modSettings['unapprovedMembers'])) |
2604
|
|
|
$context['warning_controls']['unapproved_members'] = sprintf($txt[$modSettings['unapprovedMembers'] == 1 ? 'approve_one_member_waiting' : 'approve_many_members_waiting'], $scripturl . '?action=admin;area=viewmembers;sa=browse;type=approve', $modSettings['unapprovedMembers']); |
2605
|
|
|
|
2606
|
|
|
if (!empty($context['open_mod_reports']) && (empty($user_settings['mod_prefs']) || $user_settings['mod_prefs'][0] == 1)) |
2607
|
|
|
$context['warning_controls']['open_mod_reports'] = '<a href="' . $scripturl . '?action=moderate;area=reports">' . sprintf($txt['mod_reports_waiting'], $context['open_mod_reports']) . '</a>'; |
2608
|
|
|
|
2609
|
|
|
if (isset($_SESSION['ban']['cannot_post'])) |
2610
|
|
|
{ |
2611
|
|
|
// An admin cannot be banned (technically he could), and if it is better he knows. |
2612
|
|
|
$context['security_controls_ban']['title'] = sprintf($txt['you_are_post_banned'], $user_info['is_guest'] ? $txt['guest_title'] : $user_info['name']); |
2613
|
|
|
$show_warnings = true; |
2614
|
|
|
|
2615
|
|
|
$context['security_controls_ban']['errors']['reason'] = ''; |
2616
|
|
|
|
2617
|
|
|
if (!empty($_SESSION['ban']['cannot_post']['reason'])) |
2618
|
|
|
$context['security_controls_ban']['errors']['reason'] = $_SESSION['ban']['cannot_post']['reason']; |
2619
|
|
|
|
2620
|
|
|
if (!empty($_SESSION['ban']['expire_time'])) |
2621
|
|
|
$context['security_controls_ban']['errors']['reason'] .= '<span class="smalltext">' . sprintf($txt['your_ban_expires'], standardTime($_SESSION['ban']['expire_time'], false)) . '</span>'; |
2622
|
|
|
else |
2623
|
|
|
$context['security_controls_ban']['errors']['reason'] .= '<span class="smalltext">' . $txt['your_ban_expires_never'] . '</span>'; |
2624
|
|
|
} |
2625
|
|
|
|
2626
|
|
|
// Finally, let's show the layer. |
2627
|
|
|
if ($show_warnings || !empty($context['warning_controls'])) |
2628
|
|
|
\Template_Layers::getInstance()->addAfter('admin_warning', 'body'); |
2629
|
|
|
} |
2630
|
|
|
|
2631
|
|
|
/** |
2632
|
|
|
* Load everything necessary for the BBC parsers |
2633
|
|
|
*/ |
2634
|
|
|
function loadBBCParsers() |
2635
|
|
|
{ |
2636
|
|
|
global $modSettings; |
2637
|
|
|
|
2638
|
|
|
// Set the default disabled BBC |
2639
|
|
|
if (!empty($modSettings['disabledBBC'])) |
2640
|
|
|
{ |
2641
|
|
|
if (!is_array($modSettings['disabledBBC'])) |
2642
|
|
|
$disabledBBC = explode(',', $modSettings['disabledBBC']); |
2643
|
|
|
else |
2644
|
|
|
$disabledBBC = $modSettings['disabledBBC']; |
2645
|
|
|
\BBC\ParserWrapper::getInstance()->setDisabled($disabledBBC); |
2646
|
|
|
} |
2647
|
|
|
} |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.