diff --git a/main.php b/main.php index 8c04b19..f231756 100644 --- a/main.php +++ b/main.php @@ -6,20 +6,44 @@ session_start(); $_dr = $_SERVER['DOCUMENT_ROOT']; // TODO: Make configurable in .ini -$GLOBALS['path_media'] = '/srv/http/boorein/media'; -$GLOBALS['base_media'] = 'media'; -$GLOBALS['base_uri'] = + +// Actual filesystem +$GLOBALS['path_root'] = '/srv/http/boorein'; +$GLOBALS['path_media'] = $GLOBALS['path_root'] . '/media'; +$GLOBALS['path_mediadb'] = $GLOBALS['path_root'] . '/media.db'; +// Uri addressed +$GLOBALS['base_root'] = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST']; +$GLOBALS['base_media'] = 'media'; + header('Content-Type: application/json'); -(match ([$_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']]) { +// ----- ROUTER ----- +(match ([$_SERVER['DOCUMENT_URI'], $_SERVER['REQUEST_METHOD']]) { ['/item', 'POST'] => post_item(), - //['/item', 'GET'] => get_item(), + ['/item', 'GET'] => get_item(), //['/search', 'GET'] => get_search(), default => Json::error('Not implemented') })->die(); + +function get_item() +{ + $id = $_GET['q'] ?? false; + if (!$id) Json::error('ID not specified')->die(); + + $media_db = new MediaDB(); + + $item = Item::load($media_db, $id); + + if ($item === null) { + Json::error('No item was found with the given ID')->die(); + } + + return Json::new($item->getUri()); +} + function post_item() { // The checks are performed internally @@ -32,10 +56,82 @@ function post_item() ]); }; +class MediaDB +{ + private $handler; + private bool $finished = false; + private array $lines = []; + + public function __construct() + { + // Just initialize the file handler + $this->handler = fopen($GLOBALS['path_mediadb'], 'r'); + if ($this->handler === false) + Json::error('Error opening media DB'); + } + + private function getLine(): ?array + { + $ret = fgetcsv($this->handler, 0, ' '); + if ($ret === false) + return null; + + return $ret; + } + + public function map(callable $func) + { + // First read from what's already in memory + foreach ($this->lines as $i_line) { + if ($func($i_line) === false) return; + } + + // REVIEW: Maybe this isn't needed cuz the while would be as eficient + // anyway? + + // If we already got to the end, there's no sense in carrying on + if ($this->finished) return; + + // If we run out, read from the file and append to array so the next lookup + // is fast + while ($line = $this->getLine()) { + $this->lines[] = $line; + + if ($func($line) === false) return; + } + + // Set the flag so we don't reach this point two times + $this->finished = true; + } +} + class Item { + // TODO: Change to id here in all occurrences private string $hash; private string $extension; + private array $tags = []; + + public static function load(MediaDB $db, string $id): ?Item + { + $ret = null; + + $db->map(function ($line) use (&$ret, $id) { + if ($line[0] == $id) { + $ret = new Item(); + $ret->hash = array_shift($line); + $ret->tags = $line; + $ret->extensionFromTags(); + + return true; + } + + return false; + }); + + return $ret; + } + // ::upload() requires the PHP file upload ARRAY from $_FILES public static function upload(array $php_file): Item @@ -51,7 +147,7 @@ class Item // --- INITIALIZE --- $ret = new Item(); $ret->hash = hash_file('sha256', $from_path); - $ret->calculateExtension($php_file); + $ret->extensionFromUpload($php_file); // --- ACTUALLY GRAB FILE --- $new_path = $ret->getPath(); @@ -63,8 +159,19 @@ class Item return $ret; } + private function extensionFromTags() + { + foreach ($this->tags as $i_tag) { + $parts = explode(':', $i_tag); + if ($parts[0] == 'format') { + $this->extension = $parts[1]; + return; + } + } + } + // Assumes is_uploaded_file has been done - private function calculateExtension(array $php_file) + private function extensionFromUpload(array $php_file) { $path = $php_file['tmp_name'] ?? false; $name = $php_file['name'] ?? null; @@ -121,9 +228,10 @@ class Item } public function getUri(): string { + // TODO: Implement relative return sprintf( '%s/%s/%s.%s', - $GLOBALS['base_uri'], + $GLOBALS['base_root'], $GLOBALS['base_media'], $this->hash, $this->extension,