File: /home/thwoodlg/public_html/wp-content/plugins/duplicator-pro/classes/class.php.log.php
<?php
defined("ABSPATH") or die("");
class DUP_PRO_PHP_Log
{
/*
* GET ERROR LOG DIRECT PATH
* @param $custom -Custom path
* @param $unsafe -If is true, function only check is file exists but not chmod and type
* @return array or false on fail
*/
public static function get_path($custom=NULL, $unsafe = false){
// Find custom path
if(!empty($custom))
{
if($unsafe === true && file_exists($custom) && is_file($custom)){
return $custom;
}else if(is_file($custom) && is_readable($custom)){
return $custom;
}else{
return false;
}
}
$path = self::find_path($unsafe);
if($path!==false) {
return strtr($path,array(
'\\' => '/',
'//' => '/'
));
}
return false;
}
/**
* GET ERROR LOG DATA
*
* @param $custom -Custom path
* @param $limit -Number of lines
* @param $time_format -$time format how you like to see in log
* @return array or false on fail
*/
public static function get_log($custom = NULL, $limit = 200, $time_format = "Y-m-d H:i:s"){
return self::parse_log($custom, $limit, $time_format);
}
/*
* GET FILENAME FROM PATH
*
* @param $path
* @return string -Filename
*/
public static function get_filename($path){
if( $path === false || !is_readable($path) || !is_file($path) ) return false;
$path = strtr($path,array(
'\\' => '/',
'//' => '/'
));
$log_part = explode('/',$path);
return end($log_part);
}
/*
* CLEAR PHP ERROR LOG
*
* @param $path
* @return bool
*/
public static function clear_log($path){
return self::clear_error_log($path);
}
/*
* ============== PRIVATE AREA =================
*/
/**
* Parses the PHP error log to an array.
*
* @return array , NULL or false
*/
private static function parse_log($custom = NULL, $limit = 200, $time_format = "Y-m-d H:i:s") {
$parsedLogs = array();
$path = self::find_path($custom);
$contents = NULL;
// return false for bad path
if($path === false) return false;
try {
// Good old shell can solve this in less of second
if(!DupProSnapLibOSU::isWindows()) {
if(is_callable('shell_exec') && is_callable('shell_exec') && false === stripos(ini_get('disable_functions'), 'shell_exec')){
$contents = shell_exec("tail -{$limit} {$path}");
}
}
// Shell fail on various cases, now we are ready to rock
if(NULL === $contents || false === $contents || empty($contents))
{
// If "SplFileObject" is available use it
if(class_exists('SplFileObject') && class_exists('LimitIterator')){
$file = new SplFileObject($path, 'rb');
$file->seek(PHP_INT_MAX);
$last_line = $file->key();
if($last_line > 0){
++$limit;
$lines = new LimitIterator($file, (($last_line - $limit) <= 0 ? 0 : $last_line - $limit), ($last_line > 1 ? ($last_line+1) : $last_line));
$contents = iterator_to_array($lines);
$contents = join("\n",$contents);
}
} else {
// Or good old fashion fopen()
$contents = NULL;
$limit = ($limit + 2);
$lines=array();
if($fp = fopen($path, "rb")){
while(!feof($fp)) {
$line = fgets($fp, 4096);
array_push($lines, $line);
if (count($lines) > $limit) {
array_shift($lines);
}
}
fclose($fp);
if(count($lines)>0)
{
foreach($lines as $a=>$line){
$contents.= "\n{$line}";
}
}
} else return NULL;
}
}
} catch (Exception $exc) {
//echo $exc->getTraceAsString();
echo 'ERROR?';
// Return NULL to we know that somethis is totaly wrong
return NULL;
}
// Little magic with \n
$contents = trim($contents, "\n");
$contents = preg_replace("/\n{2,}/U","\n",$contents);
$lines = explode("\n", $contents);
/* DEBUG */
if(isset($_GET['debug_log']) && $_GET['debug_log'] == 'true')
echo '<pre style="background:#fff; padding:10px;word-break: break-all;display:block;white-space: pre-line;">', var_export($contents,true),'</pre>';
// Must clean memory ASAP
unset($contents);
// Let's arse things on the right way
$currentLineNumberCount = count($lines);
for ($currentLineNumber = 0; $currentLineNumber < $currentLineNumberCount; ++$currentLineNumber) {
$currentLine = trim($lines[$currentLineNumber]);
// Normal error log line starts with the date & time in []
if ('[' === substr($currentLine, 0, 1)) {
// Get the datetime when the error occurred
$dateArr = array();
preg_match('~^\[(.*?)\]~', $currentLine, $dateArr);
$currentLine = str_replace($dateArr[0], NULL, $currentLine);
$currentLine = trim($currentLine);
$dateArr = explode(' ', $dateArr[1]);
$errorDateTime = date($time_format, strtotime($dateArr[0] . ' ' . $dateArr[1]));
// Get the type of the error
$errorType = NULL;
if (false !== strpos($currentLine, 'PHP Warning')) {
$currentLine = str_replace('PHP Warning:', NULL, $currentLine);
$currentLine = trim($currentLine);
$errorType = 'WARNING';
} else if (false !== strpos($currentLine, 'PHP Notice')) {
$currentLine = str_replace('PHP Notice:', NULL, $currentLine);
$currentLine = trim($currentLine);
$errorType = 'NOTICE';
} else if (false !== strpos($currentLine, 'PHP Fatal error')) {
$currentLine = str_replace('PHP Fatal error:', NULL, $currentLine);
$currentLine = trim($currentLine);
$errorType = 'FATAL';
} else if (false !== strpos($currentLine, 'PHP Parse error')) {
$currentLine = str_replace('PHP Parse error:', NULL, $currentLine);
$currentLine = trim($currentLine);
$errorType = 'SYNTAX';
} else if (false !== strpos($currentLine, 'PHP Exception')) {
$currentLine = str_replace('PHP Exception:', NULL, $currentLine);
$currentLine = trim($currentLine);
$errorType = 'EXCEPTION';
}
if (false !== strpos($currentLine, ' on line ')) {
$errorLine = explode(' on line ', $currentLine);
$errorLine = trim($errorLine[1]);
$currentLine = str_replace(' on line ' . $errorLine, NULL, $currentLine);
} else {
$errorLine = substr($currentLine, strrpos($currentLine, ':') + 1);
$currentLine = str_replace(':' . $errorLine, NULL, $currentLine);
}
$errorFile = explode(' in ', $currentLine);
$errorFile = trim(isset($errorFile[1])?$errorFile[1]:NULL);
$currentLine = str_replace(' in ' . $errorFile, NULL, $currentLine);
// The message of the error
$errorMessage = trim($currentLine);
$parsedLogs[] = array(
'dateTime' => $errorDateTime,
'type' => $errorType,
'file' => $errorFile,
'line' => (int)$errorLine,
'message' => $errorMessage,
'stackTrace' => array()
);
} // Stack trace beginning line
else if ('Stack trace:' === $currentLine) {
$stackTraceLineNumber = 0;
for (++$currentLineNumber; $currentLineNumber < $currentLineNumberCount; ++$currentLineNumber) {
$currentLine = NULL;
if(isset($lines[$currentLineNumber]))
$currentLine = trim($lines[$currentLineNumber]);
// If the current line is a stack trace line
if ('#' === substr($currentLine, 0, 1)) {
$parsedLogsKeys=array_keys($parsedLogs);
$parsedLogsLastKey = end($parsedLogsKeys);
$currentLine = str_replace('#' . $stackTraceLineNumber, NULL, $currentLine);
$parsedLogs[$parsedLogsLastKey]['stackTrace'][] = trim($currentLine);
++$stackTraceLineNumber;
} // If the current line is the last stack trace ('thrown in...')
else {
break;
}
}
}
}
// Sort DESC
rsort($parsedLogs);
// Reurn array
return $parsedLogs;
}
/*
* Clear error log file
*/
private static function clear_error_log($custom=NULL){
// Get error log
$path = self::find_path($custom);
// Get log file name
$filename = self::get_filename($path);
// Reutn error
if(!$filename) false;
$dir = dirname($path);
$dir = strtr($dir,array(
'\\' => '/',
'//' => '/'
));
unlink($path);
return touch($dir.'/'.$filename);
}
/*
* Find PHP error log file
*/
private static function find_path($unsafe=false){
// If ini_get is enabled find path
if(function_exists('ini_get')){
$path = ini_get('error_log');
if($unsafe === true && file_exists($path) && is_file($path)) return $path;
if(is_file($path) && is_readable($path)) return $path;
}
// HACK: If ini_get is disabled, try to parse php.ini
if(function_exists('php_ini_loaded_file') && function_exists('parse_ini_file')) {
$ini_path = php_ini_loaded_file();
if(is_file($ini_path) && is_readable($ini_path)){
$parse_ini = parse_ini_file($ini_path);
if($unsafe === true && isset($parse_ini["error_log"]) && file_exists($parse_ini["error_log"]) && is_file($parse_ini["error_log"])) return $parse_ini["error_log"];
if(isset($parse_ini["error_log"]) && file_exists($parse_ini["error_log"]) && is_readable($parse_ini["error_log"])){
return $parse_ini["error_log"];
}
}
}
// PHP.ini fail or not contain informations what we need. Let's look on few places
$possible_places = array(
// Look into root
get_home_path(),
// Look out of root
dirname(get_home_path()),
//Other places
'/etc/httpd/logs',
'/var/log/apache2',
'/var/log/httpd',
'/var/log',
'/var/www/html',
'/var/www',
// Some wierd cases
get_home_path().'/logs',
get_home_path().'/log',
dirname(get_home_path()).'/logs',
dirname(get_home_path()).'/log',
'/etc/httpd/log',
'/var/logs/apache2',
'/var/logs/httpd',
'/var/logs',
'/var/www/html/logs',
'/var/www/html/log',
'/var/www/logs',
'/var/www/log',
);
$possible_filenames = array(
'error.log',
'error_log',
'php_error',
'php5-fpm.log',
'error_log.txt',
'php_error.txt',
);
foreach($possible_filenames as $filename){
foreach($possible_places as $possibility){
$possibility = $possibility.'/'.$filename;
if($unsafe === true && file_exists($possibility) && is_file($possibility)) {
return $possibility;
} else if(is_file($possibility) && is_readable($possibility)){
return $possibility;
}
}
}
return false;
}
}