g6
This commit is contained in:
1 parent
565c1b9911
commit
28490ce8b3
36 files changed
+587
-179
No files matched your search
+139
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
class CouchDB {
|
||||
public string $db_file;
|
||||
public string $def_db_file;
|
||||
public TurtleURLObject $url_obj;
|
||||
|
||||
public function __construct(string $db_file, string $def_db_file, TurtleURLObject $url_obj) {
|
||||
$this->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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
function isFileExtImage(string $fileExt) :bool {
|
||||
switch ($fileExt) {
|
||||
case 'png':
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
case 'ico':
|
||||
case 'gif':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function res_mixed(bool $success, mixed $data = null, string $except = null) :object {
|
||||
return $success ? res_ok($data): res_err($data ?? $except);
|
||||
}
|
||||
function res_ok(mixed $data = null) :object {
|
||||
return (object) [
|
||||
"type" => "success",
|
||||
"data" => $data
|
||||
];
|
||||
}
|
||||
function res_err(string|null $message = null) :object {
|
||||
return (object) [
|
||||
"type" => "error",
|
||||
"message" => $message
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
require_once 'features.php';
|
||||
|
||||
///A collection of given paths
|
||||
class TurtlePathInfo {
|
||||
public string $content;
|
||||
}
|
||||
|
||||
///Parse url and execute it
|
||||
class TurtleURLObject {
|
||||
public static function create_from_server(bool $lowerCase = true, bool $alternativeURL = true) :TurtleURLObject {
|
||||
$urlParts = explode('?', trim($_SERVER['REQUEST_URI'], '/'));
|
||||
$urlMark = _parseUrlMark($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'] ?? '');
|
||||
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;
|
||||
}
|
||||
Reference in new issue
Block a user