| 1 | <?php
|
|---|
| 2 | /**
|
|---|
| 3 | * Debugging functions
|
|---|
| 4 | *
|
|---|
| 5 | * PHP version 5
|
|---|
| 6 | *
|
|---|
| 7 | * LICENSE: Hotaru CMS is free software: you can redistribute it and/or
|
|---|
| 8 | * modify it under the terms of the GNU General Public License as
|
|---|
| 9 | * published by the Free Software Foundation, either version 3 of
|
|---|
| 10 | * the License, or (at your option) any later version.
|
|---|
| 11 | *
|
|---|
| 12 | * Hotaru CMS is distributed in the hope that it will be useful, but WITHOUT
|
|---|
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|---|
| 14 | * FITNESS FOR A PARTICULAR PURPOSE.
|
|---|
| 15 | *
|
|---|
| 16 | * You should have received a copy of the GNU General Public License along
|
|---|
| 17 | * with Hotaru CMS. If not, see http://www.gnu.org/licenses/.
|
|---|
| 18 | *
|
|---|
| 19 | * @category Content Management System
|
|---|
| 20 | * @package HotaruCMS
|
|---|
| 21 | * @author Nick Ramsay <admin@hotarucms.org>
|
|---|
| 22 | * @copyright Copyright (c) 2009, Hotaru CMS
|
|---|
| 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
|---|
| 24 | * @link http://www.hotarucms.org/
|
|---|
| 25 | */
|
|---|
| 26 | class Debug
|
|---|
| 27 | {
|
|---|
| 28 | protected $fh = array(); // file handlers
|
|---|
| 29 | protected $log = array(); // file paths
|
|---|
| 30 |
|
|---|
| 31 | /**
|
|---|
| 32 | * Shows number of database queries and the time it takes for a page to load
|
|---|
| 33 | */
|
|---|
| 34 | public function showQueriesAndTime($h)
|
|---|
| 35 | {
|
|---|
| 36 | if ($h->isDebug) {
|
|---|
| 37 |
|
|---|
| 38 | $mysql_version = $h->db->get_var("SELECT VERSION() AS VE");
|
|---|
| 39 |
|
|---|
| 40 | echo "<p class='debug'>";
|
|---|
| 41 | echo $h->lang['main_hotaru_db_queries'] . $h->db->num_queries . " | ";
|
|---|
| 42 | echo $h->lang['main_hotaru_page_load_time'] . timer_stop(1) . $h->lang['main_times_secs'] . " | ";
|
|---|
| 43 | echo $h->lang['main_hotaru_memory_usage'] . display_filesize(memory_get_usage()) . " | ";
|
|---|
| 44 | echo $h->lang['main_hotaru_php_version'] . phpversion() . " | ";
|
|---|
| 45 | echo $h->lang['main_hotaru_mysql_version'] . $mysql_version . " | ";
|
|---|
| 46 | echo $h->lang['main_hotaru_hotaru_version'] . $h->version;
|
|---|
| 47 | echo "</p>";
|
|---|
| 48 | }
|
|---|
| 49 |
|
|---|
| 50 | if ($h->currentUser->loggedIn) {echo "<span id='loggedIn' class='loggedIn_true'/>"; } else {"<span id='loggedIn' class='loggedIn_false'/>";}
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 | /**
|
|---|
| 55 | * Open file for logging
|
|---|
| 56 | *
|
|---|
| 57 | * @param string $type "speed", "error", etc.
|
|---|
| 58 | * @param string $mode e.g. 'a' or 'w'.
|
|---|
| 59 | * @link http://php.net/manual/en/function.fopen.php
|
|---|
| 60 | */
|
|---|
| 61 | public function openLog($type = 'debug', $mode = 'a+')
|
|---|
| 62 | {
|
|---|
| 63 | $this->log[$type] = CACHE . "debug_logs/" . $type . ".php";
|
|---|
| 64 |
|
|---|
| 65 | // delete file if over 500KB
|
|---|
| 66 | if (file_exists($this->log[$type]) && (filesize($this->log[$type]) > 500000)) {
|
|---|
| 67 | unlink($this->log[$type]);
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | // If doesn't exist or rewriting, create a new file with die() at the top
|
|---|
| 71 | if (!file_exists($this->log[$type]) || ($mode != 'a' && $mode != 'a+')) {
|
|---|
| 72 | $this->fh[$type] = fopen($this->log[$type], $mode) or die("Sorry, I can't open cache/debug_logs/" . $type . ".php");
|
|---|
| 73 | fwrite($this->fh[$type], "<?php die(); ?>\r\n");
|
|---|
| 74 | } else {
|
|---|
| 75 | // open existing file:
|
|---|
| 76 | $this->fh[$type] = fopen($this->log[$type], $mode) or die("can't open file");
|
|---|
| 77 | }
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 | /**
|
|---|
| 82 | * Log performance and errors
|
|---|
| 83 | *
|
|---|
| 84 | * @param string $type "error", "speed", etc.
|
|---|
| 85 | */
|
|---|
| 86 | public function writeLog($type = 'debug', $string = '')
|
|---|
| 87 | {
|
|---|
| 88 | if ($string) {
|
|---|
| 89 | $string = date('d M Y H:i:s', time()) . " " . $string . "\n";
|
|---|
| 90 | fwrite($this->fh[$type], $string);
|
|---|
| 91 | }
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 | /**
|
|---|
| 96 | * Close log file
|
|---|
| 97 | *
|
|---|
| 98 | * @param string $type "speed", "error", etc.
|
|---|
| 99 | */
|
|---|
| 100 | public function closeLog($type = 'debug')
|
|---|
| 101 | {
|
|---|
| 102 | if (isset($this->fh[$type])) { fclose($this->fh[$type]); }
|
|---|
| 103 | }
|
|---|
| 104 |
|
|---|
| 105 |
|
|---|
| 106 | /**
|
|---|
| 107 | * Generate a System Report
|
|---|
| 108 | *
|
|---|
| 109 | * @param string $type 'log', 'email' or 'object'
|
|---|
| 110 | */
|
|---|
| 111 | public function generateReport($h, $type = 'log')
|
|---|
| 112 | {
|
|---|
| 113 | $report = $this->getSystemData($h);
|
|---|
| 114 |
|
|---|
| 115 | if ($type == 'object') { return $report; }
|
|---|
| 116 |
|
|---|
| 117 | if ($type == 'email') {
|
|---|
| 118 | $to = "admin@hotarucms.org"; // do not change!
|
|---|
| 119 | $subject = "System Report from " . SITE_NAME;
|
|---|
| 120 | $body = $this->logSystemReport($h, $report);
|
|---|
| 121 | $h->email($to, $subject, $body);
|
|---|
| 122 | $h->message = $h->lang['admin_maintenance_system_report_emailed'];
|
|---|
| 123 | $h->messageType = 'green';
|
|---|
| 124 | return true;
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | $h->openLog('system_report', 'w');
|
|---|
| 128 |
|
|---|
| 129 | // convert object to text
|
|---|
| 130 | $output = $this->logSystemReport($h, $report);
|
|---|
| 131 | if ($output) {
|
|---|
| 132 | $h->writeLog('system_report', $output);
|
|---|
| 133 | $h->closeLog('system_report');
|
|---|
| 134 |
|
|---|
| 135 | $h->message = $h->lang['admin_maintenance_system_report_success'];
|
|---|
| 136 | $h->messageType = 'green';
|
|---|
| 137 | return true;
|
|---|
| 138 | } else {
|
|---|
| 139 | $h->message = $h->lang['admin_maintenance_system_report_failure'];
|
|---|
| 140 | $h->messageType = 'red';
|
|---|
| 141 | return false;
|
|---|
| 142 | }
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 | /**
|
|---|
| 146 | * Get system data
|
|---|
| 147 | *
|
|---|
| 148 | * @param string $type 'log' or 'object'
|
|---|
| 149 | * @return object
|
|---|
| 150 | */
|
|---|
| 151 | public function getSystemData($h)
|
|---|
| 152 | {
|
|---|
| 153 | // essentials:
|
|---|
| 154 |
|
|---|
| 155 | $report['hotaru_site_name'] = SITE_NAME;
|
|---|
| 156 | $report['hotaru_baseurl'] = BASEURL;
|
|---|
| 157 |
|
|---|
| 158 | $report['php_version'] = phpversion();
|
|---|
| 159 | $report['mysql_version'] = $h->db->get_var("SELECT VERSION() AS VE");
|
|---|
| 160 | $report['hotaru_version'] = $h->version;
|
|---|
| 161 | $report['php_extensions'] = get_loaded_extensions();
|
|---|
| 162 |
|
|---|
| 163 | $sql = "SELECT miscdata_value FROM " . TABLE_MISCDATA . " WHERE miscdata_key = %s";
|
|---|
| 164 | $report['hotaru_version_db'] = $h->db->get_var($h->db->prepare($sql, 'hotaru_version'));
|
|---|
| 165 |
|
|---|
| 166 | // default permissions
|
|---|
| 167 |
|
|---|
| 168 | $sql = "SELECT miscdata_value FROM " . TABLE_MISCDATA . " WHERE miscdata_key = %s";
|
|---|
| 169 | $report['hotaru_permissions'] = $h->db->get_var($h->db->prepare($sql, 'permissions'));
|
|---|
| 170 |
|
|---|
| 171 | // default user settings
|
|---|
| 172 |
|
|---|
| 173 | $sql = "SELECT miscdata_value FROM " . TABLE_MISCDATA . " WHERE miscdata_key = %s";
|
|---|
| 174 | $report['hotaru_user_settings'] = $h->db->get_var($h->db->prepare($sql, 'user_settings'));
|
|---|
| 175 |
|
|---|
| 176 | // plugins: folder, enabled, version, order
|
|---|
| 177 |
|
|---|
| 178 | $sql = "SELECT plugin_folder, plugin_enabled, plugin_version, plugin_order FROM " . TABLE_PLUGINS . " ORDER BY plugin_order";
|
|---|
| 179 | $plugins = $h->db->get_results($h->db->prepare($sql));
|
|---|
| 180 | if ($plugins) {
|
|---|
| 181 | foreach ($plugins as $plugin) {
|
|---|
| 182 | $report['hotaru_plugins'][$plugin->plugin_folder]['enabled'] = $plugin->plugin_enabled;
|
|---|
| 183 | $report['hotaru_plugins'][$plugin->plugin_folder]['version'] = $plugin->plugin_version;
|
|---|
| 184 | $report['hotaru_plugins'][$plugin->plugin_folder]['order'] = $plugin->plugin_order;
|
|---|
| 185 | }
|
|---|
| 186 | }
|
|---|
| 187 |
|
|---|
| 188 | // plugin hooks: id, folder, hook name
|
|---|
| 189 |
|
|---|
| 190 | $sql = "SELECT phook_id, plugin_folder, plugin_hook FROM " . TABLE_PLUGINHOOKS;
|
|---|
| 191 | $plugins = $h->db->get_results($h->db->prepare($sql));
|
|---|
| 192 | if ($plugins) {
|
|---|
| 193 | foreach ($plugins as $plugin) {
|
|---|
| 194 | $report['hotaru_plugin_hooks'][$plugin->phook_id]['folder'] = $plugin->plugin_folder;
|
|---|
| 195 | $report['hotaru_plugin_hooks'][$plugin->phook_id]['hook'] = $plugin->plugin_hook;
|
|---|
| 196 | }
|
|---|
| 197 | }
|
|---|
| 198 |
|
|---|
| 199 | // plugin settings: folder, setting (can't use value because might include passwords)
|
|---|
| 200 |
|
|---|
| 201 | $sql = "SELECT plugin_folder, plugin_setting, plugin_value FROM " . TABLE_PLUGINSETTINGS;
|
|---|
| 202 | $plugins = $h->db->get_results($h->db->prepare($sql));
|
|---|
| 203 | if ($plugins) {
|
|---|
| 204 | foreach ($plugins as $plugin) {
|
|---|
| 205 | if (is_serialized($plugin->plugin_value)) { $plugin->plugin_value = unserialize($plugin->plugin_value); }
|
|---|
| 206 | $report['hotaru_plugin_settings'][$plugin->plugin_folder][$plugin->plugin_setting] = $this->applyMaskToArrays($h, $plugin->plugin_value);
|
|---|
| 207 | }
|
|---|
| 208 | }
|
|---|
| 209 |
|
|---|
| 210 | // Settings: Name, value (excluding SMTP PASSWORD)
|
|---|
| 211 |
|
|---|
| 212 | $sql = "SELECT settings_name, settings_value FROM " . TABLE_SETTINGS;
|
|---|
| 213 | $settings = $h->db->get_results($h->db->prepare($sql));
|
|---|
| 214 | if ($settings) {
|
|---|
| 215 | foreach ($settings as $setting) {
|
|---|
| 216 | // mask sensitive data
|
|---|
| 217 | switch ($setting->settings_name) {
|
|---|
| 218 | case 'SITE_EMAIL':
|
|---|
| 219 | case 'SMTP_HOST':
|
|---|
| 220 | case 'SMTP_PORT':
|
|---|
| 221 | case 'SMTP_USERNAME':
|
|---|
| 222 | case 'SMTP_PASSWORD':
|
|---|
| 223 | $setting->settings_value = preg_replace("/[a-zA-Z0-9]/", "*", $setting->settings_value);
|
|---|
| 224 | break;
|
|---|
| 225 | }
|
|---|
| 226 | $report['hotaru_settings'][$setting->settings_name] = $setting->settings_value;
|
|---|
| 227 | }
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | // Widgets: plugin, function, args
|
|---|
| 231 |
|
|---|
| 232 | $sql = "SELECT widget_plugin, widget_function, widget_args FROM " . TABLE_WIDGETS;
|
|---|
| 233 | $widgets = $h->db->get_results($h->db->prepare($sql));
|
|---|
| 234 | if ($widgets) {
|
|---|
| 235 | foreach ($widgets as $widget) {
|
|---|
| 236 | $report['hotaru_widgets'][$widget->widget_plugin]['function'] = $widget->widget_function;
|
|---|
| 237 | $report['hotaru_widgets'][$widget->widget_plugin]['args'] = $widget->widget_args;
|
|---|
| 238 | }
|
|---|
| 239 | }
|
|---|
| 240 |
|
|---|
| 241 | // Counts for all tables
|
|---|
| 242 |
|
|---|
| 243 | foreach ( $h->db->get_col("SHOW TABLES",0) as $table_name )
|
|---|
| 244 | {
|
|---|
| 245 | $report['hotaru_table_count'][$table_name] = $h->db->get_var("SELECT COUNT(*) FROM " . $table_name);
|
|---|
| 246 | }
|
|---|
| 247 |
|
|---|
| 248 | return $report;
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 |
|
|---|
| 252 | /**
|
|---|
| 253 | * Recurse through arrays, applying * mask to all values, but not keys
|
|---|
| 254 | *
|
|---|
| 255 | * @param array $array
|
|---|
| 256 | * @return array
|
|---|
| 257 | */
|
|---|
| 258 | public function applyMaskToArrays($h, $array)
|
|---|
| 259 | {
|
|---|
| 260 | //echo "<pre>"; print_r($array); echo "</pre>"; exit;
|
|---|
| 261 | if (!is_array($array) && !is_object($array)) { return false; }
|
|---|
| 262 |
|
|---|
| 263 | foreach ($array as $key => $value) {
|
|---|
| 264 | if (is_array($value) || is_object($value)) {
|
|---|
| 265 | $array[$key] = $this->applyMaskToArrays($h, $value);
|
|---|
| 266 | } else {
|
|---|
| 267 | $array[$key] = preg_replace("/[a-zA-Z0-9]/", "*", $value);
|
|---|
| 268 | }
|
|---|
| 269 | }
|
|---|
| 270 | return $array;
|
|---|
| 271 | }
|
|---|
| 272 |
|
|---|
| 273 |
|
|---|
| 274 | /**
|
|---|
| 275 | * Convert report object to text for logging to file
|
|---|
| 276 | *
|
|---|
| 277 | * @param object $report
|
|---|
| 278 | */
|
|---|
| 279 | public function logSystemReport($h, $report = NULL)
|
|---|
| 280 | {
|
|---|
| 281 | $output = "\n\n";
|
|---|
| 282 |
|
|---|
| 283 | $output .= "Name: " . $report['hotaru_site_name'] . "\n";
|
|---|
| 284 | $output .= "URL: " . $report['hotaru_baseurl'] . "\n";
|
|---|
| 285 | $output .= "Hotaru version: " . $report['hotaru_version'] . "\n";
|
|---|
| 286 | $output .= "Hotaru version in database: " . $report['hotaru_version_db'] . "\n";
|
|---|
| 287 | $output .= "PHP version: " . $report['php_version'] . "\n";
|
|---|
| 288 | $output .= "MySQL version: " . $report['mysql_version'] . "\n";
|
|---|
| 289 | $output .= "PHP extensions: " . implode(', ', $report['php_extensions']) . "\n";
|
|---|
| 290 |
|
|---|
| 291 | $output .= "\n";
|
|---|
| 292 |
|
|---|
| 293 | $output .= "Default site permissions: \n";
|
|---|
| 294 | $perms = unserialize($report['hotaru_permissions']);
|
|---|
| 295 | unset($perms['options']); // don't need to display these
|
|---|
| 296 | foreach ($perms as $key => $value) {
|
|---|
| 297 | $output .= $key . " => (";
|
|---|
| 298 | foreach ($value as $k => $v) {
|
|---|
| 299 | $output .= $k . ": " . $v . ", ";
|
|---|
| 300 | }
|
|---|
| 301 | $output = rtrim($output, ", ");
|
|---|
| 302 | $output .= ")\n";
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | $output .= "\n";
|
|---|
| 306 |
|
|---|
| 307 | $output .= "Default user settings: \n";
|
|---|
| 308 | $user_settings = unserialize($report['hotaru_user_settings']);
|
|---|
| 309 | foreach ($user_settings as $key => $value) {
|
|---|
| 310 | $output .= $key . " => " . $value . "\n";
|
|---|
| 311 | }
|
|---|
| 312 |
|
|---|
| 313 | $output .= "\n";
|
|---|
| 314 |
|
|---|
| 315 | $output .= "Plugins: \n";
|
|---|
| 316 | if (isset($report['hotaru_plugins'])) {
|
|---|
| 317 | foreach ($report['hotaru_plugins'] as $key => $value) {
|
|---|
| 318 | $output .= $value['order'] . ". " . $key . " v." . $value['version'] . " ";
|
|---|
| 319 | if ($value['enabled']) { $output .= "[enabled] \n"; } else { $output .= "[disabled] \n"; }
|
|---|
| 320 | }
|
|---|
| 321 | }
|
|---|
| 322 |
|
|---|
| 323 | $output .= "\n";
|
|---|
| 324 |
|
|---|
| 325 | $output .= "Plugin Hooks: \n";
|
|---|
| 326 | if (isset($report['hotaru_plugin_hooks'])) {
|
|---|
| 327 | foreach ($report['hotaru_plugin_hooks'] as $key => $value) {
|
|---|
| 328 | $output .= $key . ". " . $value['folder'] . " => " . $value['hook'] . " \n";
|
|---|
| 329 | }
|
|---|
| 330 | }
|
|---|
| 331 |
|
|---|
| 332 | $output .= "\n";
|
|---|
| 333 |
|
|---|
| 334 | $output .= "Plugin Settings: \n";
|
|---|
| 335 | if (isset($report['hotaru_plugin_settings'])) {
|
|---|
| 336 | foreach ($report['hotaru_plugin_settings'] as $key => $value) {
|
|---|
| 337 | foreach ($value as $k => $v) {
|
|---|
| 338 | if (!is_array($v)) {
|
|---|
| 339 | $output .= "\nPlugin settings for " . $key . ":\n...." . $k . " = " . $v . " \n";
|
|---|
| 340 | } else {
|
|---|
| 341 | $output .= "\nPlugin settings for " . $key . ":\n";
|
|---|
| 342 | $output = $this->outputArrays($h, $v, $output);
|
|---|
| 343 | }
|
|---|
| 344 | }
|
|---|
| 345 | }
|
|---|
| 346 | }
|
|---|
| 347 |
|
|---|
| 348 | $output .= "\n";
|
|---|
| 349 |
|
|---|
| 350 | $output .= "Hotaru Settings: \n";
|
|---|
| 351 | if (isset($report['hotaru_settings'])) {
|
|---|
| 352 | foreach ($report['hotaru_settings'] as $key => $value) {
|
|---|
| 353 | $output .= $key . " => " . $value . " \n";
|
|---|
| 354 | }
|
|---|
| 355 | }
|
|---|
| 356 |
|
|---|
| 357 | $output .= "\n";
|
|---|
| 358 |
|
|---|
| 359 | $output .= "Widgets: \n";
|
|---|
| 360 | if (isset($report['hotaru_widgets'])) {
|
|---|
| 361 | foreach ($report['hotaru_widgets'] as $key => $value) {
|
|---|
| 362 | $output .= $key . " => " . $value['function'];
|
|---|
| 363 | if ($value['args']) { $output .= " (args: " . $value['args'] . ")"; }
|
|---|
| 364 | $output .= "\n";
|
|---|
| 365 | }
|
|---|
| 366 | }
|
|---|
| 367 |
|
|---|
| 368 | $output .= "\n";
|
|---|
| 369 |
|
|---|
| 370 | $output .= "Number of rows in each table: \n";
|
|---|
| 371 | if (isset($report['hotaru_table_count'])) {
|
|---|
| 372 | foreach ($report['hotaru_table_count'] as $key => $value) {
|
|---|
| 373 | $output .= $key . " => " . $value . " \n";
|
|---|
| 374 | }
|
|---|
| 375 | }
|
|---|
| 376 |
|
|---|
| 377 | return $output;
|
|---|
| 378 | }
|
|---|
| 379 |
|
|---|
| 380 |
|
|---|
| 381 | /**
|
|---|
| 382 | * Recurse through arrays, adding them to $output for display
|
|---|
| 383 | *
|
|---|
| 384 | * @param array $array
|
|---|
| 385 | * @return array
|
|---|
| 386 | */
|
|---|
| 387 | public function outputArrays($h, $array = array(), $output = '')
|
|---|
| 388 | {
|
|---|
| 389 | if (!is_array($array) && !is_object($array)) { return $output; }
|
|---|
| 390 |
|
|---|
| 391 | foreach ($array as $key => $value) {
|
|---|
| 392 | if (is_array($value) || is_object($array)) {
|
|---|
| 393 | $output .= "..... " . $key . ":\n";
|
|---|
| 394 | $output = $this->outputArrays($h, $value, $output);
|
|---|
| 395 | } else {
|
|---|
| 396 | $output .= "..... " . $key . ": " . $value . " \n";
|
|---|
| 397 | }
|
|---|
| 398 | }
|
|---|
| 399 | return $output;
|
|---|
| 400 | }
|
|---|
| 401 | }
|
|---|
| 402 | ?>
|
|---|