From 4b9abfd36d91697cfc1e23564077c96742be8cb8 Mon Sep 17 00:00:00 2001 From: Mathias Wagner Date: Tue, 19 Jul 2022 21:10:42 +0200 Subject: [PATCH] Added the first cdn --- ContentDeliveryV1/.idea/.gitignore | 8 + ContentDeliveryV1/.idea/modules.xml | 8 + ContentDeliveryV1/.idea/php.xml | 4 + ContentDeliveryV1/.idea/sheepstar-api.iml | 8 + ContentDeliveryV1/.idea/vcs.xml | 6 + ContentDeliveryV1/root/index.php | 75 ++++++++ ContentDeliveryV1/util/DB.php | 15 ++ ContentDeliveryV1/util/MimeTypes.php | 201 ++++++++++++++++++++++ ContentDeliveryV1/util/MySQL.php | 131 ++++++++++++++ ContentDeliveryV1/util/Router.php | 90 ++++++++++ 10 files changed, 546 insertions(+) create mode 100644 ContentDeliveryV1/.idea/.gitignore create mode 100644 ContentDeliveryV1/.idea/modules.xml create mode 100644 ContentDeliveryV1/.idea/php.xml create mode 100644 ContentDeliveryV1/.idea/sheepstar-api.iml create mode 100644 ContentDeliveryV1/.idea/vcs.xml create mode 100755 ContentDeliveryV1/root/index.php create mode 100644 ContentDeliveryV1/util/DB.php create mode 100644 ContentDeliveryV1/util/MimeTypes.php create mode 100644 ContentDeliveryV1/util/MySQL.php create mode 100644 ContentDeliveryV1/util/Router.php diff --git a/ContentDeliveryV1/.idea/.gitignore b/ContentDeliveryV1/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/ContentDeliveryV1/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/ContentDeliveryV1/.idea/modules.xml b/ContentDeliveryV1/.idea/modules.xml new file mode 100644 index 0000000..0f1bc63 --- /dev/null +++ b/ContentDeliveryV1/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ContentDeliveryV1/.idea/php.xml b/ContentDeliveryV1/.idea/php.xml new file mode 100644 index 0000000..7341688 --- /dev/null +++ b/ContentDeliveryV1/.idea/php.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ContentDeliveryV1/.idea/sheepstar-api.iml b/ContentDeliveryV1/.idea/sheepstar-api.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/ContentDeliveryV1/.idea/sheepstar-api.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ContentDeliveryV1/.idea/vcs.xml b/ContentDeliveryV1/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/ContentDeliveryV1/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ContentDeliveryV1/root/index.php b/ContentDeliveryV1/root/index.php new file mode 100755 index 0000000..b38dd6b --- /dev/null +++ b/ContentDeliveryV1/root/index.php @@ -0,0 +1,75 @@ + $code, "message" => $message)); + exit(0); +} +spl_autoload_register('load'); +DB::init("localhost", "nutzername", "passwort", "datenbank"); +$media_dir = "/mnt/cdn/"; + +function checkAPIKey(): string { + if (isset($_SERVER['HTTP_API_KEY'])) { + if (DB::get()->query("SELECT null FROM api_keys WHERE apikey=?", $_SERVER['HTTP_API_KEY'])->numRows() != 1) + sendJSON(502, "You need to provide an valid api key."); + } else sendJSON(502, "You need to provide an valid api key."); + return $_SERVER['HTTP_API_KEY']; +} + +Router::add("/upload", function () use ($media_dir) { + $key = checkAPIKey(); + if(!empty($_FILES['asset'])) { + $fileID = substr(number_format(time() * mt_rand(),0,'',''),0,16); + $path = $media_dir.$fileID; + $asset = $_FILES['asset']; + $fileName = $asset['name']; + + if(move_uploaded_file($_FILES['asset']['tmp_name'], $path)) { + $split = explode(".", $fileName); + $fileEnding = substr($split[count($split)-1], -5); + + DB::get()->query("INSERT INTO media (assetID, assetEnding, assetOwner, assetName, assetDescription) VALUES (?, ?, ?, ?, ?)", + $fileID, $fileEnding, $key, $fileName, "test"); + sendJSON(1, "https://cdn.sheepstar.xyz/".$fileID.".".$fileEnding); + } else { + sendJSON(500, "File upload failed"); + } + } +}, "post"); + +Router::add("/delete", function () use ($media_dir) { + checkAPIKey(); + parse_str(file_get_contents("php://input"),$post_vars); + if (isset($post_vars['assetID'])) { + $assetID = $post_vars['assetID']; + $query = DB::get()->query("SELECT null FROM media WHERE assetID=?", $assetID)->numRows(); + if ($query) { + unlink($media_dir.$assetID); + DB::get()->query("DELETE FROM media WHERE assetID=?", $assetID); + sendJSON(1, "Resource deleted."); + } else sendJSON(404, "Resource not found."); + } else sendJSON(405, "Please provide an assetID."); +}, "delete"); + +Router::add("^/[0-9]+\.[a-zA-Z1-9]+$", function () use ($media_dir) { + + $parsed_url = parse_url($_SERVER['REQUEST_URI']); + $url = str_replace("/", "", $parsed_url['path']); + $split = explode(".", $url); + $assetID = $split[0]; + $assetEnding = $split[count($split)-1]; + $query = DB::get()->query("SELECT null FROM media WHERE assetID=? AND assetEnding=?", $assetID, $assetEnding)->numRows(); + + if ($query == 1) { + header("Content-Type: " . MimeTypes::getFromString($url)); + echo file_get_contents($media_dir.$assetID); + } else sendJSON(404, "Resource not found."); + +}); + +Router::add(".+", function () { + sendJSON(402, "Please use the correct URL format"); +}); + +Router::run(); diff --git a/ContentDeliveryV1/util/DB.php b/ContentDeliveryV1/util/DB.php new file mode 100644 index 0000000..4636379 --- /dev/null +++ b/ContentDeliveryV1/util/DB.php @@ -0,0 +1,15 @@ + 'application/java-archive', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'doc' => 'application/msword', + 'dat' => 'application/octet-stream', + 'oda' => 'application/oda', + 'ogg' => 'application/ogg', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'rdf' => 'application/rdf+xml', + 'rss' => 'application/rss+xml', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'gram' => 'application/srgs', + 'grxml' => 'application/srgs+xml', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'mif' => 'application/vnd.mif', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xls' => 'application/vnd.ms-excel', + 'xlb' => 'application/vnd.ms-excel', + 'xlt' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'docm' => 'application/vnd.ms-word.document.macroEnabled.12', + 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pps' => 'application/vnd.ms-powerpoint', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'vsd' => 'application/vnd.visio', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'vxml' => 'application/voicexml+xml', + 'bcpio' => 'application/x-bcpio', + 'vcd' => 'application/x-cdlink', + 'pgn' => 'application/x-chess-pgn', + 'cpio' => 'application/x-cpio', + 'csh' => 'application/x-csh', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'spl' => 'application/x-futuresplash', + 'tgz' => 'application/x-gtar', + 'gtar' => 'application/x-gtar', + 'latex' => 'application/x-latex', + 'nc' => 'application/x-netcdf', + 'cdf' => 'application/x-netcdf', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'tar' => 'application/x-tar', + 'tcl' => 'application/x-tcl', + 'tex' => 'application/x-tex', + 'texinfo' => 'application/x-texinfo', + 'texi' => 'application/x-texinfo', + 't' => 'application/x-troff', + 'tr' => 'application/x-troff', + 'roff' => 'application/x-troff', + 'man' => 'application/x-troff-man', + 'me' => 'application/x-troff-me', + 'ms' => 'application/x-troff-ms', + 'ustar' => 'application/x-ustar', + 'src' => 'application/x-wais-source', + 'xml' => 'application/xml', + 'xsl' => 'application/xml', + 'dtd' => 'application/xml-dtd', + 'zip' => 'application/zip', + 'au' => 'audio/basic', + 'snd' => 'audio/basic', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'kar' => 'audio/midi', + 'mpga' => 'audio/mpeg', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'm3u' => 'audio/x-mpegurl', + 'wma' => 'audio/x-ms-wma', + 'wax' => 'audio/x-ms-wax', + 'ram' => 'audio/x-pn-realaudio', + 'ra' => 'audio/x-pn-realaudio', + 'rm' => 'application/vnd.rn-realmedia', + 'wav' => 'audio/x-wav', + 'pdb' => 'chemical/x-pdb', + 'xyz' => 'chemical/x-xyz', + 'bmp' => 'image/bmp', + 'cgm' => 'image/cgm', + 'gif' => 'image/gif', + 'ief' => 'image/ief', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'png' => 'image/png', + 'svg' => 'image/svg+xml', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'djvu' => 'image/vnd.djvu', + 'djv' => 'image/vnd.djvu', + 'wbmp' => 'image/vnd.wap.wbmp', + 'ras' => 'image/x-cmu-raster', + 'ico' => 'image/x-icon', + 'pnm' => 'image/x-portable-anymap', + 'pbm' => 'image/x-portable-bitmap', + 'pgm' => 'image/x-portable-graymap', + 'ppm' => 'image/x-portable-pixmap', + 'rgb' => 'image/x-rgb', + 'xbm' => 'image/x-xbitmap', + 'psd' => 'image/x-photoshop', + 'xpm' => 'image/x-xpixmap', + 'xwd' => 'image/x-xwindowdump', + 'eml' => 'message/rfc822', + 'igs' => 'model/iges', + 'iges' => 'model/iges', + 'msh' => 'model/mesh', + 'mesh' => 'model/mesh', + 'silo' => 'model/mesh', + 'wrl' => 'model/vrml', + 'vrml' => 'model/vrml', + 'ics' => 'text/calendar', + 'ifb' => 'text/calendar', + 'csv' => 'text/csv', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'sgml' => 'text/sgml', + 'sgm' => 'text/sgml', + 'tsv' => 'text/tab-separated-values', + 'wml' => 'text/vnd.wap.wml', + 'wmls' => 'text/vnd.wap.wmlscript', + 'etx' => 'text/x-setext', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'mxu' => 'video/vnd.mpegurl', + 'm4u' => 'video/vnd.mpegurl', + 'flv' => 'video/x-flv', + 'json' => 'application/json', + 'py' => 'text/x-python', + 'avi' => 'video/x-msvideo', + 'ogv' => 'video/ogg', + 'movie' => 'video/x-sgi-movie', + ); + + public static function getType(string $ending): string { + if (isset(self::$mimeTypes[strtolower($ending)])) { + return self::$mimeTypes[strtolower($ending)]; + } else return self::$plain; + } + + public static function getFromString(string $string): string { + if ($string) { + $splitted = explode(".", $string); + return self::getType($splitted[sizeof($splitted)-1]); + } else return self::$plain; + } + + +} \ No newline at end of file diff --git a/ContentDeliveryV1/util/MySQL.php b/ContentDeliveryV1/util/MySQL.php new file mode 100644 index 0000000..a8ea5e6 --- /dev/null +++ b/ContentDeliveryV1/util/MySQL.php @@ -0,0 +1,131 @@ +connection = new mysqli($dbhost, $dbuser, $dbpass, $dbname); + if ($this->connection->connect_error) { + $this->error('Failed to connect to MySQL - ' . $this->connection->connect_error); + } + $this->connection->set_charset($charset); + } + + public function query($query) { + if (!$this->query_closed) { + $this->query->close(); + } + if ($this->query = $this->connection->prepare($query)) { + if (func_num_args() > 1) { + $x = func_get_args(); + $args = array_slice($x, 1); + $types = ''; + $args_ref = array(); + foreach ($args as $k => &$arg) { + if (is_array($args[$k])) { + foreach ($args[$k] as $j => &$a) { + $types .= $this->_gettype($args[$k][$j]); + $args_ref[] = &$a; + } + } else { + $types .= $this->_gettype($args[$k]); + $args_ref[] = &$arg; + } + } + array_unshift($args_ref, $types); + call_user_func_array(array($this->query, 'bind_param'), $args_ref); + } + $this->query->execute(); + if ($this->query->errno) { + $this->error('Unable to process MySQL query (check your params) - ' . $this->query->error); + } + $this->query_closed = FALSE; + $this->query_count++; + } else { + $this->error('Unable to prepare MySQL statement (check your syntax) - ' . $this->connection->error); + } + return $this; + } + + + public function fetchAll($callback = null) { + $params = array(); + $row = array(); + $meta = $this->query->result_metadata(); + while ($field = $meta->fetch_field()) { + $params[] = &$row[$field->name]; + } + call_user_func_array(array($this->query, 'bind_result'), $params); + $result = array(); + while ($this->query->fetch()) { + $r = array(); + foreach ($row as $key => $val) { + $r[$key] = $val; + } + if ($callback != null && is_callable($callback)) { + $value = call_user_func($callback, $r); + if ($value == 'break') break; + } else { + $result[] = $r; + } + } + $this->query->close(); + $this->query_closed = TRUE; + return $result; + } + + public function fetchArray() { + $params = array(); + $row = array(); + $meta = $this->query->result_metadata(); + while ($field = $meta->fetch_field()) { + $params[] = &$row[$field->name]; + } + call_user_func_array(array($this->query, 'bind_result'), $params); + $result = array(); + while ($this->query->fetch()) { + foreach ($row as $key => $val) { + $result[$key] = $val; + } + } + $this->query->close(); + $this->query_closed = TRUE; + return $result; + } + + public function close() { + return $this->connection->close(); + } + + public function numRows() { + $this->query->store_result(); + return $this->query->num_rows; + } + + public function affectedRows() { + return $this->query->affected_rows; + } + + public function lastInsertID() { + return $this->connection->insert_id; + } + + public function error($error) { + if ($this->show_errors) { + exit($error); + } + } + + private function _gettype($var) { + if (is_string($var)) return 's'; + if (is_float($var)) return 'd'; + if (is_int($var)) return 'i'; + return 'b'; + } + +} \ No newline at end of file diff --git a/ContentDeliveryV1/util/Router.php b/ContentDeliveryV1/util/Router.php new file mode 100644 index 0000000..c0ff7ce --- /dev/null +++ b/ContentDeliveryV1/util/Router.php @@ -0,0 +1,90 @@ + $expression, + 'function' => $function, + 'method' => $method + )); + } + + public static function pathNotFound($function){ + self::$pathNotFound = $function; + } + + public static function methodNotAllowed($function){ + self::$methodNotAllowed = $function; + } + + public static function run($basepath = '/'){ + + $parsed_url = parse_url($_SERVER['REQUEST_URI']); + + if(isset($parsed_url['path'])){ + $path = $parsed_url['path']; + }else{ + $path = '/'; + } + + $method = $_SERVER['REQUEST_METHOD']; + + $path_match_found = false; + + $route_match_found = false; + + foreach(self::$routes as $route){ + + if($basepath!=''&&$basepath!='/'){ + $route['expression'] = '('.$basepath.')'.$route['expression']; + } + + $route['expression'] = '^'.$route['expression']; + + $route['expression'] = $route['expression'].'$'; + + if(preg_match('#'.$route['expression'].'#',$path,$matches)){ + + $path_match_found = true; + + if(strtolower($method) == strtolower($route['method'])){ + + array_shift($matches); + + if($basepath!=''&&$basepath!='/'){ + array_shift($matches); + } + + call_user_func_array($route['function'], $matches); + + $route_match_found = true; + + break; + } + } + } + + if(!$route_match_found){ + + if($path_match_found){ + header("HTTP/1.0 405 Method Not Allowed"); + if(self::$methodNotAllowed){ + call_user_func_array(self::$methodNotAllowed, Array($path,$method)); + } + }else{ + header("HTTP/1.0 404 Not Found"); + if(self::$pathNotFound){ + call_user_func_array(self::$pathNotFound, Array($path)); + } + } + + } + + } + +} \ No newline at end of file