From ea0e8ddad860d5bfd3c9c3ce8be493d34e8df6db Mon Sep 17 00:00:00 2001 From: Dendy Faist Date: Mon, 10 Jul 2023 04:41:00 +0200 Subject: [PATCH] Intial commit --- main.php | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 main.php diff --git a/main.php b/main.php new file mode 100644 index 0000000..8c04b19 --- /dev/null +++ b/main.php @@ -0,0 +1,160 @@ + post_item(), + //['/item', 'GET'] => get_item(), + //['/search', 'GET'] => get_search(), + default => Json::error('Not implemented') +})->die(); + +function post_item() +{ + // The checks are performed internally + $item = Item::upload($_FILES['file']); + + return Json::new([ + 'type' => 'success', + 'id' => $item->getHash(), + 'link' => $item->getUri(), + ]); +}; + +class Item +{ + private string $hash; + private string $extension; + + // ::upload() requires the PHP file upload ARRAY from $_FILES + public static function upload(array $php_file): Item + { + $from_path = $php_file['tmp_name'] ?? null; + + // --- CHECKS --- + if (!is_string($from_path)) + Json::error('Passed invalid upload structure')->die(); + if (!is_uploaded_file($from_path)) + Json::error('Trying to upload illegal or non-existent file')->die(); + + // --- INITIALIZE --- + $ret = new Item(); + $ret->hash = hash_file('sha256', $from_path); + $ret->calculateExtension($php_file); + + // --- ACTUALLY GRAB FILE --- + $new_path = $ret->getPath(); + if (file_exists($new_path)) + Json::error('File already exists')->die(); + if (!move_uploaded_file($from_path, $new_path)) + Json::error('Failed to move uploaded file')->die(); + + return $ret; + } + + // Assumes is_uploaded_file has been done + private function calculateExtension(array $php_file) + { + $path = $php_file['tmp_name'] ?? false; + $name = $php_file['name'] ?? null; + + // Try to get extension from mimetype + $ext = (new finfo(FILEINFO_EXTENSION))->file($path); + + // REVIEW: Maybe change it so it doesn't have to be separated like this but + // do somethign like ['mime/type', null] be equivalent to this? + if (array_search($ext, ['webp', 'png', 'jpeg']) !== false) { + $this->extension = $ext; + return; + } + + // If it doesn't work, try to figure it out from the original extension + if ($ext == '???') { + // We mustn't accept everything straight away, so we're only accepting + // mime-type and original extension combinations that make sense + $whitelist = [ + ['application/zip', 'kra'], + ['application/zip', 'krz'], + ]; + + // NOTE: The original extension has to be grabbed from the original name + $mime = mime_content_type($path); + $ext = pathinfo($name, PATHINFO_EXTENSION); + + if (array_search([$mime, $ext], $whitelist) !== false) { + $this->extension = $ext; + return; + } + } + + Json::error('File mime-type and or extension not allowed.')->die(); + } + + public function getHash(): string + { + return $this->hash; + } + public function getExtension(): string + { + return $this->extension; + } + + public function getPath(bool $absolute = false): string + { + return sprintf( + '%s/%s.%s', + $GLOBALS[$absolute ? 'path_media' : 'path_media'], + $this->hash, + $this->extension + ); + } + public function getUri(): string + { + return sprintf( + '%s/%s/%s.%s', + $GLOBALS['base_uri'], + $GLOBALS['base_media'], + $this->hash, + $this->extension, + ); + } +} + +class Json +{ + function __construct( + private mixed $struct + ) { + $this->struct = $struct; + } + + public static function new(mixed $struct): Json + { + return new Json($struct); + } + + public static function error(mixed $msg): Json + { + return new Json([ + 'type' => 'error', + 'msg' => $msg, + ]); + } + + public function die() + { + print(json_encode($this->struct)); + die(); + } +}