Files
ave-cms-alt/class/class.logs.php

330 lines
8.5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
}
}
?>