Вход Регистрация
Файл: 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($dir0755true);
    }
    if (
is_dir($dir)) {
        
app_log_prune($dir);
        
$phpLog $dir '/php-error.log';
        if (
is_file($phpLog) && @filesize($phpLog) > 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 $levelstring $message, array $extra = []): void {
    
$dir app_log_dir();
    if (!
is_dir($dir)) @mkdir($dir0755true);

    
$file $dir '/app-error.log';
    
// Small rotation to prevent an old game from filling hosting storage.
    
if (is_file($file) && @filesize($file) > 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($safeExtraJSON_UNESCAPED_UNICODE JSON_UNESCAPED_SLASHES);
    
$line .= PHP_EOL;
    @
file_put_contents($file$lineFILE_APPEND LOCK_EX);
}

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

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($idENT_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 $severitystring $messagestring $fileint $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(), 06000),
        ]);
        
app_render_public_error($id);
    });

    
register_shutdown_function(static function (): void {
        
$e error_get_last();
        if (!
$e) return;
        if (!
in_array($e['type'], [E_ERRORE_PARSEE_CORE_ERRORE_COMPILE_ERRORE_USER_ERRORE_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);
    });
}
Онлайн: 4
Реклама