0, 'INFO' => 1, 'WARNING' => 2, 'ERROR' => 3]; $currentLevel = $logLevels[LOG_LEVEL] ?? 1; if (($logLevels[$level] ?? 1) < $currentLevel) { return; } $timestamp = date('Y-m-d H:i:s'); $contextStr = $context ? ' ' . json_encode($context) : ''; $logMessage = "[$timestamp] [$level] $message$contextStr" . PHP_EOL; $logDir = dirname(dirname(__FILE__)) . '/logs'; if (!is_dir($logDir)) { mkdir($logDir, 0755, true); } file_put_contents($logDir . '/system.log', $logMessage, FILE_APPEND | LOCK_EX); } } // Función para verificar si la instalación está completada if (!function_exists('isInstallationCompleted')) { function isInstallationCompleted() { return file_exists(dirname(__DIR__) . '/.installation_completed'); } } // Función para verificar login if (!function_exists('isUserLoggedIn')) { function isUserLoggedIn() { return isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true; } } // Función para verificar intentos de login if (!function_exists('checkLoginAttempts')) { function checkLoginAttempts($ip) { $attemptsFile = dirname(__DIR__) . '/.login_attempts.json'; if (!file_exists($attemptsFile)) { return true; } $attempts = json_decode(file_get_contents($attemptsFile), true); if (!isset($attempts[$ip])) { return true; } $ipData = $attempts[$ip]; if (time() > $ipData['locked_until']) { unset($attempts[$ip]); file_put_contents($attemptsFile, json_encode($attempts)); return true; } return $ipData['attempts'] < MAX_LOGIN_ATTEMPTS; } } // Función para registrar intento de login fallido if (!function_exists('recordFailedLogin')) { function recordFailedLogin($ip) { $attemptsFile = dirname(__DIR__) . '/.login_attempts.json'; $attempts = []; if (file_exists($attemptsFile)) { $attempts = json_decode(file_get_contents($attemptsFile), true) ?: []; } if (!isset($attempts[$ip])) { $attempts[$ip] = ['attempts' => 0, 'locked_until' => 0]; } $attempts[$ip]['attempts']++; if ($attempts[$ip]['attempts'] >= MAX_LOGIN_ATTEMPTS) { $attempts[$ip]['locked_until'] = time() + LOGIN_LOCKOUT_TIME; } file_put_contents($attemptsFile, json_encode($attempts)); writeLog('WARNING', 'Failed login attempt', ['ip' => $ip, 'attempts' => $attempts[$ip]['attempts']]); } } // Función para limpiar intentos de login exitoso if (!function_exists('clearLoginAttempts')) { function clearLoginAttempts($ip) { $attemptsFile = dirname(__DIR__) . '/.login_attempts.json'; if (file_exists($attemptsFile)) { $attempts = json_decode(file_get_contents($attemptsFile), true) ?: []; unset($attempts[$ip]); file_put_contents($attemptsFile, json_encode($attempts)); } writeLog('INFO', 'Successful login', ['ip' => $ip]); } } // Autoloader mejorado spl_autoload_register(function ($class) { $directories = [ dirname(__DIR__) . '/classes/', dirname(__DIR__) . '/services/', dirname(__DIR__) . '/controllers/' ]; foreach ($directories as $directory) { $file = $directory . $class . '.php'; if (file_exists($file)) { require_once $file; writeLog('DEBUG', 'Class loaded', ['class' => $class, 'file' => $file]); return; } } writeLog('ERROR', 'Class not found', ['class' => $class]); }); // Función para obtener configuración desde base de datos if (!function_exists('getConfigFromDB')) { function getConfigFromDB($key, $default = null) { static $configs = null; if ($configs === null && isInstallationCompleted()) { try { $pdo = new PDO( "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ] ); $stmt = $pdo->query("SELECT config_key, config_value FROM system_config"); $configs = []; while ($row = $stmt->fetch()) { $configs[$row['config_key']] = $row['config_value']; } writeLog('DEBUG', 'Database configuration loaded'); } catch (PDOException $e) { writeLog('ERROR', 'Error loading config from database', ['error' => $e->getMessage()]); $configs = []; } } return $configs[$key] ?? $default; } } // Función para validar configuración de WhatsApp if (!function_exists('validateWhatsAppConfig')) { function validateWhatsAppConfig() { $errors = []; if (WHATSAPP_TOKEN === 'TU_TOKEN_DE_WHATSAPP_AQUI' || empty(WHATSAPP_TOKEN)) { $errors[] = 'Token de WhatsApp no configurado'; } if (WHATSAPP_PHONE_NUMBER_ID === 'TU_PHONE_ID_AQUI' || empty(WHATSAPP_PHONE_NUMBER_ID)) { $errors[] = 'Phone Number ID de WhatsApp no configurado'; } if (empty(WEBHOOK_VERIFY_TOKEN)) { $errors[] = 'Token de verificación del webhook no configurado'; } return $errors; } } // Función para crear directorio si no existe if (!function_exists('ensureDirectoryExists')) { function ensureDirectoryExists($path) { if (!is_dir($path)) { mkdir($path, 0755, true); writeLog('INFO', 'Directory created', ['path' => $path]); } } } // Crear directorios necesarios ensureDirectoryExists(dirname(__DIR__) . '/logs'); ensureDirectoryExists(dirname(__DIR__) . '/uploads'); // Inicializar sesión si no está activa if (session_status() == PHP_SESSION_NONE) { ini_set('session.cookie_httponly', 1); ini_set('session.cookie_secure', isset($_SERVER['HTTPS'])); ini_set('session.use_strict_mode', 1); // Asegurar que la cookie de sesión y GC respeten el timeout configurado (SESSION_TIMEOUT) // Si SESSION_TIMEOUT <= 0 lo interpretamos como "persistente" (no expira): usamos un valor grande para cookie y GC $cookieLifetime = (int)SESSION_TIMEOUT; if ($cookieLifetime <= 0) { // 10 años en segundos $cookieLifetime = 10 * 365 * 24 * 60 * 60; } ini_set('session.cookie_lifetime', $cookieLifetime); ini_set('session.gc_maxlifetime', $cookieLifetime); session_start(); } // Verificar timeout de sesión (solo si SESSION_TIMEOUT > 0) if (isUserLoggedIn() && isset($_SESSION['last_activity'])) { if (defined('SESSION_TIMEOUT') && (int)SESSION_TIMEOUT > 0 && (time() - $_SESSION['last_activity'] > (int)SESSION_TIMEOUT)) { writeLog('INFO', 'Session timeout', ['user' => $_SESSION['username'] ?? 'unknown']); session_destroy(); session_start(); } } // Actualizar última actividad if (isUserLoggedIn()) { $_SESSION['last_activity'] = time(); } // Registrar acceso si está habilitado el logging if (ENABLE_LOGGING && isset($_SERVER['REQUEST_URI'])) { $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'; $ip = $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; writeLog('DEBUG', 'Page access', [ 'uri' => $_SERVER['REQUEST_URI'], 'ip' => $ip, 'user_agent' => substr($userAgent, 0, 100) ]); } ?>