// Global Security Headers header("X-Frame-Options: SAMEORIGIN"); header("X-XSS-Protection: 1; mode=block"); header("X-Content-Type-Options: nosniff"); header("Referrer-Policy: strict-origin-when-cross-origin"); header("Content-Security-Policy: default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google.com https://www.gstatic.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://www.google.com;"); // Error Handling (Production Mode) if (defined('ENVIRONMENT') && ENVIRONMENT === 'production') { error_reporting(0); ini_set('display_errors', 0); // Set custom error handler to redirect to a pretty error page set_exception_handler(function($e) { logActivity('system_error', $e->getMessage()); header('Location: ' . SITE_URL . '/error'); exit(); }); } else { error_reporting(E_ALL); ini_set('display_errors', 1); } // Session Hardening ini_set('session.cookie_httponly', 1); ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) ? 1 : 0); ini_set('session.use_only_cookies', 1); ini_set('session.cookie_samesite', 'Lax'); session_start(); // Load .env file function loadEnv($path) { if (!file_exists($path)) return false; $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($lines as $line) { $line = trim($line); if (empty($line) || strpos($line, '#') === 0) continue; if (strpos($line, '=') === false) continue; list($name, $value) = explode('=', $line, 2); $name = trim($name); $value = trim($value); if (!array_key_exists($name, $_SERVER) && !array_key_exists($name, $_ENV)) { putenv(sprintf('%s=%s', $name, $value)); $_ENV[$name] = $value; $_SERVER[$name] = $value; } } return true; } loadEnv(__DIR__ . '/../.env'); // Database configuration require_once 'database.php'; // Site configuration $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST'] ?? 's3.vixso.in'; define('SITE_URL', getenv('SITE_URL') ?: $protocol . '://' . $host); define('SITE_NAME', getenv('SITE_NAME') ?: 'Pitechpedia Forms'); // SMTP Configuration define('SMTP_HOST', getenv('SMTP_HOST') ?: 'localhost'); define('SMTP_PORT', getenv('SMTP_PORT') ?: 587); define('SMTP_USERNAME', getenv('SMTP_USER') ?: 'noreply@example.com'); define('SMTP_PASSWORD', getenv('SMTP_PASS') ?: ''); define('FROM_EMAIL', getenv('FROM_EMAIL') ?: 'noreply@example.com'); define('FROM_NAME', SITE_NAME); // Google Sheets API Credentials define('GOOGLE_CLIENT_ID', getenv('GOOGLE_CLIENT_ID') ?: ''); define('GOOGLE_CLIENT_SECRET', getenv('GOOGLE_CLIENT_SECRET') ?: ''); // Security settings define('SESSION_TIMEOUT', 3600); // 1 hour // Hardened Session Settings ini_set('session.cookie_httponly', 1); ini_set('session.use_only_cookies', 1); if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') { ini_set('session.cookie_secure', 1); } // Timezone date_default_timezone_set('UTC'); // Error reporting (disable in production) if (getenv('APP_ENV') === 'production') { error_reporting(0); ini_set('display_errors', 0); } else { error_reporting(E_ALL); ini_set('display_errors', 1); } // Helper functions function sanitizeInput($data) { return htmlspecialchars(strip_tags(trim($data))); } function isLoggedIn() { return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']); } function requireLogin() { if (!isLoggedIn()) { header('Location: ' . SITE_URL . '/login'); exit(); } } function hasRole($required_role) { if (!isLoggedIn()) return false; $allowed_roles = [ 'admin' => ['admin'], 'company' => ['admin', 'company'], 'user' => ['admin', 'company', 'user'] ]; return in_array($_SESSION['role'], $allowed_roles[$required_role] ?? []); } function requireRole($required_role) { if (!hasRole($required_role)) { header('Location: ' . SITE_URL . '/unauthorized'); exit(); } } function generateCSRFToken() { if (!isset($_SESSION['csrf_token']) || empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } function validateCSRFToken($token) { return isset($_SESSION['csrf_token']) && !empty($token) && hash_equals($_SESSION['csrf_token'], $token); } function csrfField() { echo ''; } /** * Global Output Escaping Helper (XSS Prevention) */ function e($string) { return htmlspecialchars($string ?? '', ENT_QUOTES, 'UTF-8'); } /** * Activity Logging */ function logActivity($action, $details = '') { global $db; if (!$db) { $database = new Database(); $db = $database->getConnection(); } try { $user_id = $_SESSION['user_id'] ?? null; $ip = $_SERVER['REMOTE_ADDR']; $ua = $_SERVER['HTTP_USER_AGENT']; $stmt = $db->prepare("INSERT INTO activity_log (user_id, action, details, ip_address, user_agent) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$user_id, $action, $details, $ip, $ua]); } catch (Exception $e) { // Silently fail to prevent breaking the app flow } } /** * Global Rate Limiter * @param string $action The action to rate limit (e.g., 'login', 'submission') * @param int $limit Max attempts * @param int $seconds Time window */ function checkRateLimit($action, $limit = 5, $seconds = 60) { if (!isset($_SESSION['rate_limit'])) { $_SESSION['rate_limit'] = []; } $now = time(); $key = $action . '_' . $_SERVER['REMOTE_ADDR']; if (!isset($_SESSION['rate_limit'][$key])) { $_SESSION['rate_limit'][$key] = []; } // Cleanup old attempts $_SESSION['rate_limit'][$key] = array_filter($_SESSION['rate_limit'][$key], function($t) use ($now, $seconds) { return $t > ($now - $seconds); }); if (count($_SESSION['rate_limit'][$key]) >= $limit) { return false; } $_SESSION['rate_limit'][$key][] = $now; return true; } function generateRandomToken($length = 8) { $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; $token = ''; for ($i = 0; $i < $length; $i++) { $token .= $chars[random_int(0, strlen($chars) - 1)]; } return $token; } ?>