From bbbe90458a3da6fcdfcb22437fd95d6ec9831f91 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Fri, 29 May 2026 09:28:30 +0200 Subject: [PATCH] Initial commit. --- config/app.php | 6 +++ config/database.php | 0 config/routes.php | 16 +++++++ index.php | 5 ++ server.sh | 10 ++++ src/bootstrap.php | 4 ++ src/database.php | 0 src/helpers.php | 10 ++++ src/router.php | 98 +++++++++++++++++++++++++++++++++++++++ src/views/pages/404.php | 0 src/views/pages/about.php | 1 + src/views/pages/home.php | 1 + 12 files changed, 151 insertions(+) create mode 100644 config/app.php create mode 100644 config/database.php create mode 100644 config/routes.php create mode 100644 index.php create mode 100755 server.sh create mode 100644 src/bootstrap.php create mode 100644 src/database.php create mode 100644 src/helpers.php create mode 100644 src/router.php create mode 100644 src/views/pages/404.php create mode 100644 src/views/pages/about.php create mode 100644 src/views/pages/home.php diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..cb37be4 --- /dev/null +++ b/config/app.php @@ -0,0 +1,6 @@ + 'My Site', + 'debug' => false, +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..e69de29 diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 0000000..8dde48c --- /dev/null +++ b/config/routes.php @@ -0,0 +1,16 @@ + [ + '/' => 'home.php', + '/about' => 'about.php', + ], + /* Some Examples + 'POST' => [ + '/contact' => 'contact.php', + ], + 'DELETE' => [ + '/api/todo' => 'delete_todo.php', + ], + */ +]; diff --git a/index.php b/index.php new file mode 100644 index 0000000..9441963 --- /dev/null +++ b/index.php @@ -0,0 +1,5 @@ + / +// /about => /about +// /about/ => /about +// /about?id=1 => /about +// ----------------------------------------------------------------------------- +$uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH); + +if (!is_string($uri)) { + http_response_code(400); + exit; +} + +$uri = rtrim($uri, '/'); +$uri = $uri ?: '/'; + +// ----------------------------------------------------------------------------- +// Request method +// ----------------------------------------------------------------------------- +$method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET'); + +// ----------------------------------------------------------------------------- +// Load route configuration +// config/routes.php: +// return [ +// 'GET' => [ +// '/' => 'home.php', +// '/about' => 'about.php', +// ], +// ]; +// ----------------------------------------------------------------------------- +$routes = require ROOT . '/config/routes.php'; + +if (!is_array($routes)) { + error_log('Router: routes.php must return an array'); + http_response_code(500); + exit; +} + +// ----------------------------------------------------------------------------- +// Find matching route +// ----------------------------------------------------------------------------- +$route = $routes[$method][$uri] ?? null; + +// ----------------------------------------------------------------------------- +// Base directory containing all page files +// Every routed file MUST live inside this directory. +// ----------------------------------------------------------------------------- +$base = realpath(ROOT . '/src/views/pages'); + +if ($base === false) { + error_log('Router: pages directory not found'); + http_response_code(500); + exit; +} + +// ----------------------------------------------------------------------------- +// Route not found +// ----------------------------------------------------------------------------- +if ($route === null) { + http_response_code(404); + $route = '404.php'; +} + +// ----------------------------------------------------------------------------- +// Resolve requested file +// realpath() converts: +// home.php +// ../home.php +// ../../etc/passwd +// into an absolute canonical path. +// ----------------------------------------------------------------------------- +$real = realpath($base . '/' . $route); + +// ----------------------------------------------------------------------------- +// Path traversal protection +// Only allow files that resolve inside: +// src/views/pages/ +// +// This blocks attempts such as: +// ../../etc/passwd +// ../../../secret.php +// even if they somehow end up in the route table. +// ----------------------------------------------------------------------------- + +if ($real === false || !str_starts_with($real, $base . DIRECTORY_SEPARATOR)) { + error_log("Router: invalid route target [$route]"); + http_response_code(403); + exit; +} + +// ----------------------------------------------------------------------------- +// Dispatch request +// ----------------------------------------------------------------------------- +require $real; diff --git a/src/views/pages/404.php b/src/views/pages/404.php new file mode 100644 index 0000000..e69de29 diff --git a/src/views/pages/about.php b/src/views/pages/about.php new file mode 100644 index 0000000..86c62fe --- /dev/null +++ b/src/views/pages/about.php @@ -0,0 +1 @@ +

about

diff --git a/src/views/pages/home.php b/src/views/pages/home.php new file mode 100644 index 0000000..0a88878 --- /dev/null +++ b/src/views/pages/home.php @@ -0,0 +1 @@ +

home