├── .github └── FUNDING.yml ├── .gitignore ├── Readme.md ├── composer.json ├── config └── profiler.php ├── libraries ├── Console.php └── Profiler.php ├── spark.info └── views └── profiler_template.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: lonnieezell 4 | patreon: lonnieezell 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject/* -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Forensics for CodeIgniter 2 | 3 | Forensics is a high-powered, completely customizable replacement for the CodeIgniter Profiler. 4 | 5 | ## What's New? 6 | 7 | Forensics adds a few things to the stock Profiler that should make your life as a developer a bit easier. At least when it comes to debugging. 8 | 9 | - The Profiler output is now completely skinnable. If you've read the comments in the Profiler class before, this is something that the EllisLab devs have said for a while it would be nice to do. Congrats. It's done. 10 | - The output now also includes a list of all files that your CodeIgniter app includes, as well as their location (relative to your FCPATH). 11 | - Output also has the ability to log items and track memory in your project via a new console class. 12 | - Any variables sent to the view are shown in the bar. 13 | - Forensics now provides a detailed look at queries run via [Illuminate Database](https://github.com/illuminate/database). 14 | 15 | The default look, and some of the additional functionality, was heavily inspired by ParticleTree's [PHP Quick Profiler](http://particletree.com/features/php-quick-profiler/). 16 | 17 | ## Installing 18 | 19 | Forensics is intended to be used as a [Spark](http://getsparks.org). However, it is best installed using [Composer](http://getcomposer.org/). 20 | 21 | Create a `composer.json` file in your application's root (alongside the application and spark folders). Add the following text in the new file: 22 | 23 | { 24 | "require": { 25 | "lonnieezell/codeigniter-forensics": "dev-master" 26 | } 27 | } 28 | 29 | Thanks to the magic of `compwright/composer-installers` the files are transferred to your application's `third_party` folder. In your application, you will first need to load the newly installed package. This is done easily through the autoloader, but could also be done in your controller with an environment check for maximum optimization. 30 | 31 | $autoload['packages'] = array(APPPATH.'third_party/codeigniter-forensics'); 32 | 33 | Then, just enable the profiler like normal. 34 | 35 | $this->output->enable_profiler(true); 36 | 37 | ## Forensics Logging 38 | 39 | In addition to the normal information that CI's Profiler provides, you now have two new logging commands at your disposal that work with the Forensics Profiler: 40 | 41 | ### Console::log($data) 42 | 43 | This function accepts any data type and simply creates a pretty, readable output of the variable, using print_r(). Very handy for logging where you are in the script execution, or outputting the contents of an array, or stdObject to your new 'console'. 44 | 45 | ### Console::log_memory($variable, $name) 46 | 47 | The log_memory function has two uses. 48 | 49 | 1) When no parameters are passed in, it will record the current memory usage of your script. This is perfect for watching a loop and checking for memory leaks. 50 | 51 | 2) If you pass in the $variable and $name parameters, will output the amount of memory that variable is using to the console. 52 | 53 | In order to use either of these functions, you must be sure to load the Console library before you use it. 54 | 55 | ### Illuminate Database Queries 56 | 57 | In addition to CodeIgniter database queries, Forensics can display information about any queries run by [Illuminate Database](https://github.com/illuminate/database) models or the Eloqeunt query builder. **This feature is disabled by default.** To enable this feature, change the config setting for `eloquent` in `config/profiler.php`. If you're using Illuminate Database in your project, note that this feature requires Capsule\Manager. 58 | 59 | ## Other Tips 60 | 61 | You can change the location of the profiler bar by changing the `$bar_location` variable at the top of the *profiler_template* view to one of the following locations: 62 | 63 | * top-right 64 | * top-left 65 | * bottom-left 66 | * bottom-right 67 | * top 68 | * bottom 69 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lonnieezell/codeigniter-forensics", 3 | "description": "A high-powered, customizable Profiler replacement for CodeIgniter.", 4 | "license": "MIT", 5 | "keywords": [ 6 | "codeigniter", "spark", "profiler", "debug" 7 | ], 8 | "authors": [ 9 | { 10 | "name": "Lonnie Ezell", 11 | "email": "lonnieezell@gmail.com", 12 | "role": "Developer" 13 | } 14 | ], 15 | "homepage": "http://lonnieezell.github.io/codeigniter-forensics/", 16 | "support": { 17 | "issues": "http://lonnieezell.github.io/codeigniter-forensics/issues", 18 | "source": "http://lonnieezell.github.io/codeigniter-forensics/" 19 | }, 20 | "type": "codeigniter-third-party", 21 | "require": { 22 | "compwright/codeigniter-installers": "*" 23 | } 24 | } -------------------------------------------------------------------------------- /config/profiler.php: -------------------------------------------------------------------------------- 1 | array(), 28 | 'log_count' => 0, 29 | 'memory_count' => 0, 30 | ); 31 | 32 | /* 33 | Var: $ci 34 | An instance of the CI super object. 35 | */ 36 | private static $ci; 37 | 38 | //-------------------------------------------------------------------- 39 | 40 | /* 41 | Method: __construct() 42 | 43 | This constructor is here purely for CI's benefit, as this is a 44 | static class. 45 | 46 | Return: 47 | void 48 | */ 49 | public function __construct() 50 | { 51 | self::init(); 52 | 53 | log_message('debug', 'Forensics Console library loaded'); 54 | } 55 | 56 | //-------------------------------------------------------------------- 57 | 58 | /* 59 | Method: init() 60 | 61 | Grabs an instance of CI and gets things ready to run. 62 | */ 63 | public static function init() 64 | { 65 | self::$ci =& get_instance(); 66 | } 67 | 68 | //-------------------------------------------------------------------- 69 | 70 | /* 71 | Method: log() 72 | 73 | Logs a variable to the console. 74 | 75 | Parameters: 76 | $data - The variable to log. 77 | */ 78 | public static function log($data=null) 79 | { 80 | if ($data !== 0 && empty($data)) 81 | { 82 | $data = 'empty'; 83 | } 84 | 85 | $log_item = array( 86 | 'data' => $data, 87 | 'type' => 'log' 88 | ); 89 | 90 | self::add_to_console('log_count', $log_item); 91 | } 92 | 93 | //-------------------------------------------------------------------- 94 | 95 | /* 96 | Method: log_memory() 97 | 98 | Logs the memory usage a single variable, or the entire script. 99 | 100 | Parameters: 101 | $object - The object to store the memory usage of. 102 | $name - The name to be displayed in the console. 103 | */ 104 | public static function log_memory($object=false, $name='PHP') 105 | { 106 | $memory = memory_get_usage(); 107 | 108 | if ($object) 109 | { 110 | $memory = strlen(serialize($object)); 111 | } 112 | 113 | $log_item = array( 114 | 'data' => $memory, 115 | 'type' => 'memory', 116 | 'name' => $name, 117 | 'data_type' => gettype($object) 118 | ); 119 | 120 | self::add_to_console('memory_count', $log_item); 121 | } 122 | 123 | //-------------------------------------------------------------------- 124 | 125 | /* 126 | Method: get_logs() 127 | 128 | Returns the logs array for use in external classes. (Namely the 129 | Forensics Profiler. 130 | */ 131 | public static function get_logs() 132 | { 133 | return self::$logs; 134 | } 135 | 136 | //-------------------------------------------------------------------- 137 | 138 | //-------------------------------------------------------------------- 139 | // !PRIVATE METHODS 140 | //-------------------------------------------------------------------- 141 | 142 | public static function add_to_console($log=null, $item=null) 143 | { 144 | if (empty($log) || empty($item)) 145 | { 146 | return; 147 | } 148 | 149 | self::$logs['console'][] = $item; 150 | self::$logs[$log] += 1; 151 | } 152 | 153 | //-------------------------------------------------------------------- 154 | 155 | } 156 | 157 | // End Console class 158 | -------------------------------------------------------------------------------- /libraries/Profiler.php: -------------------------------------------------------------------------------- 1 | CI =& get_instance(); 63 | $this->CI->load->language('profiler'); 64 | 65 | // If the config file has a query_toggle_count, 66 | // use it, but remove it from the config array. 67 | if ( isset($config['query_toggle_count']) ) 68 | { 69 | $this->_query_toggle_count = (int) $config['query_toggle_count']; 70 | unset($config['query_toggle_count']); 71 | } 72 | 73 | // default all sections to display 74 | foreach ($this->_available_sections as $section) 75 | { 76 | if ( ! isset($config[$section])) 77 | { 78 | $this->_compile_{$section} = TRUE; 79 | } 80 | } 81 | 82 | // Make sure the Console is loaded. 83 | if (!class_exists('Console')) 84 | { 85 | $this->CI->load->library('Console'); 86 | } 87 | 88 | $this->set_sections($config); 89 | 90 | // Strange hack to get access to the current 91 | // vars in the CI_Loader class. 92 | $this->_ci_cached_vars = $this->CI->load->_ci_cached_vars; 93 | } 94 | 95 | // -------------------------------------------------------------------- 96 | 97 | /** 98 | * Set Sections 99 | * 100 | * Sets the private _compile_* properties to enable/disable Profiler sections 101 | * 102 | * @param mixed 103 | * @return void 104 | */ 105 | public function set_sections($config) 106 | { 107 | foreach ($config as $method => $enable) 108 | { 109 | if (in_array($method, $this->_available_sections)) 110 | { 111 | $this->_compile_{$method} = ($enable !== FALSE) ? TRUE : FALSE; 112 | } 113 | } 114 | } 115 | 116 | // -------------------------------------------------------------------- 117 | 118 | /** 119 | * Auto Profiler 120 | * 121 | * This function cycles through the entire array of mark points and 122 | * matches any two points that are named identically (ending in "_start" 123 | * and "_end" respectively). It then compiles the execution times for 124 | * all points and returns it as an array 125 | * 126 | * @return array 127 | */ 128 | protected function _compile_benchmarks() 129 | { 130 | $profile = array(); 131 | $output = array(); 132 | 133 | foreach ($this->CI->benchmark->marker as $key => $val) 134 | { 135 | // We match the "end" marker so that the list ends 136 | // up in the order that it was defined 137 | if (preg_match("/(.+?)_end/i", $key, $match)) 138 | { 139 | if (isset($this->CI->benchmark->marker[$match[1].'_end']) AND isset($this->CI->benchmark->marker[$match[1].'_start'])) 140 | { 141 | $profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key); 142 | } 143 | } 144 | } 145 | 146 | // Build a table containing the profile data. 147 | // Note: At some point we might want to make this data available to be logged. 148 | foreach ($profile as $key => $val) 149 | { 150 | $key = ucwords(str_replace(array('_', '-'), ' ', $key)); 151 | $output[$key] = $val; 152 | } 153 | 154 | unset($profile); 155 | 156 | return $output; 157 | } 158 | 159 | // -------------------------------------------------------------------- 160 | 161 | /** 162 | * Compile Queries 163 | * 164 | * @return string 165 | */ 166 | protected function _compile_queries() 167 | { 168 | $dbs = array(); 169 | $output = array(); 170 | 171 | // Let's determine which databases are currently connected to 172 | foreach (get_object_vars($this->CI) as $name => $cobject) 173 | { 174 | if ($cobject) 175 | { 176 | if ($cobject instanceof CI_DB) 177 | { 178 | $dbs[$name] = $cobject; 179 | } 180 | elseif ($cobject instanceof CI_Model) 181 | { 182 | foreach (get_object_vars($cobject) as $mname => $mobject) 183 | { 184 | if ($mobject instanceof CI_DB) 185 | { 186 | $dbs[$mname] = $mobject; 187 | } 188 | } 189 | } 190 | } 191 | } 192 | 193 | if (count($dbs) == 0) 194 | { 195 | return $this->CI->lang->line('profiler_no_db'); // to get db access must be public instance 196 | } 197 | 198 | // Load the text helper so we can highlight the SQL 199 | $this->CI->load->helper('text'); 200 | 201 | // Key words we want bolded 202 | $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'GROUP BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR ', 'HAVING', 'OFFSET', 'NOT IN', 'IN', 'LIKE', 'NOT LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'); 203 | 204 | 205 | $total = 0; // total query time 206 | foreach ($dbs as $controler => $db) 207 | { 208 | 209 | foreach ($db->queries as $key => $val) 210 | { 211 | $time = number_format($db->query_times[$key], 4); 212 | $total += $db->query_times[$key]; 213 | 214 | foreach ($highlight as $bold) 215 | { 216 | $val = str_replace($bold, ''. $bold .'', $val); 217 | } 218 | 219 | $output[][$time] = $controler.':'.$db->database.' ' . $val; // there's a filter CI plugin, so must show controler name, tho mention on wich controler was exec the query if some filter was applied 220 | } 221 | 222 | } 223 | 224 | if(count($output) == 0) 225 | { 226 | $output = $this->CI->lang->line('profiler_no_queries'); 227 | } 228 | else 229 | { 230 | $total = number_format($total, 4); 231 | $output[][$total] = 'Total Query Execution Time'; 232 | } 233 | 234 | return $output; 235 | } 236 | 237 | 238 | // -------------------------------------------------------------------- 239 | 240 | /** 241 | * Compile Eloquent Queries 242 | * 243 | * @return string 244 | */ 245 | protected function _compile_eloquent() 246 | { 247 | $output = array(); 248 | 249 | // hack to make eloquent not throw error for now 250 | // but checks if file actually exists, or CI will throw an error 251 | if (file_exists(APPPATH.'/models/Eloquent/Assets/Action.php')) { 252 | $this->CI->load->model('Eloquent/Assets/Action'); 253 | } 254 | 255 | if ( ! class_exists('Illuminate\Database\Capsule\Manager', FALSE)) { 256 | $output = 'Illuminate\Database has not been loaded.'; 257 | } else { 258 | // Load the text helper so we can highlight the SQL 259 | $this->CI->load->helper('text'); 260 | 261 | // Key words we want bolded 262 | $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'GROUP BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR ', 'HAVING', 'OFFSET', 'NOT IN', 'IN', 'LIKE', 'NOT LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'); 263 | 264 | 265 | $total = 0; // total query time 266 | $queries = Illuminate\Database\Capsule\Manager::getQueryLog(); 267 | foreach ($queries as $q) 268 | { 269 | $time = number_format($q['time']/1000, 4); 270 | $total += $q['time']/1000; 271 | 272 | $query = $this->interpolateQuery($q['query'], $q['bindings']); 273 | foreach ($highlight as $bold) 274 | $query = str_ireplace($bold, ''.$bold.'', $query); 275 | 276 | $output[][$time] = $query; 277 | } 278 | 279 | if(count($output) == 0) 280 | { 281 | $output = $this->CI->lang->line('profiler_no_queries'); 282 | } 283 | else 284 | { 285 | $total = number_format($total, 4); 286 | $output[][$total] = 'Total Query Execution Time'; 287 | } 288 | } 289 | 290 | return $output; 291 | } 292 | 293 | public function interpolateQuery($query, array $params) { 294 | $keys = array(); 295 | $values = $params; 296 | 297 | //build a regular expression for each parameter 298 | foreach ($params as $key => $value) { 299 | if (is_string($key)) { 300 | $keys[] = "/:" . $key . "/"; 301 | } else { 302 | $keys[] = '/[?]/'; 303 | } 304 | 305 | if (is_string($value)) 306 | $values[$key] = "'" . $value . "'"; 307 | 308 | if (is_array($value)) 309 | $values[$key] = implode(',', $value); 310 | 311 | if (is_null($value)) 312 | $values[$key] = 'NULL'; 313 | } 314 | 315 | $query = preg_replace($keys, $values, $query, 1, $count); 316 | 317 | return $query; 318 | } 319 | 320 | 321 | // -------------------------------------------------------------------- 322 | 323 | /** 324 | * Compile $_GET Data 325 | * 326 | * @return string 327 | */ 328 | protected function _compile_get() 329 | { 330 | $output = array(); 331 | 332 | $get = $this->CI->input->get(); 333 | 334 | if (count($get) == 0 || $get === false) 335 | { 336 | $output = $this->CI->lang->line('profiler_no_get'); 337 | } 338 | else 339 | { 340 | foreach ($get as $key => $val) 341 | { 342 | if (is_array($val)) 343 | { 344 | $output[$key] = "
" . htmlspecialchars(stripslashes(print_r($val, true))) . ""; 345 | } 346 | else 347 | { 348 | $output[$key] = htmlspecialchars(stripslashes($val)); 349 | } 350 | } 351 | } 352 | 353 | return $output; 354 | } 355 | 356 | // -------------------------------------------------------------------- 357 | 358 | /** 359 | * Compile $_POST Data 360 | * 361 | * @return string 362 | */ 363 | protected function _compile_post() 364 | { 365 | $output = array(); 366 | 367 | if (count($_POST) == 0) 368 | { 369 | $output = $this->CI->lang->line('profiler_no_post'); 370 | } 371 | else 372 | { 373 | foreach ($_POST as $key => $val) 374 | { 375 | if ( ! is_numeric($key)) 376 | { 377 | $key = "'".$key."'"; 378 | } 379 | 380 | if (is_array($val)) 381 | { 382 | $output['$_POST['. $key .']'] = '
'. htmlspecialchars(stripslashes(print_r($val, TRUE))) . ''; 383 | } 384 | else 385 | { 386 | $output['$_POST['. $key .']'] = htmlspecialchars(stripslashes($val)); 387 | } 388 | } 389 | } 390 | 391 | return $output; 392 | } 393 | 394 | // -------------------------------------------------------------------- 395 | 396 | /** 397 | * Show query string 398 | * 399 | * @return string 400 | */ 401 | protected function _compile_uri_string() 402 | { 403 | if ($this->CI->uri->uri_string == '') 404 | { 405 | $output = $this->CI->lang->line('profiler_no_uri'); 406 | } 407 | else 408 | { 409 | $output = $this->CI->uri->uri_string; 410 | } 411 | 412 | return $output; 413 | } 414 | 415 | // -------------------------------------------------------------------- 416 | 417 | /** 418 | * Show the controller and function that were called 419 | * 420 | * @return string 421 | */ 422 | protected function _compile_controller_info() 423 | { 424 | $output = $this->CI->router->class."/".$this->CI->router->method; 425 | 426 | return $output; 427 | } 428 | 429 | // -------------------------------------------------------------------- 430 | 431 | /** 432 | * Compile memory usage 433 | * 434 | * Display total used memory 435 | * 436 | * @return string 437 | */ 438 | protected function _compile_memory_usage() 439 | { 440 | if (function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '') 441 | { 442 | $output = number_format($usage) .' bytes'; 443 | } 444 | else 445 | { 446 | $output = $this->CI->lang->line('profiler_no_memory_usage'); 447 | } 448 | 449 | return $output; 450 | } 451 | 452 | // -------------------------------------------------------------------- 453 | 454 | /** 455 | * Compile header information 456 | * 457 | * Lists HTTP headers 458 | * 459 | * @return string 460 | */ 461 | protected function _compile_http_headers() 462 | { 463 | $output = array(); 464 | 465 | foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header) 466 | { 467 | $val = (isset($_SERVER[$header])) ? $_SERVER[$header] : ''; 468 | $output[$header] = $val; 469 | } 470 | 471 | return $output; 472 | } 473 | 474 | // -------------------------------------------------------------------- 475 | 476 | /** 477 | * Compile config information 478 | * 479 | * Lists developer config variables 480 | * 481 | * @return string 482 | */ 483 | protected function _compile_config() 484 | { 485 | $output = array(); 486 | 487 | foreach ($this->CI->config->config as $config=>$val) 488 | { 489 | if (is_array($val)) 490 | { 491 | $val = print_r($val, TRUE); 492 | } 493 | 494 | $output[$config] = htmlspecialchars($val); 495 | } 496 | 497 | return $output; 498 | } 499 | 500 | // -------------------------------------------------------------------- 501 | 502 | public function _compile_files() 503 | { 504 | $files = get_included_files(); 505 | 506 | sort($files); 507 | 508 | return $files; 509 | } 510 | 511 | //-------------------------------------------------------------------- 512 | 513 | public function _compile_console() 514 | { 515 | $logs = Console::get_logs(); 516 | 517 | if ($logs['console']) 518 | { 519 | foreach ($logs['console'] as $key => $log) 520 | { 521 | if ($log['type'] == 'log') 522 | { 523 | $logs['console'][$key]['data'] = print_r($log['data'], true); 524 | } 525 | elseif ($log['type'] == 'memory') 526 | { 527 | $logs['console'][$key]['data'] = $this->get_file_size($log['data']); 528 | } 529 | } 530 | } 531 | 532 | return $logs; 533 | } 534 | 535 | //-------------------------------------------------------------------- 536 | 537 | function _compile_userdata() 538 | { 539 | $output = array(); 540 | 541 | if (FALSE !== $this->CI->load->is_loaded('session')) 542 | { 543 | 544 | $compiled_userdata = $this->CI->session->all_userdata(); 545 | 546 | if (count($compiled_userdata)) 547 | { 548 | foreach ($compiled_userdata as $key => $val) 549 | { 550 | if (is_numeric($key)) 551 | { 552 | $output[$key] = print_r($val,true); 553 | } 554 | 555 | if (is_array($val) || is_object($val)) 556 | { 557 | if (is_object($val)) 558 | $output[$key] = json_decode(json_encode($val), true); 559 | else 560 | $output[$key] = htmlspecialchars(stripslashes(print_r($val, true))); 561 | } 562 | else 563 | { 564 | $output[$key] = htmlspecialchars(stripslashes(print_r($val, true))); 565 | } 566 | } 567 | } 568 | } 569 | 570 | return $output; 571 | } 572 | 573 | //-------------------------------------------------------------------- 574 | 575 | /** 576 | * Compile View Data 577 | * 578 | * Allows any data passed to views to be available in the profiler bar. 579 | * 580 | * @return array 581 | */ 582 | public function _compile_view_data() 583 | { 584 | $output = array(); 585 | 586 | foreach ($this->_ci_cached_vars as $key => $val) 587 | { 588 | if (is_numeric($key)) 589 | { 590 | $output[$key] = "'$val'"; 591 | } 592 | 593 | if (is_array($val) || is_object($val)) 594 | { 595 | $output[$key] = '
' . htmlspecialchars(stripslashes(print_r($val, true))) . ''; 596 | } 597 | else 598 | { 599 | $output[$key] = htmlspecialchars(stripslashes($val)); 600 | } 601 | } 602 | 603 | return $output; 604 | } 605 | 606 | //-------------------------------------------------------------------- 607 | 608 | 609 | public static function get_file_size($size, $retstring = null) { 610 | // adapted from code at http://aidanlister.com/repos/v/function.size_readable.php 611 | $sizes = array('bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); 612 | 613 | if ($retstring === null) { $retstring = '%01.2f %s'; } 614 | 615 | $lastsizestring = end($sizes); 616 | 617 | foreach ($sizes as $sizestring) { 618 | if ($size < 1024) { break; } 619 | if ($sizestring != $lastsizestring) { $size /= 1024; } 620 | } 621 | 622 | if ($sizestring == $sizes[0]) { $retstring = '%01d %s'; } // Bytes aren't normally fractional 623 | return sprintf($retstring, $size, $sizestring); 624 | } 625 | 626 | //-------------------------------------------------------------------- 627 | 628 | /** 629 | * Run the Profiler 630 | * 631 | * @return string 632 | */ 633 | public function run() 634 | { 635 | $this->CI->load->helper('language'); 636 | 637 | $fields_displayed = 0; 638 | 639 | foreach ($this->_available_sections as $section) 640 | { 641 | if ($this->_compile_{$section} !== FALSE) 642 | { 643 | $func = "_compile_{$section}"; 644 | if ($section == 'http_headers') $section = 'headers'; 645 | $this->_sections[$section] = $this->{$func}(); 646 | $fields_displayed++; 647 | } 648 | } 649 | 650 | return $this->CI->load->view('profiler_template', array('sections' => $this->_sections), true); 651 | } 652 | 653 | } 654 | 655 | // END CI_Profiler class 656 | 657 | //-------------------------------------------------------------------- 658 | 659 | /* End of file Profiler.php */ 660 | /* Location: ./system/libraries/Profiler.php */ 661 | -------------------------------------------------------------------------------- /spark.info: -------------------------------------------------------------------------------- 1 | # This is the spark-sdk specification. It's in a magical format called YAML. 2 | # Use this format while developing your own sparks! 3 | 4 | # This is the spark name. This should be the registered name of the spark. 5 | # It is here for informational purposes only. 6 | name: forensics 7 | 8 | # This is the current version of this spark. All sparks should be in 9 | # x.x.x format. Validation will fail otherwise. 10 | version: 1.0.0 11 | 12 | # This is the version of CodeIgniter this spark is compatible up to. It should 13 | # be in x.x.x format 14 | compatibility: 2.1.4 15 | 16 | # There are no dependencies now, but when there are, uncomment below. 17 | #dependencies: 18 | # some-spark-1: 1.0.0 19 | # some-other-spark-2: 1.0.0 -------------------------------------------------------------------------------- /views/profiler_template.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 59 | 60 | 178 | 179 | 180 | 181 | 473 | --------------------------------------------------------------------------------