1 <?php 2 /** 3 * Nexus Forum — Core Configuration 4 * Auto-detects base path. Loads db_config.php if present. 5 */ 6 if (!defined('NEXUS')) { http_response_code(403); exit('Forbidden'); } 7 8 /* ── Paths ──────────────────────────────────────────────────── */ 9 define('ROOT', dirname(__DIR__)); 10 define('DATA', ROOT . '/data'); 11 define('UPLOADS', ROOT . '/public/uploads'); 12 13 /* ── Base URL detection ─────────────────────────────────────── */ 14 if (!defined('BASE')) { 15 $docRoot = rtrim(str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT'] ?? ''), '/'); 16 $rootPath = str_replace('\\', '/', ROOT); 17 $base = str_replace($docRoot, '', $rootPath); 18 $base = '/' . trim($base, '/'); 19 define('BASE', $base === '/' ? '' : $base); 20 } 21 22 /* ── Database config (written by installer) ─────────────────── */ 23 $dbCfg = ROOT . '/includes/db_config.php'; 24 if (file_exists($dbCfg)) { 25 require_once $dbCfg; 26 } else { 27 // Default: SQLite (installer not yet run, or config missing) 28 if (!defined('DB_DRIVER')) define('DB_DRIVER', 'sqlite'); 29 } 30 31 /* ── Security headers (applied on every page load) ──────────── */ 32 if (!headers_sent()) { 33 header('X-Content-Type-Options: nosniff'); 34 header('X-Frame-Options: SAMEORIGIN'); 35 header('X-XSS-Protection: 1; mode=block'); 36 header('Referrer-Policy: strict-origin-when-cross-origin'); 37 header('Permissions-Policy: camera=(), microphone=(), geolocation=()'); 38 39 // Content-Security-Policy — blocks injected scripts even if XSS were possible. 40 // script-src 'self' allows our own JS; cdnjs for Prism.js; 'unsafe-inline' for 41 // onclick= attributes used throughout the forum (toolbar buttons, embeds etc.). 42 // frame-src allows trusted embed domains only. 43 $csp = implode('; ', [ 44 "default-src 'self'", 45 "script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://platform.twitter.com", 46 "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com", 47 "font-src 'self' https://fonts.gstatic.com", 48 "img-src 'self' data: https:", 49 "media-src 'self' https:", 50 "frame-src 'self' https://www.youtube.com https://www.youtube-nocookie.com https://player.vimeo.com https://player.twitch.tv https://clips.twitch.tv https://open.spotify.com https://w.soundcloud.com https://soundcloud.com https://bandcamp.com https://codepen.io https://jsfiddle.net https://www.loom.com https://rumble.com https://embed.ted.com https://www.dailymotion.com https://streamable.com https://platform.twitter.com https://syndication.twitter.com", 51 "connect-src 'self'", 52 "object-src 'none'", 53 "base-uri 'self'", 54 "form-action 'self'", 55 ]); 56 header('Content-Security-Policy: ' . $csp); 57 // Only set HSTS if running HTTPS 58 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') { 59 header('Strict-Transport-Security: max-age=31536000; includeSubDomains'); 60 } 61 } 62 63 /* ── Error handling ──────────────────────────────────────────── */ 64 // Production: hide errors from users, log them instead 65 if (!(defined('NEXUS_DEBUG') && NEXUS_DEBUG)) { 66 ini_set('display_errors', '0'); 67 ini_set('log_errors', '1'); 68 error_reporting(E_ALL); 69 }