Files

330 lines
8.5 KiB
PHP

<?php
/**
* AVE.cms
*
* Класс, предназначенный для управления журналом системных сообщений
* (Оптимизировано чтение для больших файлов логов)
*
* @package AVE.cms
* @version 4.x
* @filesource
* @copyright © 2007-2026 AVE.cms, https://ave4cms.ru
*
*/
class AVE_Logs
{
/**
* Свойства класса
*/
/**
* Файлы для хранения записей
*
* @public
*/
public $_404dir = '/tmp/logs/404.csv';
public $_logdir = '/tmp/logs/log.csv';
public $_sqldir = '/tmp/logs/sql.csv';
/**
* Внутренние методы класса
*/
/**
* Вспомогательный метод для чтения последних строк файла с конца
*
* @param string $file_name Путь к файлу
* @param int $_count Количество строк, которые нужно прочитать
* @param int $chunk_size Размер блока для чтения
* @return array Массив строк в прямом хронологическом порядке
*/
private function readLastLines($file_name, $_count, $chunk_size = 8192)
{
if (!file_exists($file_name) || !($fp = @fopen($file_name, 'rb'))) {
return [];
}
$file_size = @filesize($file_name);
$pos = $file_size;
$buffer = '';
$raw_lines = [];
// Чтение файла блоками с конца
while ($pos > 0 && count($raw_lines) < $_count) {
$bytes_to_read = min($chunk_size, $pos);
$pos -= $bytes_to_read;
fseek($fp, $pos);
$chunk = fread($fp, $bytes_to_read);
$buffer = $chunk . $buffer;
if ($pos == 0) {
$lines = explode("\n", $buffer);
$buffer = '';
} else {
$lines = explode("\n", $buffer);
$buffer = array_shift($lines);
}
foreach (array_reverse($lines) as $line) {
if (trim($line) !== '') {
$raw_lines[] = $line;
if (count($raw_lines) >= $_count) {
break 2;
}
}
}
}
fclose($fp);
// Разворачиваем, чтобы получить правильный хронологический порядок
return array_reverse($raw_lines);
}
/**
* Внешние методы класса
*/
/**
* Метод, предназначенный для отображения всех записей Журнала событий (log.csv)
*
*/
function logList ()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_logdir;
$_count = 10000;
$_lines = [];
$raw_lines = $this->readLastLines($file_name, $_count);
foreach ($raw_lines as $line) {
$event = str_getcsv($line, ',', '"', '\\');
if (empty($event[0]) || count($event) < 3) {
continue;
}
$_lines[] = [
'log_time' => $event['0'] ?? '',
'log_ip' => $event['1'] ?? '',
'log_url' => $event['2'] ?? '',
'log_user_id' => $event['3'] ?? '',
'log_user_name' => $event['4'] ?? '',
'log_text' => $event['5'] ?? '',
'log_type' => $event['6'] ?? '',
'log_rubric' => $event['7'] ?? ''
];
}
$AVE_Template->assign('logs', $_lines);
$AVE_Template->assign('content', $AVE_Template->fetch('logs/logs.tpl'));
}
/**
* Метод, предназначенный для отображения всех записей Журнала событий 404 (404.csv)
*
*/
function List404()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_404dir;
$_count = 10000;
$_lines = [];
$raw_lines = $this->readLastLines($file_name, $_count);
foreach ($raw_lines as $line) {
$event = str_getcsv($line, ',', '"', '\\');
if (empty($event[0]) || count($event) < 3) {
continue;
}
$_lines[] = [
'log_time' => $event['0'] ?? '',
'log_ip' => $event['1'] ?? '',
'log_query' => $event['2'] ?? '',
'log_user_agent' => $event['3'] ?? '',
'log_user_referer' => $event['4'] ?? '',
'log_request_uri' => $event['5'] ?? ''
];
}
$AVE_Template->assign('logs', $_lines);
$AVE_Template->assign('content', $AVE_Template->fetch('logs/404.tpl'));
}
/**
* Метод, предназначенный для отображения всех записей Журнала событий SQL (sql.csv)
*
*/
function ListSql()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_sqldir;
$_count = 10000;
$_lines = [];
$raw_lines = $this->readLastLines($file_name, $_count);
foreach ($raw_lines as $line) {
$event = str_getcsv($line);
if (empty($event[0]) || count($event) < 3) {
continue;
}
$_lines[] = [
'log_time' => $event['0'] ?? '',
'log_ip' => $event['1'] ?? '',
'log_url' => $event['2'] ?? '',
'log_user_id' => $event['3'] ?? '',
'log_user_name' => $event['4'] ?? '',
'log_text' => isset($event['5']) ? unserialize(base64_decode($event['5'])) : ''
];
}
$AVE_Template->assign('logs', $_lines);
$AVE_Template->assign('content', $AVE_Template->fetch('logs/sql.tpl'));
}
function logDelete()
{
global $AVE_Template;
$logfile = BASE_DIR . $this->_logdir;
if(file_exists($logfile)) unlink($logfile);
reportLog($AVE_Template->get_config_vars('LOGS_CLEAN'));
header('Location:index.php?do=logs&cp=' . SESSION);
exit;
}
function DeleteSql()
{
global $AVE_Template;
$logfile = BASE_DIR . $this->_sqldir;
if(file_exists($logfile)) unlink($logfile);
reportLog($AVE_Template->get_config_vars('LOGS_SQL_CLEAN'));
header('Location:index.php?do=logs&action=logsql&cp=' . SESSION);
exit;
}
function Delete404()
{
global $AVE_Template;
$logfile = BASE_DIR . $this->_404dir;
if(file_exists($logfile)) unlink($logfile);
reportLog($AVE_Template->get_config_vars('LOGS_404_CLEAN'));
header('Location:index.php?do=logs&action=log404&cp=' . SESSION);
exit;
}
/**
* Экспорт системных сообщений
*/
function logExport()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_logdir;
if (!file_exists($file_name)) exit;
$dateName = 'system_log_' . date('dmyhis', time()) . '.csv';
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $dateName . '"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF";
$fp = fopen($file_name, 'rb');
$out = fopen('php://output', 'w');
while (($data = fgetcsv($fp, 0, ',', '"', '\\')) !== FALSE) {
if (isset($data[2])) $data[2] = urldecode($data[2]);
fputcsv($out, $data, ',', '"', '\\');
}
fclose($fp);
fclose($out);
reportLog($AVE_Template->get_config_vars('LOGS_EXPORT'));
exit;
}
/**
* Экспорт сообщений 404
*/
function Export404()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_404dir;
if (!file_exists($file_name)) exit;
$dateName = 'system_404_' . date('dmyhis', time()) . '.csv';
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $dateName . '"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF";
$fp = fopen($file_name, 'rb');
$out = fopen('php://output', 'w');
while (($data = fgetcsv($fp, 0, ',', '"', '\\')) !== FALSE) {
if (isset($data[2])) $data[2] = urldecode($data[2]);
if (isset($data[4])) $data[4] = urldecode($data[4]);
if (isset($data[5])) $data[5] = urldecode($data[5]);
fputcsv($out, $data, ',', '"', '\\');
}
fclose($fp);
fclose($out);
reportLog($AVE_Template->get_config_vars('LOGS_EXPORT'));
exit;
}
/**
* Экспорт сообщений MySql
*/
function ExportSql()
{
global $AVE_Template;
$file_name = BASE_DIR . $this->_sqldir;
if (!file_exists($file_name)) exit;
$dateName = 'system_sql_' . date('dmyhis', time()) . '.csv';
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $dateName . '"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF";
$fp = fopen($file_name, 'rb');
$out = fopen('php://output', 'w');
while (($data = fgetcsv($fp, 0, ',', '"', '\\')) !== FALSE) {
fputcsv($out, $data, ',', '"', '\\');
}
fclose($fp);
fclose($out);
reportLog($AVE_Template->get_config_vars('LOGS_EXPORT'));
exit;
}
}
?>