- Fix detectNewestPage() to search subdirectories recursively and handle language prefixes - Fix getFileInfo() to preserve frontmatter created date or ctime instead of overwriting with mtime - Automatically store created date in frontmatter when creating/editing files - Add RequestLogger::getClientIp() with proxy and Cloudflare header support - Replace domain column in request log with visitor/bot type badges (Human, AI, Search, Scraper) - Update 'Activiteitenlog' to 'Activiteiten log' in UI and guide
123 lines
4.2 KiB
PHP
123 lines
4.2 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/../cms/core/index.php';
|
|
|
|
$config = include __DIR__ . '/../cms/core/config.php';
|
|
|
|
// Security headers
|
|
header('X-Content-Type-Options: nosniff');
|
|
header('X-Frame-Options: SAMEORIGIN');
|
|
header('X-XSS-Protection: 1; mode=block');
|
|
header('Referrer-Policy: strict-origin-when-cross-origin');
|
|
header('Content-Security-Policy: default-src \'self\'; script-src \'self\' \'unsafe-inline\'; style-src \'self\' \'unsafe-inline\'; img-src \'self\' data:; font-src \'self\';');
|
|
header_remove('X-Powered-By');
|
|
|
|
// Serve media files from any content/ subdirectory via /-media/
|
|
// Serve files from content/-assets/ via /-assets/ (backward compatible)
|
|
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
|
|
$parsedUrl = parse_url($requestUri);
|
|
$path = $parsedUrl['path'] ?? '';
|
|
|
|
$allowedExt = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'pdf', 'zip', 'mp4', 'webm', 'ogg', 'mp3', 'wav'];
|
|
$mimeTypes = [
|
|
'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png',
|
|
'gif' => 'image/gif', 'webp' => 'image/webp', 'svg' => 'image/svg+xml',
|
|
'pdf' => 'application/pdf', 'zip' => 'application/zip',
|
|
'mp4' => 'video/mp4', 'webm' => 'video/webm', 'ogg' => 'video/ogg',
|
|
'mp3' => 'audio/mpeg', 'wav' => 'audio/wav',
|
|
'css' => 'text/css', 'js' => 'application/javascript',
|
|
];
|
|
|
|
if (strpos($path, '/-media/') === 0) {
|
|
$relative = ltrim(substr($path, 7), '/');
|
|
$root = realpath(__DIR__ . '/..');
|
|
$filePath = $root . '/content/' . $relative;
|
|
if (strpos($filePath, $root . '/content') === 0) {
|
|
$ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
|
|
if (in_array($ext, $allowedExt) && file_exists($filePath) && !is_dir($filePath)) {
|
|
if (isset($mimeTypes[$ext])) {
|
|
header('Content-Type: ' . $mimeTypes[$ext]);
|
|
}
|
|
readfile($filePath);
|
|
exit;
|
|
}
|
|
}
|
|
http_response_code(404);
|
|
echo '<h1>404 - Not Found</h1>';
|
|
exit;
|
|
}
|
|
|
|
if (strpos($path, '/-assets/') === 0) {
|
|
$relative = ltrim(substr($path, 8), '/');
|
|
$root = realpath(__DIR__ . '/..');
|
|
|
|
$servePath = null;
|
|
$candidates = [
|
|
$root . '/content/-assets/' . $relative,
|
|
$root . '/content/' . $relative,
|
|
];
|
|
|
|
foreach ($candidates as $candidate) {
|
|
if (strpos($candidate, $root . '/content') !== 0) continue;
|
|
if (file_exists($candidate) && !is_dir($candidate)) {
|
|
$ext = strtolower(pathinfo($candidate, PATHINFO_EXTENSION));
|
|
if (in_array($ext, $allowedExt)) {
|
|
$servePath = $candidate;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($servePath !== null) {
|
|
$ext = strtolower(pathinfo($servePath, PATHINFO_EXTENSION));
|
|
if (isset($mimeTypes[$ext])) {
|
|
header('Content-Type: ' . $mimeTypes[$ext]);
|
|
}
|
|
readfile($servePath);
|
|
exit;
|
|
}
|
|
|
|
http_response_code(404);
|
|
echo '<h1>404 - Not Found</h1>';
|
|
exit;
|
|
}
|
|
|
|
// Block direct access to content files
|
|
if (strpos($path, '/content/') === 0) {
|
|
http_response_code(403);
|
|
echo '<h1>403 - Forbidden</h1><p>Access denied.</p>';
|
|
exit;
|
|
}
|
|
|
|
// Load RequestLogger for bot detection and request logging
|
|
require_once __DIR__ . '/../cms/core/class/RequestLogger.php';
|
|
|
|
// Bot detection — block known bots/AI scrapers early
|
|
if (RequestLogger::detectBot() !== null) {
|
|
http_response_code(403);
|
|
echo '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>403 Forbidden</title><meta name="robots" content="noindex,nofollow"></head><body><h1>403 Forbidden</h1><p>Access denied.</p></body></html>';
|
|
exit;
|
|
}
|
|
|
|
$cms = new CodePressCMS($config);
|
|
|
|
// Log page view (not for media/assets)
|
|
if (!str_starts_with($path, '/-media/') && !str_starts_with($path, '/-assets/')) {
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
@session_start();
|
|
}
|
|
$loggedInUser = $_SESSION['admin_user'] ?? 'Gast';
|
|
|
|
$requestLogFile = dirname(__DIR__) . '/admin/storage/logs/requests.log';
|
|
$logger = new RequestLogger($requestLogFile);
|
|
$logger->log(
|
|
$_GET['page'] ?? $config['default_page'] ?? 'index',
|
|
RequestLogger::getClientIp(),
|
|
$_SERVER['HTTP_USER_AGENT'] ?? '',
|
|
$_SERVER['HTTP_REFERER'] ?? '',
|
|
$loggedInUser,
|
|
$_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''
|
|
);
|
|
}
|
|
|
|
$cms->render(); |