1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* The main purpose of this file is to show a list of all errors that were |
5
|
|
|
* logged on the forum, and allow filtering and deleting them. |
6
|
|
|
* |
7
|
|
|
* Simple Machines Forum (SMF) |
8
|
|
|
* |
9
|
|
|
* @package SMF |
10
|
|
|
* @author Simple Machines https://www.simplemachines.org |
11
|
|
|
* @copyright 2022 Simple Machines and individual contributors |
12
|
|
|
* @license https://www.simplemachines.org/about/smf/license.php BSD |
13
|
|
|
* |
14
|
|
|
* @version 2.1.0 |
15
|
|
|
*/ |
16
|
|
|
|
17
|
|
|
if (!defined('SMF')) |
18
|
|
|
die('No direct access...'); |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* View the forum's error log. |
22
|
|
|
* This function sets all the context up to show the error log for maintenance. |
23
|
|
|
* It requires the maintain_forum permission. |
24
|
|
|
* It is accessed from ?action=admin;area=logs;sa=errorlog. |
25
|
|
|
* |
26
|
|
|
* @uses template_error_log() |
27
|
|
|
*/ |
28
|
|
|
function ViewErrorLog() |
29
|
|
|
{ |
30
|
|
|
global $scripturl, $txt, $context, $modSettings, $user_profile, $filter, $smcFunc; |
31
|
|
|
|
32
|
|
|
// Viewing contents of a file? |
33
|
|
|
if (isset($_GET['file'])) |
34
|
|
|
return ViewFile(); |
35
|
|
|
|
36
|
|
|
// Viewing contents of a backtrace? |
37
|
|
|
if (isset($_GET['backtrace'])) |
38
|
|
|
return ViewBacktrace(); |
39
|
|
|
|
40
|
|
|
// Check for the administrative permission to do this. |
41
|
|
|
isAllowedTo('admin_forum'); |
42
|
|
|
|
43
|
|
|
// Templates, etc... |
44
|
|
|
loadLanguage('ManageMaintenance'); |
45
|
|
|
loadTemplate('Errors'); |
46
|
|
|
|
47
|
|
|
// You can filter by any of the following columns: |
48
|
|
|
$filters = array( |
49
|
|
|
'id_member' => array( |
50
|
|
|
'txt' => $txt['username'], |
51
|
|
|
'operator' => '=', |
52
|
|
|
'datatype' => 'int', |
53
|
|
|
), |
54
|
|
|
'ip' => array( |
55
|
|
|
'txt' => $txt['ip_address'], |
56
|
|
|
'operator' => '=', |
57
|
|
|
'datatype' => 'inet', |
58
|
|
|
), |
59
|
|
|
'session' => array( |
60
|
|
|
'txt' => $txt['session'], |
61
|
|
|
'operator' => 'LIKE', |
62
|
|
|
'datatype' => 'string', |
63
|
|
|
), |
64
|
|
|
'url' => array( |
65
|
|
|
'txt' => $txt['error_url'], |
66
|
|
|
'operator' => 'LIKE', |
67
|
|
|
'datatype' => 'string', |
68
|
|
|
), |
69
|
|
|
'message' => array( |
70
|
|
|
'txt' => $txt['error_message'], |
71
|
|
|
'operator' => 'LIKE', |
72
|
|
|
'datatype' => 'string', |
73
|
|
|
), |
74
|
|
|
'error_type' => array( |
75
|
|
|
'txt' => $txt['error_type'], |
76
|
|
|
'operator' => 'LIKE', |
77
|
|
|
'datatype' => 'string', |
78
|
|
|
), |
79
|
|
|
'file' => array( |
80
|
|
|
'txt' => $txt['file'], |
81
|
|
|
'operator' => 'LIKE', |
82
|
|
|
'datatype' => 'string', |
83
|
|
|
), |
84
|
|
|
'line' => array( |
85
|
|
|
'txt' => $txt['line'], |
86
|
|
|
'operator' => '=', |
87
|
|
|
'datatype' => 'int', |
88
|
|
|
), |
89
|
|
|
); |
90
|
|
|
|
91
|
|
|
// Set up the filtering... |
92
|
|
|
if (isset($_GET['value'], $_GET['filter']) && isset($filters[$_GET['filter']])) |
93
|
|
|
$filter = array( |
94
|
|
|
'variable' => $_GET['filter'], |
95
|
|
|
'value' => array( |
96
|
|
|
'sql' => in_array($_GET['filter'], array('message', 'url', 'file')) ? base64_decode(strtr($_GET['value'], array(' ' => '+'))) : $smcFunc['db_escape_wildcard_string']($_GET['value']), |
97
|
|
|
), |
98
|
|
|
'href' => ';filter=' . $_GET['filter'] . ';value=' . $_GET['value'], |
99
|
|
|
'entity' => $filters[$_GET['filter']]['txt'] |
100
|
|
|
); |
101
|
|
|
|
102
|
|
|
// Deleting, are we? |
103
|
|
|
if (isset($_POST['delall']) || isset($_POST['delete'])) |
104
|
|
|
deleteErrors(); |
105
|
|
|
|
106
|
|
|
// Just how many errors are there? |
107
|
|
|
$result = $smcFunc['db_query']('', ' |
108
|
|
|
SELECT COUNT(*) |
109
|
|
|
FROM {db_prefix}log_errors' . (isset($filter) ? ' |
110
|
|
|
WHERE ' . $filter['variable'] . ' ' . $filters[$_GET['filter']]['operator'] . ' {' . $filters[$_GET['filter']]['datatype'] . ':filter}' : ''), |
111
|
|
|
array( |
112
|
|
|
'filter' => isset($filter) ? $filter['value']['sql'] : '', |
113
|
|
|
) |
114
|
|
|
); |
115
|
|
|
list ($num_errors) = $smcFunc['db_fetch_row']($result); |
116
|
|
|
$smcFunc['db_free_result']($result); |
117
|
|
|
|
118
|
|
|
// If this filter is empty... |
119
|
|
|
if ($num_errors == 0 && isset($filter)) |
120
|
|
|
redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '')); |
121
|
|
|
|
122
|
|
|
// Clean up start. |
123
|
|
|
if (!isset($_GET['start']) || $_GET['start'] < 0) |
124
|
|
|
$_GET['start'] = 0; |
125
|
|
|
|
126
|
|
|
// Do we want to reverse error listing? |
127
|
|
|
$context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up'; |
128
|
|
|
|
129
|
|
|
// Set the page listing up. |
130
|
|
|
$context['page_index'] = constructPageIndex($scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : '') . (isset($filter) ? $filter['href'] : ''), $_GET['start'], $num_errors, $modSettings['defaultMaxListItems']); |
131
|
|
|
$context['start'] = $_GET['start']; |
132
|
|
|
|
133
|
|
|
// Update the error count |
134
|
|
|
if (!isset($filter)) |
135
|
|
|
$context['num_errors'] = $num_errors; |
136
|
|
|
else |
137
|
|
|
{ |
138
|
|
|
// We want all errors, not just the number of filtered messages... |
139
|
|
|
$query = $smcFunc['db_query']('', ' |
140
|
|
|
SELECT COUNT(*) |
141
|
|
|
FROM {db_prefix}log_errors', |
142
|
|
|
array() |
143
|
|
|
); |
144
|
|
|
|
145
|
|
|
list($context['num_errors']) = $smcFunc['db_fetch_row']($query); |
146
|
|
|
$smcFunc['db_free_result']($query); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
// Find and sort out the errors. |
150
|
|
|
$request = $smcFunc['db_query']('', ' |
151
|
|
|
SELECT id_error, id_member, ip, url, log_time, message, session, error_type, file, line |
152
|
|
|
FROM {db_prefix}log_errors' . (isset($filter) ? ' |
153
|
|
|
WHERE ' . $filter['variable'] . ' ' . $filters[$_GET['filter']]['operator'] . ' {' . $filters[$_GET['filter']]['datatype'] . ':filter}' : '') . ' |
154
|
|
|
ORDER BY id_error ' . ($context['sort_direction'] == 'down' ? 'DESC' : '') . ' |
155
|
|
|
LIMIT {int:start}, {int:max}', |
156
|
|
|
array( |
157
|
|
|
'filter' => isset($filter) ? $filter['value']['sql'] : '', |
158
|
|
|
'start' => $_GET['start'], |
159
|
|
|
'max' => $modSettings['defaultMaxListItems'], |
160
|
|
|
) |
161
|
|
|
); |
162
|
|
|
$context['errors'] = array(); |
163
|
|
|
$members = array(); |
164
|
|
|
|
165
|
|
|
for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i++) |
166
|
|
|
{ |
167
|
|
|
$search_message = preg_replace('~<span class="remove">(.+?)</span>~', '%', $smcFunc['db_escape_wildcard_string']($row['message'])); |
168
|
|
|
|
169
|
|
|
if (isset($filter) && $search_message == $filter['value']['sql']) |
170
|
|
|
$search_message = $smcFunc['db_escape_wildcard_string']($row['message']); |
171
|
|
|
|
172
|
|
|
$show_message = strtr(strtr(preg_replace('~<span class="remove">(.+?)</span>~', '$1', $row['message']), array("\r" => '', '<br>' => "\n", '<' => '<', '>' => '>', '"' => '"')), array("\n" => '<br>')); |
173
|
|
|
|
174
|
|
|
$context['errors'][$row['id_error']] = array( |
175
|
|
|
'member' => array( |
176
|
|
|
'id' => $row['id_member'], |
177
|
|
|
'ip' => inet_dtop($row['ip']), |
178
|
|
|
'session' => $row['session'] |
179
|
|
|
), |
180
|
|
|
'time' => timeformat($row['log_time']), |
181
|
|
|
'timestamp' => $row['log_time'], |
182
|
|
|
'url' => array( |
183
|
|
|
'html' => $smcFunc['htmlspecialchars'](strpos($row['url'], 'cron.php') === false ? (substr($row['url'], 0, 1) == '?' ? $scripturl : '') . $row['url'] : $row['url']), |
184
|
|
|
'href' => base64_encode($smcFunc['db_escape_wildcard_string']($row['url'])) |
185
|
|
|
), |
186
|
|
|
'message' => array( |
187
|
|
|
'html' => $show_message, |
188
|
|
|
'href' => base64_encode($search_message) |
189
|
|
|
), |
190
|
|
|
'id' => $row['id_error'], |
191
|
|
|
'error_type' => array( |
192
|
|
|
'type' => $row['error_type'], |
193
|
|
|
'name' => isset($txt['errortype_' . $row['error_type']]) ? $txt['errortype_' . $row['error_type']] : $row['error_type'], |
194
|
|
|
), |
195
|
|
|
'file' => array(), |
196
|
|
|
); |
197
|
|
|
if (!empty($row['file']) && !empty($row['line'])) |
198
|
|
|
{ |
199
|
|
|
// Eval'd files rarely point to the right location and cause havoc for linking, so don't link them. |
200
|
|
|
$linkfile = strpos($row['file'], 'eval') === false || strpos($row['file'], '?') === false; // De Morgan's Law. Want this true unless both are present. |
201
|
|
|
|
202
|
|
|
$context['errors'][$row['id_error']]['file'] = array( |
203
|
|
|
'file' => $row['file'], |
204
|
|
|
'line' => $row['line'], |
205
|
|
|
'href' => $scripturl . '?action=admin;area=logs;sa=errorlog;file=' . base64_encode($row['file']) . ';line=' . $row['line'], |
206
|
|
|
'link' => $linkfile ? '<a href="' . $scripturl . '?action=admin;area=logs;sa=errorlog;file=' . base64_encode($row['file']) . ';line=' . $row['line'] . '" onclick="return reqWin(this.href, 600, 480, false);">' . $row['file'] . '</a>' : $row['file'], |
207
|
|
|
'search' => base64_encode($row['file']), |
208
|
|
|
); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
// Make a list of members to load later. |
212
|
|
|
$members[$row['id_member']] = $row['id_member']; |
213
|
|
|
} |
214
|
|
|
$smcFunc['db_free_result']($request); |
215
|
|
|
|
216
|
|
|
// Load the member data. |
217
|
|
|
if (!empty($members)) |
218
|
|
|
{ |
219
|
|
|
// Get some additional member info... |
220
|
|
|
$request = $smcFunc['db_query']('', ' |
221
|
|
|
SELECT id_member, member_name, real_name |
222
|
|
|
FROM {db_prefix}members |
223
|
|
|
WHERE id_member IN ({array_int:member_list}) |
224
|
|
|
LIMIT {int:members}', |
225
|
|
|
array( |
226
|
|
|
'member_list' => $members, |
227
|
|
|
'members' => count($members), |
228
|
|
|
) |
229
|
|
|
); |
230
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
231
|
|
|
$members[$row['id_member']] = $row; |
232
|
|
|
$smcFunc['db_free_result']($request); |
233
|
|
|
|
234
|
|
|
// This is a guest... |
235
|
|
|
$members[0] = array( |
236
|
|
|
'id_member' => 0, |
237
|
|
|
'member_name' => '', |
238
|
|
|
'real_name' => $txt['guest_title'] |
239
|
|
|
); |
240
|
|
|
|
241
|
|
|
// Go through each error and tack the data on. |
242
|
|
|
foreach ($context['errors'] as $id => $dummy) |
243
|
|
|
{ |
244
|
|
|
$memID = $context['errors'][$id]['member']['id']; |
245
|
|
|
$context['errors'][$id]['member']['username'] = $members[$memID]['member_name']; |
246
|
|
|
$context['errors'][$id]['member']['name'] = $members[$memID]['real_name']; |
247
|
|
|
$context['errors'][$id]['member']['href'] = empty($memID) ? '' : $scripturl . '?action=profile;u=' . $memID; |
248
|
|
|
$context['errors'][$id]['member']['link'] = empty($memID) ? $txt['guest_title'] : '<a href="' . $scripturl . '?action=profile;u=' . $memID . '">' . $context['errors'][$id]['member']['name'] . '</a>'; |
249
|
|
|
} |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
// Filtering anything? |
253
|
|
|
if (isset($filter)) |
254
|
|
|
{ |
255
|
|
|
$context['filter'] = &$filter; |
256
|
|
|
|
257
|
|
|
// Set the filtering context. |
258
|
|
|
if ($filter['variable'] == 'id_member') |
259
|
|
|
{ |
260
|
|
|
$id = $filter['value']['sql']; |
261
|
|
|
loadMemberData($id, false, 'minimal'); |
262
|
|
|
$context['filter']['value']['html'] = '<a href="' . $scripturl . '?action=profile;u=' . $id . '">' . $user_profile[$id]['real_name'] . '</a>'; |
263
|
|
|
} |
264
|
|
|
elseif ($filter['variable'] == 'url') |
265
|
|
|
$context['filter']['value']['html'] = '\'' . strtr($smcFunc['htmlspecialchars']((substr($filter['value']['sql'], 0, 1) == '?' ? $scripturl : '') . $filter['value']['sql']), array('\_' => '_')) . '\''; |
266
|
|
|
elseif ($filter['variable'] == 'message') |
267
|
|
|
{ |
268
|
|
|
$context['filter']['value']['html'] = '\'' . strtr($smcFunc['htmlspecialchars']($filter['value']['sql']), array("\n" => '<br>', '<br />' => '<br>', "\t" => ' ', '\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; |
269
|
|
|
$context['filter']['value']['html'] = preg_replace('~&lt;span class=&quot;remove&quot;&gt;(.+?)&lt;/span&gt;~', '$1', $context['filter']['value']['html']); |
270
|
|
|
} |
271
|
|
|
elseif ($filter['variable'] == 'error_type') |
272
|
|
|
{ |
273
|
|
|
$context['filter']['value']['html'] = '\'' . strtr($smcFunc['htmlspecialchars']($filter['value']['sql']), array("\n" => '<br>', '<br />' => '<br>', "\t" => ' ', '\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; |
274
|
|
|
} |
275
|
|
|
else |
276
|
|
|
$context['filter']['value']['html'] = &$filter['value']['sql']; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
$context['error_types'] = array(); |
280
|
|
|
|
281
|
|
|
$context['error_types']['all'] = array( |
282
|
|
|
'label' => $txt['errortype_all'], |
283
|
|
|
'error_type' => 'all', |
284
|
|
|
'description' => isset($txt['errortype_all_desc']) ? $txt['errortype_all_desc'] : '', |
285
|
|
|
'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : ''), |
286
|
|
|
'is_selected' => empty($filter), |
287
|
|
|
); |
288
|
|
|
|
289
|
|
|
$sum = 0; |
290
|
|
|
// What type of errors do we have and how many do we have? |
291
|
|
|
$request = $smcFunc['db_query']('', ' |
292
|
|
|
SELECT error_type, COUNT(*) AS num_errors |
293
|
|
|
FROM {db_prefix}log_errors |
294
|
|
|
GROUP BY error_type |
295
|
|
|
ORDER BY error_type = {string:critical_type} DESC, error_type ASC', |
296
|
|
|
array( |
297
|
|
|
'critical_type' => 'critical', |
298
|
|
|
) |
299
|
|
|
); |
300
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
301
|
|
|
{ |
302
|
|
|
// Total errors so far? |
303
|
|
|
$sum += $row['num_errors']; |
304
|
|
|
|
305
|
|
|
$context['error_types'][$sum] = array( |
306
|
|
|
'label' => (isset($txt['errortype_' . $row['error_type']]) ? $txt['errortype_' . $row['error_type']] : $row['error_type']) . ' (' . $row['num_errors'] . ')', |
307
|
|
|
'error_type' => $row['error_type'], |
308
|
|
|
'description' => isset($txt['errortype_' . $row['error_type'] . '_desc']) ? $txt['errortype_' . $row['error_type'] . '_desc'] : '', |
309
|
|
|
'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : '') . ';filter=error_type;value=' . $row['error_type'], |
310
|
|
|
'is_selected' => isset($filter) && $filter['value']['sql'] == $smcFunc['db_escape_wildcard_string']($row['error_type']), |
311
|
|
|
); |
312
|
|
|
} |
313
|
|
|
$smcFunc['db_free_result']($request); |
314
|
|
|
|
315
|
|
|
// Update the all errors tab with the total number of errors |
316
|
|
|
$context['error_types']['all']['label'] .= ' (' . $sum . ')'; |
317
|
|
|
|
318
|
|
|
// Finally, work out what is the last tab! |
319
|
|
|
if (isset($context['error_types'][$sum])) |
320
|
|
|
$context['error_types'][$sum]['is_last'] = true; |
321
|
|
|
else |
322
|
|
|
$context['error_types']['all']['is_last'] = true; |
323
|
|
|
|
324
|
|
|
// And this is pretty basic ;). |
325
|
|
|
$context['page_title'] = $txt['errorlog']; |
326
|
|
|
$context['has_filter'] = isset($filter); |
327
|
|
|
$context['sub_template'] = 'error_log'; |
328
|
|
|
|
329
|
|
|
createToken('admin-el'); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Delete all or some of the errors in the error log. |
334
|
|
|
* It applies any necessary filters to deletion. |
335
|
|
|
* This should only be called by ViewErrorLog(). |
336
|
|
|
* It attempts to TRUNCATE the table to reset the auto_increment. |
337
|
|
|
* Redirects back to the error log when done. |
338
|
|
|
*/ |
339
|
|
|
function deleteErrors() |
340
|
|
|
{ |
341
|
|
|
global $filter, $smcFunc; |
342
|
|
|
|
343
|
|
|
// Make sure the session exists and is correct; otherwise, might be a hacker. |
344
|
|
|
checkSession(); |
345
|
|
|
validateToken('admin-el'); |
346
|
|
|
|
347
|
|
|
// Delete all or just some? |
348
|
|
|
if (isset($_POST['delall']) && !isset($filter)) |
349
|
|
|
$smcFunc['db_query']('truncate_table', ' |
350
|
|
|
TRUNCATE {db_prefix}log_errors', |
351
|
|
|
array( |
352
|
|
|
) |
353
|
|
|
); |
354
|
|
|
// Deleting all with a filter? |
355
|
|
|
elseif (isset($_POST['delall']) && isset($filter)) |
356
|
|
|
{ |
357
|
|
|
// ip need a different placeholder type |
358
|
|
|
$filter_type = $filter['variable'] == 'ip'? 'inet' : 'string'; |
359
|
|
|
$filter_op = $filter['variable'] == 'ip'? '=' : 'LIKE'; |
360
|
|
|
$smcFunc['db_query']('', ' |
361
|
|
|
DELETE FROM {db_prefix}log_errors |
362
|
|
|
WHERE ' . $filter['variable'] . ' ' . $filter_op . ' {' . $filter_type . ':filter}', |
363
|
|
|
array( |
364
|
|
|
'filter' => $filter['value']['sql'], |
365
|
|
|
) |
366
|
|
|
); |
367
|
|
|
} |
368
|
|
|
// Just specific errors? |
369
|
|
|
elseif (!empty($_POST['delete'])) |
370
|
|
|
{ |
371
|
|
|
$smcFunc['db_query']('', ' |
372
|
|
|
DELETE FROM {db_prefix}log_errors |
373
|
|
|
WHERE id_error IN ({array_int:error_list})', |
374
|
|
|
array( |
375
|
|
|
'error_list' => array_unique($_POST['delete']), |
376
|
|
|
) |
377
|
|
|
); |
378
|
|
|
|
379
|
|
|
// Go back to where we were. |
380
|
|
|
redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '') . ';start=' . $_GET['start'] . (isset($filter) ? ';filter=' . $_GET['filter'] . ';value=' . $_GET['value'] : '')); |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
// Back to the error log! |
384
|
|
|
redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '')); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* View a file specified in $_REQUEST['file'], with php highlighting on it |
389
|
|
|
* Preconditions: |
390
|
|
|
* - file must be readable, |
391
|
|
|
* - full file path must be base64 encoded, |
392
|
|
|
* - user must have admin_forum permission. |
393
|
|
|
* The line number number is specified by $_REQUEST['line']... |
394
|
|
|
* The function will try to get the 20 lines before and after the specified line. |
395
|
|
|
*/ |
396
|
|
|
function ViewFile() |
397
|
|
|
{ |
398
|
|
|
global $context, $boarddir, $sourcedir, $cachedir, $smcFunc; |
399
|
|
|
|
400
|
|
|
// Check for the administrative permission to do this. |
401
|
|
|
isAllowedTo('admin_forum'); |
402
|
|
|
|
403
|
|
|
// Decode the file and get the line |
404
|
|
|
$file = realpath(base64_decode($_REQUEST['file'])); |
405
|
|
|
$real_board = realpath($boarddir); |
406
|
|
|
$real_source = realpath($sourcedir); |
407
|
|
|
$real_cache = realpath($cachedir); |
408
|
|
|
$basename = strtolower(basename($file)); |
409
|
|
|
$ext = strrchr($basename, '.'); |
410
|
|
|
$line = isset($_REQUEST['line']) ? (int) $_REQUEST['line'] : 0; |
411
|
|
|
|
412
|
|
|
// Make sure the file we are looking for is one they are allowed to look at |
413
|
|
|
if ($ext != '.php' || (strpos($file, $real_board) === false && strpos($file, $real_source) === false) || ($basename == 'settings.php' || $basename == 'settings_bak.php') || strpos($file, $real_cache) !== false || !is_readable($file)) |
414
|
|
|
fatal_lang_error('error_bad_file', true, array($smcFunc['htmlspecialchars']($file))); |
415
|
|
|
|
416
|
|
|
// get the min and max lines |
417
|
|
|
$min = $line - 20 <= 0 ? 1 : $line - 20; |
418
|
|
|
$max = $line + 21; // One additional line to make everything work out correctly |
419
|
|
|
|
420
|
|
|
if ($max <= 0 || $min >= $max) |
421
|
|
|
fatal_lang_error('error_bad_line'); |
422
|
|
|
|
423
|
|
|
$file_data = explode('<br />', highlight_php_code($smcFunc['htmlspecialchars'](implode('', file($file))))); |
424
|
|
|
|
425
|
|
|
// We don't want to slice off too many so lets make sure we stop at the last one |
426
|
|
|
$max = min($max, max(array_keys($file_data))); |
427
|
|
|
|
428
|
|
|
$file_data = array_slice($file_data, $min - 1, $max - $min); |
429
|
|
|
|
430
|
|
|
$context['file_data'] = array( |
431
|
|
|
'contents' => $file_data, |
432
|
|
|
'min' => $min, |
433
|
|
|
'target' => $line, |
434
|
|
|
'file' => strtr($file, array('"' => '\\"')), |
435
|
|
|
); |
436
|
|
|
|
437
|
|
|
loadTemplate('Errors'); |
438
|
|
|
$context['template_layers'] = array(); |
439
|
|
|
$context['sub_template'] = 'show_file'; |
440
|
|
|
|
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
/** |
444
|
|
|
* View a backtrace specified in $_REQUEST['backtrace'], with php highlighting on it |
445
|
|
|
* Preconditions: |
446
|
|
|
* - user must have admin_forum permission. |
447
|
|
|
*/ |
448
|
|
|
function ViewBacktrace() |
449
|
|
|
{ |
450
|
|
|
global $context, $smcFunc, $scripturl; |
451
|
|
|
|
452
|
|
|
// Check for the administrative permission to do this. |
453
|
|
|
isAllowedTo('admin_forum'); |
454
|
|
|
|
455
|
|
|
$id_error = (int) $_REQUEST['backtrace']; |
456
|
|
|
$request = $smcFunc['db_query']('', ' |
457
|
|
|
SELECT backtrace, error_type, message, file, line, url |
458
|
|
|
FROM {db_prefix}log_errors |
459
|
|
|
WHERE id_error = {int:id_error}', |
460
|
|
|
array( |
461
|
|
|
'id_error' => $id_error, |
462
|
|
|
) |
463
|
|
|
); |
464
|
|
|
|
465
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
466
|
|
|
{ |
467
|
|
|
$context['error_info'] = $row; |
468
|
|
|
$context['error_info']['url'] = $scripturl . $row['url']; |
469
|
|
|
$context['error_info']['backtrace'] = $smcFunc['json_decode']($row['backtrace']); |
470
|
|
|
} |
471
|
|
|
$smcFunc['db_free_result']($request); |
472
|
|
|
|
473
|
|
|
loadCSSFile('admin.css', array(), 'smf_admin'); |
474
|
|
|
loadTemplate('Errors'); |
475
|
|
|
loadLanguage('ManageMaintenance'); |
476
|
|
|
$context['template_layers'] = array(); |
477
|
|
|
$context['sub_template'] = 'show_backtrace'; |
478
|
|
|
|
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
?> |