Mercurial > hg > vamp-website
comparison forum/Sources/ManageErrors.php @ 76:e3e11437ecea website
Add forum code
| author | Chris Cannam |
|---|---|
| date | Sun, 07 Jul 2013 11:25:48 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 75:72f59aa7e503 | 76:e3e11437ecea |
|---|---|
| 1 <?php | |
| 2 | |
| 3 /** | |
| 4 * Simple Machines Forum (SMF) | |
| 5 * | |
| 6 * @package SMF | |
| 7 * @author Simple Machines http://www.simplemachines.org | |
| 8 * @copyright 2011 Simple Machines | |
| 9 * @license http://www.simplemachines.org/about/smf/license.php BSD | |
| 10 * | |
| 11 * @version 2.0.4 | |
| 12 */ | |
| 13 | |
| 14 if (!defined('SMF')) | |
| 15 die('Hacking attempt...'); | |
| 16 | |
| 17 /* Show a list of all errors that were logged on the forum. | |
| 18 | |
| 19 void ViewErrorLog() | |
| 20 - sets all the context up to show the error log for maintenance. | |
| 21 - uses the Errors template and error_log sub template. | |
| 22 - requires the maintain_forum permission. | |
| 23 - uses the 'view_errors' administration area. | |
| 24 - accessed from ?action=admin;area=logs;sa=errorlog. | |
| 25 | |
| 26 void deleteErrors() | |
| 27 - deletes all or some of the errors in the error log. | |
| 28 - applies any necessary filters to deletion. | |
| 29 - should only be called by ViewErrorLog(). | |
| 30 - attempts to TRUNCATE the table to reset the auto_increment. | |
| 31 - redirects back to the error log when done. | |
| 32 | |
| 33 void ViewFile() | |
| 34 - will do php highlighting on the file specified in $_REQUEST['file'] | |
| 35 - file must be readable | |
| 36 - full file path must be base64 encoded | |
| 37 - user must have admin_forum permission | |
| 38 - the line number number is specified by $_REQUEST['line'] | |
| 39 - Will try to get the 20 lines before and after the specified line | |
| 40 */ | |
| 41 | |
| 42 // View the forum's error log. | |
| 43 function ViewErrorLog() | |
| 44 { | |
| 45 global $scripturl, $txt, $context, $modSettings, $user_profile, $filter, $boarddir, $sourcedir, $themedir, $smcFunc; | |
| 46 | |
| 47 // Viewing contents of a file? | |
| 48 if (isset($_GET['file'])) | |
| 49 return ViewFile(); | |
| 50 | |
| 51 // Check for the administrative permission to do this. | |
| 52 isAllowedTo('admin_forum'); | |
| 53 | |
| 54 // Templates, etc... | |
| 55 loadLanguage('ManageMaintenance'); | |
| 56 loadTemplate('Errors'); | |
| 57 | |
| 58 // You can filter by any of the following columns: | |
| 59 $filters = array( | |
| 60 'id_member' => $txt['username'], | |
| 61 'ip' => $txt['ip_address'], | |
| 62 'session' => $txt['session'], | |
| 63 'url' => $txt['error_url'], | |
| 64 'message' => $txt['error_message'], | |
| 65 'error_type' => $txt['error_type'], | |
| 66 'file' => $txt['file'], | |
| 67 'line' => $txt['line'], | |
| 68 ); | |
| 69 | |
| 70 // Set up the filtering... | |
| 71 if (isset($_GET['value'], $_GET['filter']) && isset($filters[$_GET['filter']])) | |
| 72 $filter = array( | |
| 73 'variable' => $_GET['filter'], | |
| 74 'value' => array( | |
| 75 'sql' => in_array($_GET['filter'], array('message', 'url', 'file')) ? base64_decode(strtr($_GET['value'], array(' ' => '+'))) : $smcFunc['db_escape_wildcard_string']($_GET['value']), | |
| 76 ), | |
| 77 'href' => ';filter=' . $_GET['filter'] . ';value=' . $_GET['value'], | |
| 78 'entity' => $filters[$_GET['filter']] | |
| 79 ); | |
| 80 | |
| 81 // Deleting, are we? | |
| 82 if (isset($_POST['delall']) || isset($_POST['delete'])) | |
| 83 deleteErrors(); | |
| 84 | |
| 85 // Just how many errors are there? | |
| 86 $result = $smcFunc['db_query']('', ' | |
| 87 SELECT COUNT(*) | |
| 88 FROM {db_prefix}log_errors' . (isset($filter) ? ' | |
| 89 WHERE ' . $filter['variable'] . ' LIKE {string:filter}' : ''), | |
| 90 array( | |
| 91 'filter' => isset($filter) ? $filter['value']['sql'] : '', | |
| 92 ) | |
| 93 ); | |
| 94 list ($num_errors) = $smcFunc['db_fetch_row']($result); | |
| 95 $smcFunc['db_free_result']($result); | |
| 96 | |
| 97 // If this filter is empty... | |
| 98 if ($num_errors == 0 && isset($filter)) | |
| 99 redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '')); | |
| 100 | |
| 101 // Clean up start. | |
| 102 if (!isset($_GET['start']) || $_GET['start'] < 0) | |
| 103 $_GET['start'] = 0; | |
| 104 | |
| 105 // Do we want to reverse error listing? | |
| 106 $context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up'; | |
| 107 | |
| 108 // Set the page listing up. | |
| 109 $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['defaultMaxMessages']); | |
| 110 $context['start'] = $_GET['start']; | |
| 111 | |
| 112 // Find and sort out the errors. | |
| 113 $request = $smcFunc['db_query']('', ' | |
| 114 SELECT id_error, id_member, ip, url, log_time, message, session, error_type, file, line | |
| 115 FROM {db_prefix}log_errors' . (isset($filter) ? ' | |
| 116 WHERE ' . $filter['variable'] . ' LIKE {string:filter}' : '') . ' | |
| 117 ORDER BY id_error ' . ($context['sort_direction'] == 'down' ? 'DESC' : '') . ' | |
| 118 LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'], | |
| 119 array( | |
| 120 'filter' => isset($filter) ? $filter['value']['sql'] : '', | |
| 121 ) | |
| 122 ); | |
| 123 $context['errors'] = array(); | |
| 124 $members = array(); | |
| 125 | |
| 126 for ($i = 0; $row = $smcFunc['db_fetch_assoc']($request); $i ++) | |
| 127 { | |
| 128 $search_message = preg_replace('~<span class="remove">(.+?)</span>~', '%', $smcFunc['db_escape_wildcard_string']($row['message'])); | |
| 129 if ($search_message == $filter['value']['sql']) | |
| 130 $search_message = $smcFunc['db_escape_wildcard_string']($row['message']); | |
| 131 $show_message = strtr(strtr(preg_replace('~<span class="remove">(.+?)</span>~', '$1', $row['message']), array("\r" => '', '<br />' => "\n", '<' => '<', '>' => '>', '"' => '"')), array("\n" => '<br />')); | |
| 132 | |
| 133 $context['errors'][$row['id_error']] = array( | |
| 134 'alternate' => $i %2 == 0, | |
| 135 'member' => array( | |
| 136 'id' => $row['id_member'], | |
| 137 'ip' => $row['ip'], | |
| 138 'session' => $row['session'] | |
| 139 ), | |
| 140 'time' => timeformat($row['log_time']), | |
| 141 'timestamp' => $row['log_time'], | |
| 142 'url' => array( | |
| 143 'html' => htmlspecialchars((substr($row['url'], 0, 1) == '?' ? $scripturl : '') . $row['url']), | |
| 144 'href' => base64_encode($smcFunc['db_escape_wildcard_string']($row['url'])) | |
| 145 ), | |
| 146 'message' => array( | |
| 147 'html' => $show_message, | |
| 148 'href' => base64_encode($search_message) | |
| 149 ), | |
| 150 'id' => $row['id_error'], | |
| 151 'error_type' => array( | |
| 152 'type' => $row['error_type'], | |
| 153 'name' => isset($txt['errortype_'.$row['error_type']]) ? $txt['errortype_'.$row['error_type']] : $row['error_type'], | |
| 154 ), | |
| 155 'file' => array(), | |
| 156 ); | |
| 157 if (!empty($row['file']) && !empty($row['line'])) | |
| 158 { | |
| 159 // Eval'd files rarely point to the right location and cause havoc for linking, so don't link them. | |
| 160 $linkfile = strpos($row['file'], 'eval') === false || strpos($row['file'], '?') === false; // De Morgan's Law. Want this true unless both are present. | |
| 161 | |
| 162 $context['errors'][$row['id_error']]['file'] = array( | |
| 163 'file' => $row['file'], | |
| 164 'line' => $row['line'], | |
| 165 'href' => $scripturl . '?action=admin;area=logs;sa=errorlog;file=' . base64_encode($row['file']) . ';line=' . $row['line'], | |
| 166 '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, 400, false);">' . $row['file'] . '</a>' : $row['file'], | |
| 167 'search' => base64_encode($row['file']), | |
| 168 ); | |
| 169 } | |
| 170 | |
| 171 // Make a list of members to load later. | |
| 172 $members[$row['id_member']] = $row['id_member']; | |
| 173 } | |
| 174 $smcFunc['db_free_result']($request); | |
| 175 | |
| 176 // Load the member data. | |
| 177 if (!empty($members)) | |
| 178 { | |
| 179 // Get some additional member info... | |
| 180 $request = $smcFunc['db_query']('', ' | |
| 181 SELECT id_member, member_name, real_name | |
| 182 FROM {db_prefix}members | |
| 183 WHERE id_member IN ({array_int:member_list}) | |
| 184 LIMIT ' . count($members), | |
| 185 array( | |
| 186 'member_list' => $members, | |
| 187 ) | |
| 188 ); | |
| 189 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
| 190 $members[$row['id_member']] = $row; | |
| 191 $smcFunc['db_free_result']($request); | |
| 192 | |
| 193 // This is a guest... | |
| 194 $members[0] = array( | |
| 195 'id_member' => 0, | |
| 196 'member_name' => '', | |
| 197 'real_name' => $txt['guest_title'] | |
| 198 ); | |
| 199 | |
| 200 // Go through each error and tack the data on. | |
| 201 foreach ($context['errors'] as $id => $dummy) | |
| 202 { | |
| 203 $memID = $context['errors'][$id]['member']['id']; | |
| 204 $context['errors'][$id]['member']['username'] = $members[$memID]['member_name']; | |
| 205 $context['errors'][$id]['member']['name'] = $members[$memID]['real_name']; | |
| 206 $context['errors'][$id]['member']['href'] = empty($memID) ? '' : $scripturl . '?action=profile;u=' . $memID; | |
| 207 $context['errors'][$id]['member']['link'] = empty($memID) ? $txt['guest_title'] : '<a href="' . $scripturl . '?action=profile;u=' . $memID . '">' . $context['errors'][$id]['member']['name'] . '</a>'; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 // Filtering anything? | |
| 212 if (isset($filter)) | |
| 213 { | |
| 214 $context['filter'] = &$filter; | |
| 215 | |
| 216 // Set the filtering context. | |
| 217 if ($filter['variable'] == 'id_member') | |
| 218 { | |
| 219 $id = $filter['value']['sql']; | |
| 220 loadMemberData($id, false, 'minimal'); | |
| 221 $context['filter']['value']['html'] = '<a href="' . $scripturl . '?action=profile;u=' . $id . '">' . $user_profile[$id]['real_name'] . '</a>'; | |
| 222 } | |
| 223 elseif ($filter['variable'] == 'url') | |
| 224 $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars((substr($filter['value']['sql'], 0, 1) == '?' ? $scripturl : '') . $filter['value']['sql']), array('\_' => '_')) . '\''; | |
| 225 elseif ($filter['variable'] == 'message') | |
| 226 { | |
| 227 $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars($filter['value']['sql']), array("\n" => '<br />', '<br />' => '<br />', "\t" => ' ', '\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; | |
| 228 $context['filter']['value']['html'] = preg_replace('~&lt;span class=&quot;remove&quot;&gt;(.+?)&lt;/span&gt;~', '$1', $context['filter']['value']['html']); | |
| 229 } | |
| 230 elseif ($filter['variable'] == 'error_type') | |
| 231 { | |
| 232 $context['filter']['value']['html'] = '\'' . strtr(htmlspecialchars($filter['value']['sql']), array("\n" => '<br />', '<br />' => '<br />', "\t" => ' ', '\_' => '_', '\\%' => '%', '\\\\' => '\\')) . '\''; | |
| 233 } | |
| 234 else | |
| 235 $context['filter']['value']['html'] = &$filter['value']['sql']; | |
| 236 } | |
| 237 | |
| 238 $context['error_types'] = array(); | |
| 239 | |
| 240 $context['error_types']['all'] = array( | |
| 241 'label' => $txt['errortype_all'], | |
| 242 'description' => isset($txt['errortype_all_desc']) ? $txt['errortype_all_desc'] : '', | |
| 243 'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : ''), | |
| 244 'is_selected' => empty($filter), | |
| 245 ); | |
| 246 | |
| 247 $sum = 0; | |
| 248 // What type of errors do we have and how many do we have? | |
| 249 $request = $smcFunc['db_query']('', ' | |
| 250 SELECT error_type, COUNT(*) AS num_errors | |
| 251 FROM {db_prefix}log_errors | |
| 252 GROUP BY error_type | |
| 253 ORDER BY error_type = {string:critical_type} DESC, error_type ASC', | |
| 254 array( | |
| 255 'critical_type' => 'critical', | |
| 256 ) | |
| 257 ); | |
| 258 while ($row = $smcFunc['db_fetch_assoc']($request)) | |
| 259 { | |
| 260 // Total errors so far? | |
| 261 $sum += $row['num_errors']; | |
| 262 | |
| 263 $context['error_types'][$sum] = array( | |
| 264 'label' => (isset($txt['errortype_' . $row['error_type']]) ? $txt['errortype_' . $row['error_type']] : $row['error_type']) . ' (' . $row['num_errors'] . ')', | |
| 265 'description' => isset($txt['errortype_' . $row['error_type'] . '_desc']) ? $txt['errortype_' . $row['error_type'] . '_desc'] : '', | |
| 266 'url' => $scripturl . '?action=admin;area=logs;sa=errorlog' . ($context['sort_direction'] == 'down' ? ';desc' : '') . ';filter=error_type;value=' . $row['error_type'], | |
| 267 'is_selected' => isset($filter) && $filter['value']['sql'] == $smcFunc['db_escape_wildcard_string']($row['error_type']), | |
| 268 ); | |
| 269 } | |
| 270 $smcFunc['db_free_result']($request); | |
| 271 | |
| 272 // Update the all errors tab with the total number of errors | |
| 273 $context['error_types']['all']['label'] .= ' (' . $sum . ')'; | |
| 274 | |
| 275 // Finally, work out what is the last tab! | |
| 276 if (isset($context['error_types'][$sum])) | |
| 277 $context['error_types'][$sum]['is_last'] = true; | |
| 278 else | |
| 279 $context['error_types']['all']['is_last'] = true; | |
| 280 | |
| 281 // And this is pretty basic ;). | |
| 282 $context['page_title'] = $txt['errlog']; | |
| 283 $context['has_filter'] = isset($filter); | |
| 284 $context['sub_template'] = 'error_log'; | |
| 285 } | |
| 286 | |
| 287 // Delete errors from the database. | |
| 288 function deleteErrors() | |
| 289 { | |
| 290 global $filter, $smcFunc; | |
| 291 | |
| 292 // Make sure the session exists and is correct; otherwise, might be a hacker. | |
| 293 checkSession(); | |
| 294 | |
| 295 // Delete all or just some? | |
| 296 if (isset($_POST['delall']) && !isset($filter)) | |
| 297 $smcFunc['db_query']('truncate_table', ' | |
| 298 TRUNCATE {db_prefix}log_errors', | |
| 299 array( | |
| 300 ) | |
| 301 ); | |
| 302 // Deleting all with a filter? | |
| 303 elseif (isset($_POST['delall']) && isset($filter)) | |
| 304 $smcFunc['db_query']('', ' | |
| 305 DELETE FROM {db_prefix}log_errors | |
| 306 WHERE ' . $filter['variable'] . ' LIKE {string:filter}', | |
| 307 array( | |
| 308 'filter' => $filter['value']['sql'], | |
| 309 ) | |
| 310 ); | |
| 311 // Just specific errors? | |
| 312 elseif (!empty($_POST['delete'])) | |
| 313 { | |
| 314 $smcFunc['db_query']('', ' | |
| 315 DELETE FROM {db_prefix}log_errors | |
| 316 WHERE id_error IN ({array_int:error_list})', | |
| 317 array( | |
| 318 'error_list' => array_unique($_POST['delete']), | |
| 319 ) | |
| 320 ); | |
| 321 | |
| 322 // Go back to where we were. | |
| 323 redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '') . ';start=' . $_GET['start'] . (isset($filter) ? ';filter=' . $_GET['filter'] . ';value=' . $_GET['value'] : '')); | |
| 324 } | |
| 325 | |
| 326 // Back to the error log! | |
| 327 redirectexit('action=admin;area=logs;sa=errorlog' . (isset($_REQUEST['desc']) ? ';desc' : '')); | |
| 328 } | |
| 329 | |
| 330 function ViewFile() | |
| 331 { | |
| 332 global $context, $txt, $boarddir, $sourcedir, $cachedir; | |
| 333 // Check for the administrative permission to do this. | |
| 334 isAllowedTo('admin_forum'); | |
| 335 | |
| 336 // Decode the file and get the line | |
| 337 $file = realpath(base64_decode($_REQUEST['file'])); | |
| 338 $real_board = realpath($boarddir); | |
| 339 $real_source = realpath($sourcedir); | |
| 340 $real_cache = realpath($cachedir); | |
| 341 $basename = strtolower(basename($file)); | |
| 342 $ext = strrchr($basename, '.'); | |
| 343 $line = isset($_REQUEST['line']) ? (int) $_REQUEST['line'] : 0; | |
| 344 | |
| 345 // Make sure the file we are looking for is one they are allowed to look at | |
| 346 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)) | |
| 347 fatal_lang_error('error_bad_file', true, array(htmlspecialchars($file))); | |
| 348 | |
| 349 // get the min and max lines | |
| 350 $min = $line - 20 <= 0 ? 1 : $line - 20; | |
| 351 $max = $line + 21; // One additional line to make everything work out correctly | |
| 352 | |
| 353 if ($max <= 0 || $min >= $max) | |
| 354 fatal_lang_error('error_bad_line'); | |
| 355 | |
| 356 $file_data = explode('<br />', highlight_php_code(htmlspecialchars(implode('', file($file))))); | |
| 357 | |
| 358 // We don't want to slice off too many so lets make sure we stop at the last one | |
| 359 $max = min($max, max(array_keys($file_data))); | |
| 360 | |
| 361 $file_data = array_slice($file_data, $min-1, $max - $min); | |
| 362 | |
| 363 $context['file_data'] = array( | |
| 364 'contents' => $file_data, | |
| 365 'min' => $min, | |
| 366 'target' => $line, | |
| 367 'file' => strtr($file, array('"' => '\\"')), | |
| 368 ); | |
| 369 | |
| 370 loadTemplate('Errors'); | |
| 371 $context['template_layers'] = array(); | |
| 372 $context['sub_template'] = 'show_file'; | |
| 373 | |
| 374 } | |
| 375 | |
| 376 ?> |
