This commit is contained in:
Turtle committed 2026-01-11 13:32:08 +01:00
1 parent f5704e87df
commit 96594641dc
11 files changed
+143 -109

No files matched your search

+112 -88
View File
@@ -1,17 +1,48 @@
<?php
class TurtlePathInfo {
public string $content;
public static function create_default(string $filesDir) :TurtlePathInfo {
$res = new TurtlePathInfo();
$res->filesDir = $filesDir;
$res->contentDir = "{$filesDir}content/";
$res->homeFile = "{$res->contentDir}HOME";
$res->notFoundFile = "{$res->contentDir}NOT-FOUND";
return $res;
}
public string $filesDir;
public string $contentDir;
public string $homeFile;
public string $notFoundFile;
}
class TurtleURLObject {
public static function parse_url_mark(array $urlParts) :object {
$res = (object) [];
if (count($urlParts) == 1) return $res;
foreach (explode('&', $urlParts[1]) as $part) {
$arr = explode('=', $part, 2);
$cnt = count($arr);
switch ($cnt) {
case 1:
$res->{$arr[0]} = 1;
break;
case 2:
$res->{$arr[0]} = $arr[1];
break;
}
}
return $res;
}
public static function create_from_server(bool $lowerCase = true, bool $alternativeURL = true) :TurtleURLObject {
$urlParts = explode('?', trim($_SERVER['REQUEST_URI'], '/'));
$urlMark = _parseUrlMark($urlParts);
$urlMark = TurtleURLObject::parse_url_mark($urlParts);
$request = str_replace("..", ".", $urlParts[0]);
if ($lowerCase) $request = strtolower($request);
if ($alternativeURL) $request = str_replace("-", "/", $request);
$res = new TurtleURLObject($request, $urlMark);
$res->method = $_SERVER['REQUEST_METHOD'];
$res->method_type = explode(',', $_SERVER['HTTP_ACCEPT'] ?? '');
@@ -32,116 +63,109 @@ class TurtleURLObject {
$bodyContent = file_get_contents("php://input");
return $bodyContent;
}
public function get_html_file(string $file_path): string {
if (!file_exists($file_path)) {
return "Not found!";
} else {
return file_get_contents($file_path);
}
public function get_body_json() :mixed {
$res = json_decode($this->get_body_text());
return json_last_error() === JSON_ERROR_NONE ? $res: null;
}
public function send_text(string $text) :void {
header('Content-Type: text/plain');
$this->set_ext_header('txt');
echo $text;
}
public function send_json(mixed $data) :void {
header('Content-Type: application/json');
$this->set_ext_header('json');
echo json_encode($data);
}
public function send_image(string $path) :void {
//send custom content
public function send_file(string $path) :void {
$fileExt = pathinfo($path, PATHINFO_EXTENSION);
if ($fileExt === "ico") {
header("Cache-Control: no-cache, must-revalidate, max-age=0");
header("Content-Type: image/x-icon");
$fileExt = strtolower(ltrim($fileExt, '.'));
$this->set_ext_header($fileExt);
if ($fileExt == "html") {
if (!is_file($path)) echo 'File not found!';
else echo $this->get_html_file($path);
} else {
header("Content-Type: image/$fileExt");
if (!is_file($path)) echo '';
else readfile($path);
}
readfile($path);
}
public function send_custom_file(string $path) :bool {
$fileExt = pathinfo($path, PATHINFO_EXTENSION);
if (isFileExtImage($fileExt)) {
$this->send_image($path);
} else if ($fileExt == "json") {
$content = file_get_contents($path);
if ($content == false) return false;
header('Content-Type: application/json');
echo $content;
} else if ($fileExt == "txt") {
$content = file_get_contents($path);
if ($content == false) return false;
$this->send_text($content);
} else if ($fileExt == "js") {
header('Content-Type: text/javascript; charset=utf-8');
echo file_get_contents($path);
return true;
} else if ($fileExt == "css") {
header("Content-Type: text/css");
echo file_get_contents($path);
} else if ($fileExt == "html") {
echo $this->get_html_file($path);
} else {
public function allow_ext_referer(string $ext) :bool {
$types = $this->method_type;
if (isFileExtImage($ext)) {
foreach ($types as $i) if (str_starts_with($i, 'image/')) return true;
return false;
} else if ($ext == 'js') {
if (sizeof($types) == 1 && $types[0] == "*/*") return true;
return false;
} else if ($ext == 'css') {
foreach ($types as $i) if ($i == 'text/css') return true;
return false;
} else {
return true;
}
}
public function set_ext_header(string $ext) :void {
if (isFileExtImage($ext)) {
if ($ext === "ico") {
header("Cache-Control: no-cache, must-revalidate, max-age=0");
header("Content-Type: image/x-icon");
} else {
header("Content-Type: image/$ext");
}
return;
}
switch ($ext) {
case 'html':
header('Content-Type: text/html'); break;
case 'json':
header('Content-Type: application/json'); break;
case 'css':
header("Content-Type: text/css"); break;
case 'js':
header('Content-Type: application/javascript; charset=utf-8'); break;
case 'md': case 'txt':
header('Content-Type: text/plain'); break;
case 'pdf':
header("Content-Type: application/$ext"); break;
default:
header('Content-Type: text/html'); break;
}
return true;
}
public function is_image_request() :bool {
foreach ($this->method_type as $type) {
if (!str_starts_with($type, "image/")) return false;
}
return true;
}
//execution
private function get_html_file(string $file_path): string {
return file_get_contents($file_path);
}
private function _get_path(string|null $path, string $filesDir = "") :string {
if ($path == null || is_file($path)) return $path;
if (is_file("$path.html")) return "$path.html";
return $path;
}
public function handle_request(TurtlePathInfo $path_info): void {
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$filePath = $path_info->content . $this->url;
if (strlen($this->url) == 0) {
$filePath = "{$path_info->content}START.html";
}
//-------------Image-Pages-------------------//
else if (
!empty($referer) && $this->is_image_request()
) {
if (file_exists($filePath)) {
$this->send_image($filePath);
return;
} else {
$filePath = NULL;
}
}
//-------------HTML-Pages-------------------//
$filePath = $path_info->contentDir . $this->url;
if (strlen($this->url) == 0) $filePath = $path_info->homeFile;
if ($filePath === NULL || !file_exists($filePath)) {
$filePath = "{$path_info->content}NOT-FOUND.html";
http_response_code(404);
$filePath = $this->_get_path($filePath, $path_info->filesDir);
if (!($this->allow_ext_referer(pathinfo($filePath, PATHINFO_EXTENSION)))) {
$filePath = null;
}
$this->send_custom_file($filePath);
if ($filePath == null || !is_file($filePath)) {
http_response_code(404);
$filePath = $this->_get_path($path_info->notFoundFile, $path_info->filesDir);
}
$this->send_file($filePath);
}
}
function _parseUrlMark($urlParts) :object {
$res = (object) [];
if (count($urlParts) == 1) return $res;
foreach (explode('&', $urlParts[1]) as $part) {
$arr = explode('=', $part, 2);
$cnt = count($arr);
switch ($cnt) {
case 1:
$res->{$arr[0]} = 1;
break;
case 2:
$res->{$arr[0]} = $arr[1];
break;
}
}
return $res;
}
function isFileExtImage(string $fileExt) :bool {
switch ($fileExt) {
case 'png':