Вход Регистрация
Файл: system/logger.php
Строк: 135
<?php
/* Обновление игры под PHP 8.4 / PDO и усиление безопасности: by Метриум (Стэлп) */
declare(strict_types=1);

/**
 * Central production error logger for PHP 8.4.
 * Error details are written outside the public UI to /logs.
 */
function app_log_dir(): string {
    return 
dirname(__DIR__) . '/logs';
}

function 
app_log_prune(string $dir): void {
    foreach ([
'app-error-*.log','php-error-*.log'] as $pattern) {
        
$files=(array)@glob($dir.'/'.$pattern);
        
usort($files, static fn($a,$b)=>(@filemtime($b)?:0)<=> (@filemtime($a)?:0));
        foreach(
array_slice($files,2) as $old) @unlink($old);
    }
}
function 
app_log_storage_available(string $dir): bool {
    if(!
is_dir($dir)) return false;
    
$free=@disk_free_space($dir);
    if(
$free===false) return true;
    if(
$free >= 2*1024*1024) return true;
    
app_log_prune($dir);
    
$free=@disk_free_space($dir);
    return 
$free===false || $free >= 512*1024;
}

function 
app_log_prepare(): void {
    
$dir = app_log_dir();
    if (!
is_dir($dir)) {
        @
mkdir($dir, 0755, true);
    }
    if (
is_dir($dir)) {
        
app_log_prune($dir);
        
$phpLog = $dir . '/php-error.log';
        if (
is_file($phpLog) && @filesize($phpLog) > 2 * 1024 * 1024) {
            @
rename($phpLog, $dir . '/php-error-' . date('Ymd-His') . '.log');
            
app_log_prune($dir);
        }
        @
ini_set('display_errors', '0');
        @
ini_set('display_startup_errors', '0');
        if(
app_log_storage_available($dir)) {
            @
ini_set('log_errors', '1');
            @
ini_set('error_log', $phpLog);
        } else {
            
// При полностью заполненной квоте не заставляем PHP без конца пытаться писать журнал.
            
@ini_set('log_errors', '0');
        }
    }
    
error_reporting(E_ALL);
}

function 
app_log_context(): string {
    
$method = $_SERVER['REQUEST_METHOD'] ?? 'CLI';
    
$uri = $_SERVER['REQUEST_URI'] ?? '';
    
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
    
$uid = 0;
    if (
function_exists('security_auth_user_id')) {
        try { 
$uid = (int)security_auth_user_id(); } catch (Throwable) { $uid = 0; }
    }
    return 
'method=' . $method . ' uri=' . $uri . ' ip=' . $ip . ' user=' . $uid;
}

function 
app_log_write(string $level, string $message, array $extra = []): void {
    
$dir = app_log_dir();
    if (!
is_dir($dir)) @mkdir($dir, 0755, true);

    
$file = $dir . '/app-error.log';
    
// Small rotation to prevent an old game from filling hosting storage.
    
if (is_file($file) && @filesize($file) > 2 * 1024 * 1024) {
        @
rename($file, $dir . '/app-error-' . date('Ymd-His') . '.log');
        
app_log_prune($dir);
    }
    if(!
app_log_storage_available($dir)) return;

    
$safeExtra = [];
    foreach (
$extra as $k => $v) {
        if (
is_scalar($v) || $v === null) $safeExtra[$k] = $v;
    }
    
$line = '[' . date('Y-m-d H:i:s') . '] [' . $level . '] ' . $message
          
. ' | ' . app_log_context();
    if (
$safeExtra) $line .= ' | ' . json_encode($safeExtra, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    
$line .= PHP_EOL;
    @
file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
}

function 
app_error_id(): string {
    try { return 
strtoupper(bin2hex(random_bytes(4))); }
    catch (
Throwable) { return strtoupper(substr(md5((string)microtime(true)), 0, 8)); }
}

function 
app_render_public_error(string $id): void {
    if (
PHP_SAPI === 'cli') return;
    if (!
headers_sent()) {
        
http_response_code(500);
        
header('Content-Type: text/html; charset=UTF-8');
    }
    echo 
'<div style="max-width:520px;margin:30px auto;padding:16px;background:#211;border:1px solid #633;color:#eee;font:14px Arial,sans-serif;text-align:center">'
       
. '<b>Внутренняя ошибка игры</b><br><br>'
       
. 'Код ошибки: <b>' . htmlspecialchars($id, ENT_QUOTES, 'UTF-8') . '</b><br>'
       
. '<span style="color:#aaa">Подробности записаны в папку logs.</span>'
       
. '</div>';
}

function 
app_register_error_handlers(): void {
    
app_log_prepare();

    
set_error_handler(static function (int $severity, string $message, string $file, int $line): bool {
        if (!(
error_reporting() & $severity)) return false;
        
$names = [
            
E_ERROR=>'E_ERROR', E_WARNING=>'E_WARNING', E_PARSE=>'E_PARSE', E_NOTICE=>'E_NOTICE',
            
E_CORE_ERROR=>'E_CORE_ERROR', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_ERROR=>'E_COMPILE_ERROR',
            
E_COMPILE_WARNING=>'E_COMPILE_WARNING', E_USER_ERROR=>'E_USER_ERROR', E_USER_WARNING=>'E_USER_WARNING',
            
E_USER_NOTICE=>'E_USER_NOTICE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR',
            
E_DEPRECATED=>'E_DEPRECATED', E_USER_DEPRECATED=>'E_USER_DEPRECATED'
        
];
        
app_log_write($names[$severity] ?? ('E_' . $severity), $message, ['file'=>$file, 'line'=>$line]);
        return 
true; // production: log it, do not print it into game HTML
    
});

    
set_exception_handler(static function (Throwable $e): void {
        
$id = app_error_id();
        
app_log_write('UNCAUGHT', $e::class . ': ' . $e->getMessage(), [
            
'id'=>$id,
            
'file'=>$e->getFile(),
            
'line'=>$e->getLine(),
            
'trace'=>substr($e->getTraceAsString(), 0, 6000),
        ]);
        
app_render_public_error($id);
    });

    
register_shutdown_function(static function (): void {
        
$e = error_get_last();
        if (!
$e) return;
        if (!
in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR], true)) return;
        
$id = app_error_id();
        
app_log_write('FATAL', (string)$e['message'], [
            
'id'=>$id,
            
'file'=>$e['file'] ?? '',
            
'line'=>$e['line'] ?? 0,
        ]);
        
app_render_public_error($id);
    });
}
Онлайн: 2
Реклама