/tools/log-reader.php
PHP | 345 lines | 216 code | 57 blank | 72 comment | 56 complexity | b39b0fe5f49b7c6236b9afb67fa3da2f MD5 | raw file
Possible License(s): LGPL-3.0
- <?php
-
- /**
- * Wave Framework <http://www.waveframework.com>
- * Log Reader
- *
- * This is a simple script that is used to read log files stored by WWW_Logger class.
- * It loads a log file defined by specific timestamp formatted as Y-m-d-H. By default
- * it displays information about all the requests that have happened in the current
- * hour, but if GET variable 'log' is supplied in same timestamp format, then that
- * log file data is returned instead.
- *
- * @package Tools
- * @author Kristo Vaher <kristo@waher.net>
- * @copyright Copyright (c) 2012, Kristo Vaher
- * @license GNU Lesser General Public License Version 3
- * @tutorial /doc/pages/guide_tools.htm
- * @since 1.0.0
- * @version 3.6.0
- */
-
- // This initializes tools and authentication
- require('.'.DIRECTORY_SEPARATOR.'tools_autoload.php');
-
- // Log is printed out in plain text format
- header('Content-Type: text/html;charset=utf-8');
-
- // Checking if logger attempts to read internal log
- if(isset($_GET['internal'])){
-
- // Debugger actions are based on whether signature and error are set
- if(isset($_GET['signature'])){
-
- // Replacing potentially harmful characters
- $signature=preg_replace('[^a-zA-Z0-9]','',$_GET['signature']);
-
- // Actual log address
- $logAddress='..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'internal_'.$signature.'_data.tmp';
-
- // If file is set for deletion
- if(isset($_GET['delete']) && file_exists($logAddress)){
- // Removing the data file
- unlink($logAddress);
- // Removing signature file
- $signatureAddress=str_replace('_data','_signature',$logAddress);
- if(file_exists($signatureAddress)){
- unlink($signatureAddress);
- }
- // Redirecting to link without delete flag set
- header('Location: log-reader.php?internal');
- die();
- }
-
- } else {
-
- // This array stores all the error developer signatures
- $signatures=array();
-
- // This is the list of all errors based on signatures
- $files=fileIndex('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR,'filenames',false);
-
- // Looping over each folder that includes errors
- foreach($files as $f){
- // Making sure that the file is that of an internal log entry
- $f=explode('_',$f);
- if(count($f)==3 && $f[0]=='internal' && $f[2]=='signature.tmp'){
- $signatures[$f[1]]=file_get_contents('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'internal_'.$f[1].'_signature.tmp');
- }
- }
-
- }
-
- } elseif(isset($_GET['api'])){
-
- // Actual log address
- $logAddress='..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'api.tmp';
-
- // If file is set for deletion
- if(isset($_GET['delete']) && file_exists($logAddress)){
- unlink($logAddress);
- // Redirecting to link without delete flag set
- header('Location: log-reader.php?api');
- die();
- }
-
- } elseif(isset($_GET['http'])){
-
- // Log reader can access any log file created by the system
- if(isset($_GET['log'])){
- // User agent requested input URL is validated against hostile characters
- $logFileName=preg_replace('/[^A-Za-z\-\_0-9\/]/i','',$_GET['log']);
- } else {
- // By default the results are returned from current hour
- header('Location: log-reader.php?http&log='.date('Y-m-d-H'));
- die();
- }
-
- // This stores the array types to print out
- $types=array();
-
- // You can print out only some log information
- if(isset($_GET['types'])){
- $rawTypes=explode(',',$_GET['types']);
- foreach($rawTypes as $t){
- $bits=explode('[',$t);
- if(isset($bits[1])){
- $types[$t]=str_replace(']','',$bits[1]);
- } else {
- $types[$t]=true;
- }
- }
- } else {
- $types['all']=true;
- }
-
- // Every day the logs are stored under different log subfolder
- $logSubfolder=substr($logFileName,0,10);
-
- // Actual log address
- $logAddress='..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.$logSubfolder.DIRECTORY_SEPARATOR.$logFileName.'.tmp';
-
- // If file is set for deletion
- if(isset($_GET['delete']) && file_exists($logAddress)){
- unlink($logAddress);
- unset($_GET['delete']);
- // Redirecting to link without delete flag set
- if(!empty($_GET)){
- header('Location: log-reader.php?'.http_build_query($_GET));
- } else {
- header('Location: log-reader.php');
- }
- die();
- }
-
- }
-
- ?>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title><?=(isset($_GET['internal']))?'Internal Log':((isset($_GET['api']))?'API Log':'Log Reader')?></title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width"/>
- <link type="text/css" href="style.css" rel="stylesheet" media="all"/>
- <link rel="icon" href="../favicon.ico" type="image/x-icon"/>
- <link rel="icon" href="../favicon.ico" type="image/vnd.microsoft.icon"/>
- <meta content="noindex,nocache,nofollow,noarchive,noimageindex,nosnippet" name="robots"/>
- <meta http-equiv="cache-control" content="no-cache"/>
- <meta http-equiv="pragma" content="no-cache"/>
- <meta http-equiv="expires" content="0"/>
- </head>
- <body>
- <?php
-
- // Pops up an alert about default password
- passwordNotification($config['http-authentication-password']);
-
- // Header
- if(isset($_GET['internal'])){
- echo '<h1>Internal Log</h1>';
- } elseif(isset($_GET['api'])){
- echo '<h1>API Log</h1>';
- } elseif(isset($_GET['http'])) {
- echo '<h1>HTTP Request Log</h1>';
- } else {
- echo '<h1>Log Entries</h1>';
- }
- echo '<h4 class="highlight">';
- foreach($softwareVersions as $software=>$version){
- // Adding version numbers
- echo '<b>'.$software.'</b> ('.$version.') ';
- }
- echo '</h4>';
-
- echo '<h2>Log</h2>';
-
- if(isset($_GET['internal']) && !isset($_GET['signature'])){
-
- echo '<h3>Available Signatures</h3>';
- echo '<h4>Signature is a pair of IP address and user agent string that generated the log entries. This helps you keep different log entries separate from one another based on client. Click on signature to see relevant log entries.</h4>';
-
- // If there are error signatures found
- if(!empty($signatures)){
- foreach($signatures as $folder=>$signature){
- if($signature==$_SERVER['REMOTE_ADDR'].' '.$_SERVER['HTTP_USER_AGENT']){
- echo '<a href="log-reader.php?internal&signature='.md5($signature).'">'.$signature.' <span class="orange">(this matches your signature)</span></a><br/>';
- } else {
- echo '<a href="log-reader.php?internal&signature='.md5($signature).'">'.$signature.'</a><br/>';
- }
- }
- } else {
- echo '<p class="bold">There are no logged messages</p>';
- }
-
- } elseif(file_exists($logAddress)){
-
- // File delete link
- echo '<h3 onclick="if(confirm(\'Are you sure?\')){ document.location.href=document.location.href+\'&delete\'; }" class="red bold" style="cursor:pointer;">Click to delete this log</h3>';
-
- // Getting error file size
- $filesize=filesize($logAddress);
- // Attempting to get memory limit
- $memory=ini_get('memory_limit');
- if($memory){
- $memory=iniSettingToBytes($memory);
- // Getting the amount of bytes currently allocated
- $memory=$memory-memory_get_usage();
- // available memory is 'about half' of the actual memory, just in case the array creation takes a lot of memory
- $memory=intval($memory/2);
- }
-
- // Output buffer allows to increase peformance due to multiple echo's
- ob_start();
-
- // This variable holds various summary statistics
- $summary=array();
-
- // Log is only shown if memory limit could not be gotten or is less than the file size
- if(!$memory || $filesize<$memory){
-
- // Log files are stored as JSON serialized arrays, separated with line-breaks
- $log=explode("\n",file_get_contents($logAddress));
-
- // Printing out every line from the log file
- foreach($log as $l){
-
- if(isset($_GET['api']) && $l!=''){
- $logDetails=explode("\t",$l);
- echo '<div class="block">';
- // Printing out log data
- echo '<b>'.date('d.m.Y H:i:s',$logDetails[0]).'</b> '.$logDetails[1].' -> '.$logDetails[2].'<br/>';
- echo '</div>';
- if($logDetails[0]>=($_SERVER['REQUEST_TIME']-2592000)){
- $summary['30days'][$logDetails[1]][$logDetails[2]]++;
- }
- $summary['totals'][$logDetails[1]][$logDetails[2]]++;
- } else {
- // Log data is deencoded from JSON string
- $l=json_decode($l,true);
- // Log entry should be an array once decoded
- if(is_array($l)){
- $accepted=true;
- // Breaking out of the loop if the assigned key value is not the one that is required
- if(isset($types)){
- foreach($types as $key=>$t){
- if($key!='all' && $t!==true){
- if(!isset($l[str_replace('['.$t.']','',$key)]) || $l[str_replace('['.$t.']','',$key)]!=$t){
- $accepted=false;
- }
- }
- }
- }
- if($accepted){
- echo '<div class="border block">';
- // Printing out log data
- foreach($l as $key=>$entry){
- if(isset($_GET['internal']) || isset($types['all']) || isset($types[$key])){
- if(!is_array($entry)){
- echo '<b>'.$key.':</b> '.$entry.'<br/>';
- } else {
- echo '<b>'.$key.':</b>';
- echo '<pre class="small box disabled">';
- print_r($entry);
- echo '</pre>';
- }
- }
- }
- echo '</div>';
- }
- }
- }
-
- }
-
- } else {
- echo '<p class="bold">This log is too large for PHP to handle.</p>';
- }
-
- // Getting the content from output buffer
- $logContent=ob_get_clean();
-
- // Output buffer allows to increase peformance due to multiple echo's
- ob_start();
-
- // If summary data is set
- if(!empty($summary)){
-
- echo '<h2>Summary</h2>';
-
- if(isset($_GET['api'])){
-
- // Summary for 30 Days
- echo '<h3>Last 30 Days</h3>';
- foreach($summary['30days'] as $profile=>$data){
- echo '<h4><b>'.$profile.'</b></h4>';
- echo '<ul>';
- foreach($data as $command=>$d){
- echo '<li><b>'.$command.'</b> '.$d.' calls</li>';
- }
- echo '</ul>';
- }
-
- // Printing out summary for totals
- echo '<h3>Totals</h3>';
- foreach($summary['totals'] as $profile=>$data){
- echo '<h4><b>'.$profile.'</b></h4>';
- echo '<ul>';
- foreach($data as $command=>$d){
- echo '<li><b>'.$command.'</b> '.$d.' calls</li>';
- }
- echo '</ul>';
- }
-
- }
-
- echo '<h2>Entries</h2>';
- }
-
- // Getting the content from output buffer
- $summaryContent=ob_get_clean();
-
- // Printing out summary and log
- echo $summaryContent;
- echo $logContent;
-
- } else {
- if(isset($_GET['internal']) || isset($_GET['api']) || isset($_GET['http'])){
- // Log information not found
- echo '<p class="red bold">Cannot find log information</p>';
- } else {
- echo '<p class="bold">Please select log type</p>';
- }
- }
-
- echo '<h2>Modes</h2>';
- echo '<p><a href="log-reader.php?http">HTTP Request Log</a> - Log information about HTTP requests</p>';
- echo '<p><a href="log-reader.php?api">API Log</a> - API profile call log</p>';
- echo '<p><a href="log-reader.php?internal">Internal Log</a> - Internal log entries</p>';
-
- // Footer
- echo '<p class="footer small bold">Generated at '.date('d.m.Y h:i').' GMT '.date('P').' for '.$_SERVER['HTTP_HOST'].'</p>';
-
- ?>
- </body>
- </html>