From 28490ce8b3d9bc8ea5b49cc3471f523baca6bf36 Mon Sep 17 00:00:00 2001 From: Turtle <104490184+CodingTurtle2@users.noreply.github.com> Date: Sun, 11 Jan 2026 10:26:39 +0100 Subject: [PATCH] g6 --- .gitignore | 2 + START.html | 26 --- data/def_data.json | 217 ++++++++++++++++++ files/START.html | 8 + {audio => files/audio}/levelup1.mp3 | Bin {audio => files/audio}/levelup2.mp3 | Bin auth.js => files/auth.js | 0 {help => files/help}/Example.html | 6 +- files/help/data_xample.js | 3 + {help => files/help}/documentation.md | 0 {imgs => files/imgs}/epic_border.png | Bin {imgs => files/imgs}/gold_border.png | Bin {imgs => files/imgs}/humoid_profil.png | Bin {imgs => files/imgs}/rosa_profil.png | Bin {imgs => files/imgs}/simple_border.png | Bin {imgs => files/imgs}/standart_profil.png | Bin {imgs => files/imgs}/xp-bar-bg.png | Bin {imgs => files/imgs}/xp-bar-fg.png | Bin {lib => files/lib}/basic.css | 0 {lib => files/lib}/basic.js | 4 +- login.html => files/login.html | 0 {other => files/other}/skills.js | 0 {other => files/other}/skilltree.js | 0 {prof => files/prof}/auswertung.html | 0 {prof => files/prof}/kursAnzeige.html | 0 {prof => files/prof}/uebersicht.html | 0 signup.html => files/signup.html | 0 {student => files/student}/kursAnzeige.html | 0 {student => files/student}/uebersicht.html | 0 .../student}/uebersicht_overlay.js | 0 {student => files/student}/umfrage.html | 0 help/data_xample.js | 148 ------------ index.php | 16 ++ utils/couch.php | 139 +++++++++++ utils/features.php | 30 +++ utils/url_handler.php | 167 ++++++++++++++ 36 files changed, 587 insertions(+), 179 deletions(-) create mode 100644 .gitignore delete mode 100644 START.html create mode 100644 data/def_data.json create mode 100644 files/START.html rename {audio => files/audio}/levelup1.mp3 (100%) rename {audio => files/audio}/levelup2.mp3 (100%) rename auth.js => files/auth.js (100%) rename {help => files/help}/Example.html (93%) create mode 100644 files/help/data_xample.js rename {help => files/help}/documentation.md (100%) rename {imgs => files/imgs}/epic_border.png (100%) rename {imgs => files/imgs}/gold_border.png (100%) rename {imgs => files/imgs}/humoid_profil.png (100%) rename {imgs => files/imgs}/rosa_profil.png (100%) rename {imgs => files/imgs}/simple_border.png (100%) rename {imgs => files/imgs}/standart_profil.png (100%) rename {imgs => files/imgs}/xp-bar-bg.png (100%) rename {imgs => files/imgs}/xp-bar-fg.png (100%) rename {lib => files/lib}/basic.css (100%) rename {lib => files/lib}/basic.js (99%) rename login.html => files/login.html (100%) rename {other => files/other}/skills.js (100%) rename {other => files/other}/skilltree.js (100%) rename {prof => files/prof}/auswertung.html (100%) rename {prof => files/prof}/kursAnzeige.html (100%) rename {prof => files/prof}/uebersicht.html (100%) rename signup.html => files/signup.html (100%) rename {student => files/student}/kursAnzeige.html (100%) rename {student => files/student}/uebersicht.html (100%) rename {student => files/student}/uebersicht_overlay.js (100%) rename {student => files/student}/umfrage.html (100%) delete mode 100644 help/data_xample.js create mode 100644 index.php create mode 100644 utils/couch.php create mode 100644 utils/features.php create mode 100644 utils/url_handler.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a17e23f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +data/couchdb.json diff --git a/START.html b/START.html deleted file mode 100644 index 7bb2ce0..0000000 --- a/START.html +++ /dev/null @@ -1,26 +0,0 @@ - - -
- - - - - - - - - - - - \ No newline at end of file diff --git a/data/def_data.json b/data/def_data.json new file mode 100644 index 0000000..f836734 --- /dev/null +++ b/data/def_data.json @@ -0,0 +1,217 @@ +{ + "sassy": { + "users": { + "turtle": { + "password": "1234", + "level": 3, + "xp": 2, + "avatar": null, + "abilities": [], + "enabled_abilities": [], + "role": "student", + "courses": ["weiche_ware", "bucket"] + }, + "dumble-door": { + "password": "bla", + "level": 10, + "xp": 0, + "avatar": "https://static.turtle-coding-gbr.de/gmci/profile-pic.png", + "abilities": [], + "enabled_abilities": [], + "role": "professor", + "courses": ["weiche_ware", "algebra", "geometrie"] + }, + "narrator": { + "password": "stanley", + "level": 10, + "xp": 0, + "avatar": "https://static.turtle-coding-gbr.de/gmci/st", + "abilities": [ + "dark_mode", + "accent_color", + "pink_mode", + "profile_pic", + "simple_border", + "gold_border", + "epic_border", + "title_of_honor" + ], + "enabled_abilities": [], + "role": "professor", + "courses": ["bucket", "statistik"] + } + }, + "course:bucket": { + "title": "Bucket", + "description": "The end is never the end is never the end is never", + "owner": "narrator", + "questions": [ + { + "title": "What is comedic timing?", + "type": "text" + }, + { + "title": "How does it work?", + "type": "text" + }, + { + "title": "How long should it last?", + "type": "scala" + }, + { + "title": "How can it be used to effectively silence your political enemies?", + "type": "emoji" + } + ], + "result": [ + ["YES", "YES", 5, 2], + ["YES", "YES", 1, 3] + ], + "result_history": [ + { + "date": "2025-12-27", + "questions": [ + { "title": "Wie war die Vorlesung?", "type": "text" }, + { "title": "Wie war der Professor?", "type": "scala" } + ], + "result": [ + ["Gut, weil ...", 5], + ["Schlecht, weil ...", 1] + ] + } + ], + "start_date": "2025-12-23", + "expire_date": "2026-02-20" + }, + "course:weiche_ware": { + "title": "Weiche Ware", + "description": "blabering", + "owner": "dumble-door", + "questions": [ + { + "title": "Wie fanden Sie die Vorlesung?", + "type": "text" + }, + { + "title": "Finden Sie, dass man Zauberei an lebendigen Schülern praktizieren sollte?", + "type": "scala" + } + ], + "result": [ + ["Gut, weil ...", 5], + ["Schlecht, weil ...", 1], + ["Lorem ipsum dolor sit amet", 2], + ["consetetur sadipscing elitr, sed diam ", 3], + [" nonumy eirmod tempor invidunt ut labore ", 4], + ["et dolore magna aliquyam erat, sed diam", 5], + [" voluptua. At vero eos et accusam et justo duo", 1], + ["the end", 5] + ], + "result_history": [ + { + "date": "2025-12-27", + "questions": [ + { "title": "1", "type": "text" }, + { "title": "2", "type": "scala" } + ], + "result": [ + ["Gut, weil ...", 5], + ["Schlecht, weil ...", 1], + ["Lorem ipsum dolor sit amet", 2], + ["consetetur sadipscing elitr, sed diam ", 3], + [" nonumy eirmod tempor invidunt ut labore ", 4], + ["et dolore magna aliquyam erat, sed diam", 5], + [" voluptua. At vero eos et accusam et justo duo", 1], + ["the end", 5] + ] + } + ], + "start_date": "2025-12-23", + "expire_date": "2026-02-20" + }, + "course:algebra": { + "title": "Algebra", + "description": "Grundlagen der algebraischen Konzepte.", + "owner": "math-wizard", + "questions": [ + { "title": "Wie gut verstehen Sie die Grundlagen der Algebra?", "type": "text" }, + { "title": "Bewerten Sie die Schwierigkeit algebraischer Aufgaben.", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ], + "result_history": [ + { + "date": "2025-12-28", + "questions": [ + { "title": "1", "type": "text" }, + { "title": "2", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ] + } + ], + "start_date": "2025-12-26", + "expire_date": "2025-02-25" + }, + "course:geometrie": { + "title": "Geometrie", + "description": "Erforschung geometrischer Figuren und Konzepte.", + "owner": "geo-genius", + "questions": [ + { "title": "Wie sicher sind Sie im Umgang mit geometrischen Formen?", "type": "text" }, + { "title": "Bewerten Sie die Komplexität geometrischer Aufgaben.", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ], + "result_history": [ + { + "date": "2025-12-29", + "questions": [ + { "title": "1", "type": "text" }, + { "title": "2", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ] + } + ], + "start_date": "2025-12-24", + "expire_date": "2025-03-15" + }, + "course:statistik": { + "title": "Statistik", + "description": "Grundlagen der statistischen Analyse und Interpretation.", + "owner": "data-analyst", + "questions": [ + { "title": "Wie gut verstehen Sie statistische Methoden?", "type": "text" }, + { "title": "Bewerten Sie die Schwierigkeit statistischer Analysen.", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ], + "result_history": [ + { + "date": "2025-12-30", + "questions": [ + { "title": "1", "type": "text" }, + { "title": "2", "type": "scala" } + ], + "result": [ + ["Einfach, weil ...", 5], + ["Schwierig, weil ...", 1] + ] + } + ], + "start_date": "2025-12-25", + "expire_date": "2025-04-10" + } + } +} diff --git a/files/START.html b/files/START.html new file mode 100644 index 0000000..c78a536 --- /dev/null +++ b/files/START.html @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/audio/levelup1.mp3 b/files/audio/levelup1.mp3 similarity index 100% rename from audio/levelup1.mp3 rename to files/audio/levelup1.mp3 diff --git a/audio/levelup2.mp3 b/files/audio/levelup2.mp3 similarity index 100% rename from audio/levelup2.mp3 rename to files/audio/levelup2.mp3 diff --git a/auth.js b/files/auth.js similarity index 100% rename from auth.js rename to files/auth.js diff --git a/help/Example.html b/files/help/Example.html similarity index 93% rename from help/Example.html rename to files/help/Example.html index 62f0709..c545c64 100644 --- a/help/Example.html +++ b/files/help/Example.html @@ -50,12 +50,12 @@ async function main() { const data = await couchDB.get("xample"); console.log(JSON.stringify(data)); //Gibt { "my_data": 1, "more_data": "bla" } wieder + + console.log(JSON.stringify(await couchDB.get("*"))); + //Gibt ["users","course:bucket","course:weiche_ware","course:algebra","course:geometrie","course:statistik","xample"] wieder } main(); -createTemp().then((v) => { - setUserData(couchDB); -}); diff --git a/files/help/data_xample.js b/files/help/data_xample.js new file mode 100644 index 0000000..2708bba --- /dev/null +++ b/files/help/data_xample.js @@ -0,0 +1,3 @@ +async function createTemp() { + console.warn("createTemp is deprecated"); +} \ No newline at end of file diff --git a/help/documentation.md b/files/help/documentation.md similarity index 100% rename from help/documentation.md rename to files/help/documentation.md diff --git a/imgs/epic_border.png b/files/imgs/epic_border.png similarity index 100% rename from imgs/epic_border.png rename to files/imgs/epic_border.png diff --git a/imgs/gold_border.png b/files/imgs/gold_border.png similarity index 100% rename from imgs/gold_border.png rename to files/imgs/gold_border.png diff --git a/imgs/humoid_profil.png b/files/imgs/humoid_profil.png similarity index 100% rename from imgs/humoid_profil.png rename to files/imgs/humoid_profil.png diff --git a/imgs/rosa_profil.png b/files/imgs/rosa_profil.png similarity index 100% rename from imgs/rosa_profil.png rename to files/imgs/rosa_profil.png diff --git a/imgs/simple_border.png b/files/imgs/simple_border.png similarity index 100% rename from imgs/simple_border.png rename to files/imgs/simple_border.png diff --git a/imgs/standart_profil.png b/files/imgs/standart_profil.png similarity index 100% rename from imgs/standart_profil.png rename to files/imgs/standart_profil.png diff --git a/imgs/xp-bar-bg.png b/files/imgs/xp-bar-bg.png similarity index 100% rename from imgs/xp-bar-bg.png rename to files/imgs/xp-bar-bg.png diff --git a/imgs/xp-bar-fg.png b/files/imgs/xp-bar-fg.png similarity index 100% rename from imgs/xp-bar-fg.png rename to files/imgs/xp-bar-fg.png diff --git a/lib/basic.css b/files/lib/basic.css similarity index 100% rename from lib/basic.css rename to files/lib/basic.css diff --git a/lib/basic.js b/files/lib/basic.js similarity index 99% rename from lib/basic.js rename to files/lib/basic.js index 49d1f49..f75096f 100644 --- a/lib/basic.js +++ b/files/lib/basic.js @@ -105,7 +105,7 @@ window.addEventListener("load", (event) => { //http://127.0.0.1:5984/_utils/#_config/couchdb@127.0.0.1 class CouchDB { - static _default_url = "http://127.0.0.1:5984/"; + static _default_url = "/couchdb/"; constructor() { this._does_auth_exists_err(); @@ -162,7 +162,7 @@ class CouchDB { this.request.onreadystatechange = () => { if (request.readyState != 4) return; - + try { if (request.status == 200 || request.status == 201) { var response = JSON.parse(request.responseText); diff --git a/login.html b/files/login.html similarity index 100% rename from login.html rename to files/login.html diff --git a/other/skills.js b/files/other/skills.js similarity index 100% rename from other/skills.js rename to files/other/skills.js diff --git a/other/skilltree.js b/files/other/skilltree.js similarity index 100% rename from other/skilltree.js rename to files/other/skilltree.js diff --git a/prof/auswertung.html b/files/prof/auswertung.html similarity index 100% rename from prof/auswertung.html rename to files/prof/auswertung.html diff --git a/prof/kursAnzeige.html b/files/prof/kursAnzeige.html similarity index 100% rename from prof/kursAnzeige.html rename to files/prof/kursAnzeige.html diff --git a/prof/uebersicht.html b/files/prof/uebersicht.html similarity index 100% rename from prof/uebersicht.html rename to files/prof/uebersicht.html diff --git a/signup.html b/files/signup.html similarity index 100% rename from signup.html rename to files/signup.html diff --git a/student/kursAnzeige.html b/files/student/kursAnzeige.html similarity index 100% rename from student/kursAnzeige.html rename to files/student/kursAnzeige.html diff --git a/student/uebersicht.html b/files/student/uebersicht.html similarity index 100% rename from student/uebersicht.html rename to files/student/uebersicht.html diff --git a/student/uebersicht_overlay.js b/files/student/uebersicht_overlay.js similarity index 100% rename from student/uebersicht_overlay.js rename to files/student/uebersicht_overlay.js diff --git a/student/umfrage.html b/files/student/umfrage.html similarity index 100% rename from student/umfrage.html rename to files/student/umfrage.html diff --git a/help/data_xample.js b/help/data_xample.js deleted file mode 100644 index 41f2827..0000000 --- a/help/data_xample.js +++ /dev/null @@ -1,148 +0,0 @@ -async function createTemp() { - const couchDB = new CouchDB(); - await couchDB.set("users", { - "turtle": { - "password": "1234", - "level": 3, - "xp": 2, - "avatar": null, - "abilities": [], - "enabled_abilities": [], - "role": "student", - "courses": [ - "weiche_ware", - "bucket" - ] - }, - "dumble-door": { - "password": "bla", - "level": 10, - "xp": 0, - "avatar": "https://static.turtle-coding-gbr.de/gmci/profile-pic.png", - "abilities": [ - ], - "enabled_abilities": [ - ], - "role": "professor", - "courses": [ - "weiche_ware", "algebra", "geometrie" - ] - }, - "narrator": { - "password": "stanley", - "level": 10, - "xp": 0, - "avatar": "https://static.turtle-coding-gbr.de/gmci/st", - "abilities": [ - "dark_mode", - "accent_color", - "pink_mode", - "profile_pic", - "simple_border", - "gold_border", - "epic_border", - "title_of_honor" - ], - "enabled_abilities": [ - ], - "role": "professor", - "courses": [ - "bucket", "statistik" - ] - } - }); - await couchDB.set("course:bucket", { - "title": "Bucket", - "description": "The end is never the end is never the end is never", - "owner": "narrator", - "questions": [ - { - "title": "What is comedic timing?", - "type": "text" - }, - { - "title": "How does it work?", - "type": "text" - }, - { - "title": "How long should it last?", - "type": "scala" - }, - { - "title": "How can it be used to effectively silence your political enemies?", - "type": "emoji" - } - ], - "result": [ - ["YES", "YES", 5, 2], - ["YES", "YES", 1, 3] - ], - "result_history": [ - { - "date": "2025-12-27", - "questions": [ - { "title": "Wie war die Vorlesung?", "type": "text" }, - { "title": "Wie war der Professor?", "type": "scala" } - ], - "result": [ - ["Gut, weil ...", 5], - ["Schlecht, weil ...", 1] - ] - } - ], - "start_date": "2025-12-23", - "expire_date": "2026-02-20" - }); - await couchDB.set("course:weiche_ware", { - "title": "Weiche Ware", - "description": "blabering", - "owner": "dumble-door", - "questions": [ - { - "title": "Wie fanden Sie die Vorlesung?", - "type": "text" - }, - { - "title": "Finden Sie, dass man Zauberei an lebendigen Schülern praktizieren sollte?", - "type": "scala" - } - ], - "result": [ - ["Gut, weil ...", 5], - ["Schlecht, weil ...", 1], - ["Lorem ipsum dolor sit amet", 2], - ["consetetur sadipscing elitr, sed diam ", 3], - [" nonumy eirmod tempor invidunt ut labore ", 4], - ["et dolore magna aliquyam erat, sed diam", 5], - [" voluptua. At vero eos et accusam et justo duo", 1], - ["the end", 5] - ], - "result_history": [ - { - "date": "2025-12-27", - "questions": [ - { "title": "1", "type": "text" }, - { "title": "2", "type": "scala" } - ], - "result": [ - ["Gut, weil ...", 5], - ["Schlecht, weil ...", 1], - ["Lorem ipsum dolor sit amet", 2], - ["consetetur sadipscing elitr, sed diam ", 3], - [" nonumy eirmod tempor invidunt ut labore ", 4], - ["et dolore magna aliquyam erat, sed diam", 5], - [" voluptua. At vero eos et accusam et justo duo", 1], - ["the end", 5] - ] - } - ], - "start_date": "2025-12-23", - "expire_date": "2026-02-20" - }); - - - await couchDB.set("course:algebra", { "title": "Algebra", "description": "Grundlagen der algebraischen Konzepte.", "owner": "math-wizard", "questions": [ { "title": "Wie gut verstehen Sie die Grundlagen der Algebra?", "type": "text" }, { "title": "Bewerten Sie die Schwierigkeit algebraischer Aufgaben.", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ], "result_history": [ { "date": "2025-12-28", "questions": [ { "title": "1", "type": "text" }, { "title": "2", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ] } ], "start_date": "2025-12-26", "expire_date": "2025-02-25" }); - await couchDB.set("course:geometrie", { "title": "Geometrie", "description": "Erforschung geometrischer Figuren und Konzepte.", "owner": "geo-genius", "questions": [ { "title": "Wie sicher sind Sie im Umgang mit geometrischen Formen?", "type": "text" }, { "title": "Bewerten Sie die Komplexität geometrischer Aufgaben.", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ], "result_history": [ { "date": "2025-12-29", "questions": [ { "title": "1", "type": "text" }, { "title": "2", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ] } ], "start_date": "2025-12-24", "expire_date": "2025-03-15" }); - await couchDB.set("course:statistik", { "title": "Statistik", "description": "Grundlagen der statistischen Analyse und Interpretation.", "owner": "data-analyst", "questions": [ { "title": "Wie gut verstehen Sie statistische Methoden?", "type": "text" }, { "title": "Bewerten Sie die Schwierigkeit statistischer Analysen.", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ], "result_history": [ { "date": "2025-12-30", "questions": [ { "title": "1", "type": "text" }, { "title": "2", "type": "scala" } ], "result": [ ["Einfach, weil ...", 5], ["Schwierig, weil ...", 1] ] } ], "start_date": "2025-12-25", "expire_date": "2025-04-10" }); - -} \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..63fdb29 --- /dev/null +++ b/index.php @@ -0,0 +1,16 @@ +content = "./files/"; + +$url_obj = TurtleURLObject::create_from_server(false, false); + +if (str_starts_with($url_obj->url, "couchdb")) { + $couchDB = new CouchDB("./data/couchdb.json", "./data/def_data.json", $url_obj); + $couchDB->execute(); +} else { + $url_obj->handle_request($path_info); +} \ No newline at end of file diff --git a/utils/couch.php b/utils/couch.php new file mode 100644 index 0000000..8d88db8 --- /dev/null +++ b/utils/couch.php @@ -0,0 +1,139 @@ +db_file = $db_file; + $this->def_db_file = $def_db_file; + $this->url_obj = $url_obj; + } + + public function getFile(): object { + if (file_exists($this->db_file)) { + $content = json_decode(file_get_contents($this->db_file)); + if (json_last_error() === JSON_ERROR_NONE) { + return $content; + } + } + + if (file_exists($this->def_db_file)) { + $content = json_decode(file_get_contents($this->def_db_file)); + if (json_last_error() === JSON_ERROR_NONE) { + return $content; + } + } + + return (object) []; + } + + public function setFile(object $content): void { + file_put_contents($this->db_file, str_replace(" ", "\t", json_encode($content, JSON_PRETTY_PRINT))); + } + + public function sendError(string $msg, int $code = 404) :bool { + http_response_code($code); + $this->url_obj->send_json(["ok" => false, "reason" => $msg]); + return false; + } + public function sendData(object $data = new stdClass()) :bool { + $data->ok = true; + $this->url_obj->send_json($data); + return true; + } + + public function execute(): bool { + $method = strtoupper($this->url_obj->method); + $args = $this->url_obj->args; + + //path + $pathParts = explode("/", trim($this->url_obj->url ?? "", "/")); + if (!empty($pathParts) && strtolower($pathParts[0]) == "couchdb") { + array_splice($pathParts, 0, 1); + } + + if (empty($pathParts)) return $this->sendData(); + + $dbName = $pathParts[0] ?? null; + $docId = null; + if (sizeof($pathParts) > 1) $docId = $pathParts[1] ?? null; + + if (!$dbName) return $this->sendError("wrong_usage"); + + //data + $db_obj = $this->getFile(); + $jsonBody = null; + $rawBody = $this->url_obj->get_body_text(); + if ($rawBody !== "") { + $jsonBody = json_decode($rawBody, true); + if (!is_array($jsonBody) && !is_object($jsonBody)) $jsonBody = null; + else $jsonBody = (object) $jsonBody; + } + + //get data + $obj = null; + if (isset($db_obj->$dbName) && is_object($db_obj->$dbName)) { + if ($docId && isset($db_obj->$dbName->$docId) && is_object($db_obj->$dbName->$docId)) { + $obj = $db_obj->$dbName->$docId; + } else if ($method != "PUT" && !($method == "GET" && $docId == "*")) { + return $this->sendError("missing"); + } + } else if ($method != "PUT") { + if (!$dbName || !isset($db_obj->$dbName)) { + return $this->sendError("no_db_file"); + } + } else { + $db_obj->$dbName = null; + } + + //execute + switch ($method) { + case "GET": + if ($docId == "*") { + $res_arr = []; + foreach ($db_obj->$dbName as $key => $value) $res_arr[] = $key; + $this->url_obj->send_json($res_arr); + return true; + } + + $obj->_id = $docId; + $obj->_rev = 0; + $this->url_obj->send_json($obj); + + return true; + case "PUT": + if ($db_obj->$dbName == null) { + if ($docId == null) { + $db_obj->$dbName = (object) []; + $this->setFile($db_obj); + return $this->sendData(); + } else { + return $this->sendError("no_db_file"); + } + } + + $db_obj->$dbName->$docId ??= (object) []; + + if ($jsonBody == null) return $this->sendError("missing_body"); + + unset($jsonBody->_id); + unset($jsonBody->_rev); + + $db_obj->$dbName->$docId = $jsonBody; + $this->setFile($db_obj); + + return $this->sendData((object) [ + "id" => $docId, + "rev" => 0 + ]); + case "DELETE": + unset($db_obj->$dbName->$docId); + $this->setFile($db_obj); + return $this->sendData((object) [ "id" => $docId ]); + default: + return $this->sendError("method_not_allowed"); + } + } +} diff --git a/utils/features.php b/utils/features.php new file mode 100644 index 0000000..1880ef1 --- /dev/null +++ b/utils/features.php @@ -0,0 +1,30 @@ + "success", + "data" => $data + ]; +} +function res_err(string|null $message = null) :object { + return (object) [ + "type" => "error", + "message" => $message + ]; +} \ No newline at end of file diff --git a/utils/url_handler.php b/utils/url_handler.php new file mode 100644 index 0000000..45662f3 --- /dev/null +++ b/utils/url_handler.php @@ -0,0 +1,167 @@ +method = $_SERVER['REQUEST_METHOD']; + $res->method_type = explode(',', $_SERVER['HTTP_ACCEPT'] ?? ''); + return $res; + } + + public string $url; + public object $args; + public function __construct(string $url, object $args) { + $this->url = $url; + $this->args = $args; + } + + public string $method; + public array $method_type; + + public function get_body_text() :string { + $bodyContent = file_get_contents("php://input"); + return $bodyContent; + } + public function get_body_json() :mixed { + return json_decode($this->get_body_text()); + } + + 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 send_text(string $text) :void { + header('Content-Type: text/plain'); + echo $text; + } + public function send_json(mixed $data) :void { + header('Content-Type: application/json'); + echo json_encode($data); + } + public function send_image(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"); + } else { + header("Content-Type: image/$fileExt"); + } + 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 { + return false; + } + return true; + } + + public function send_download_file(string $path) :bool { + if (!file_exists($path)) return false; + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="'.basename($path).'"'); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: ' . filesize($path)); + + readfile($path); + return true; + } + + public function is_image_request() :bool { + foreach ($this->method_type as $type) { + if (!str_starts_with($type, "image/")) return false; + } + return true; + } + + 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-------------------// + + if ($filePath === NULL || !file_exists($filePath)) { + $filePath = "{$path_info->content}NOT-FOUND.html"; + http_response_code(404); + } + + $this->send_custom_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; +} \ No newline at end of file