Files
IPB/system/Log/Disk.php
T
2025-12-19 04:57:54 -08:00

274 lines
5.9 KiB
PHP

<?php
/**
* @brief Disk Log Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 12 Nov 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Log;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Disk log class
*/
class _Disk extends \IPS\Log
{
/* @Brief Log directory */
public $logDir = NULL;
/**
* The constructor
*
* @param array|null $config
* @param int $severity
* @return void
*/
public function __construct( $config, $severity )
{
$this->logDir = \IPS\ROOT_PATH . '/uploads/logs';
parent::__construct( $config, $severity );
}
/**
* Get the most recent log titles
*
* @param int $limit
* @return array array( array( 'date' => unixTimeStamp, 'title' => title, 'suffix' => suffix ), ... );
*/
public function getMostRecentLogsTitles( $limit=50 )
{
$logs = array();
if ( is_dir( $this->logDir ) )
{
$dir = new \DirectoryIterator( $this->logDir );
$files = array();
foreach ( $dir as $file )
{
if ( ! $file->isDir() and ! $file->isDot() and mb_substr( $file, -4 ) === '.php' and mb_substr( $file, 0, 6 ) !== 'latest' )
{
$files[ $file->getMTime() ] = $file->getFilename();
}
}
krsort( $files );
$set = array_slice( $files, 0, $limit, true );
foreach( $set as $mtime => $name )
{
$suffix = mb_substr( mb_substr( $name, 0, -4 ), 11 ); #[YYYY-mm-dd_]suffix[.cgi]
$logs[] = array( 'date' => $mtime, 'title' => $name, 'suffix' => $suffix );
}
}
return $logs;
}
/**
* Get latest logs
*
* @param \IPS\DateTime $date Limit only to logs after this date
* @return array
*/
public function getLatestTitles( \IPS\DateTime $date )
{
$logs = array();
if ( is_dir( $this->logDir ) )
{
$dir = new \DirectoryIterator( $this->logDir );
foreach ( $dir as $file )
{
if ( ! $file->isDir() and ! $file->isDot() and mb_substr( $file, -4 ) === '.php' and mb_substr( $file, 0, 6 ) === 'latest' and $file->getMTime() > $date->getTimestamp() )
{
$logs[ $file->getMTime() ] = $file->getFilename();
}
}
krsort( $logs );
}
return $logs;
}
/**
* Get log content
*
* @param string $title Title of log to fetch
* @return string Raw log contents
*/
public function getLog( $title )
{
/* Paranoid clean */
$title = preg_replace( '#^[^a-z0-9-_\.]+?$#i', '', $title );
if ( file_exists( $this->logDir . '/' . $title ) )
{
/* Get the last 300 lines max */
$handle = @fopen( $this->logDir . '/' . $title, 'r' );
$content = '';
$lines = 300;
if ( $handle )
{
$l = $lines;
$pos = -2;
$beg = false;
while ( $l > 0 )
{
$_t = " ";
while( $_t != "\n" )
{
if ( @fseek( $handle, $pos, SEEK_END ) == -1 )
{
$beg = true;
break;
}
$_t = @fgetc( $handle );
$pos--;
}
$l--;
if ( $beg )
{
rewind( $handle );
break;
}
$t[ $lines - $l - 1 ] = @fgets( $handle );
}
@fclose ($handle);
$content = trim( implode( "", array_reverse( $t ) ) );
}
return $content;
}
return NULL;
}
/**
* Prune logs
*
* @param int $days Older than (days) to prune
* @return void
*/
public function prune( $days )
{
try
{
foreach( new \DirectoryIterator( $this->logDir ) as $file )
{
if( $file->isDot() OR !$file->isFile() )
{
continue;
}
if( preg_match( "#.cgi$#", $file->getFilename(), $matches ) or ( preg_match( "#.php$#", $file->getFilename(), $matches ) and $file->getMTime() < ( time() - ( 60 * 60 * 24 * (int) $days ) ) ) )
{
@unlink( $file->getPathname() );
}
}
} catch ( Exception $e ) {}
}
/**
* Log
*
* @param string $message The message
* @param string $suffix Unique key for this log
* @return void
*/
public function write( $message, $suffix=NULL )
{
$date = date( 'r' );
$ip = $this->getIpAddress();
$url = ( mb_strtolower( php_sapi_name() ) == 'cli' ) ? "Command line" : \IPS\Request::i()->url();
$fileSuffix = ( $suffix !== NULL ) ? '_' . $suffix : '';
if ( is_array( $message ) )
{
$message = var_export( $message, TRUE );
}
#$debug = @print_r( debug_backtrace(), true );
$header = "<?php exit; ?>\n\n";
$message = <<<MSG
{$date} (Severity: {$this->severity})
{$ip} - {$url}
{$message}
------------------------------------------------------------------------
MSG;
if ( ! is_dir( $this->logDir ) )
{
if ( ! @mkdir( $this->logDir ) )
{
if( $this->severity === LOG_DEBUG )
{
return;
}
throw new \RuntimeException( 'COULD_NOT_CREATE_LOG_DIR' );
}
@chmod( $this->logDir, \IPS\IPS_FOLDER_PERMISSION );
}
/* Latest */
if ( ! @\file_put_contents( $this->logDir . '/latest' . $fileSuffix . '.php', $header . $message ) )
{
if( $this->severity === LOG_DEBUG )
{
return;
}
throw new \RuntimeException( 'COULD_NOT_WRITE_FILE' );
}
@chmod( $this->logDir . '/latest' . $fileSuffix . '.php', \IPS\IPS_FILE_PERMISSION );
/* Log */
$file = $this->logDir . '/' . date( 'Y' ) . '_' . date( 'm' ) . '_' . date('d') . $fileSuffix . '.php';
if ( file_exists( $file ) )
{
$return = @\file_put_contents( $file, $message, FILE_APPEND );
}
else
{
$return = @\file_put_contents( $file, $header . $message );
}
if ( !$return )
{
if( $this->severity === LOG_DEBUG )
{
return;
}
throw new \RuntimeException( 'COULD_NOT_WRITE_FILE' );
}
@chmod( $file, \IPS\IPS_FILE_PERMISSION );
}
}