From 5861e7384836d109621b74d45c164355baadf5bb Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 6 Jun 2020 13:27:47 +0200 Subject: [PATCH] implemented dynamic content controller loading, enabling whitelisting of content types. closes #87 --- api/base64.php | 5 +- api/geturl.php | 5 +- api/info.php | 2 +- api/pastebin.php | 4 +- api/upload.php | 19 ++++-- content-controllers/text/text.controller.php | 2 +- inc/core.php | 61 ++++++++++---------- index.php | 5 +- rtfm/CONFIG.md | 15 +++++ 9 files changed, 69 insertions(+), 49 deletions(-) diff --git a/api/base64.php b/api/base64.php index 47b5f4c..0f4d25c 100644 --- a/api/base64.php +++ b/api/base64.php @@ -10,10 +10,7 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT . DS . 'inc' . DS. 'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'image'. DS . 'image.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'text'. DS . 'text.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'url'. DS . 'url.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'video'. DS . 'video.controller.php'); +loadAllContentControllers(); // check write permissions first if(!isFolderWritable(ROOT.DS.'data')) diff --git a/api/geturl.php b/api/geturl.php index 4134846..dafdc70 100644 --- a/api/geturl.php +++ b/api/geturl.php @@ -10,10 +10,7 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT . DS . 'inc' . DS. 'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'image'. DS . 'image.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'text'. DS . 'text.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'url'. DS . 'url.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'video'. DS . 'video.controller.php'); +loadAllContentControllers(); // check write permissions first if(!isFolderWritable(ROOT.DS.'data')) diff --git a/api/info.php b/api/info.php index 6f10f85..ed0a8f2 100644 --- a/api/info.php +++ b/api/info.php @@ -10,7 +10,7 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT . DS . 'inc' . DS. 'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'video'. DS . 'video.controller.php'); +loadAllContentControllers(); $hash = $_REQUEST['hash']; diff --git a/api/pastebin.php b/api/pastebin.php index 34f3388..3a77ac8 100644 --- a/api/pastebin.php +++ b/api/pastebin.php @@ -10,7 +10,9 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT . DS . 'inc' . DS. 'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'text'. DS . 'text.controller.php'); +$controllers = loadAllContentControllers(); +if(!in_array('TextController',$controllers)) + exit(json_encode(array('status'=>'err','reason'=>'Text controller not enabled'))); // check write permissions first if(!isFolderWritable(ROOT.DS.'data')) diff --git a/api/upload.php b/api/upload.php index 0571de0..06ab2ac 100644 --- a/api/upload.php +++ b/api/upload.php @@ -10,10 +10,7 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT . DS . 'inc' . DS. 'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'image'. DS . 'image.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'text'. DS . 'text.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'url'. DS . 'url.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'video'. DS . 'video.controller.php'); +$allowedcontentcontrollers = loadAllContentControllers(); // check write permissions first if(!isFolderWritable(ROOT.DS.'data')) @@ -42,10 +39,22 @@ if ($_FILES['file']["error"] == UPLOAD_ERR_OK) //cross check filetype for controllers // //image? + + foreach($allowedcontentcontrollers as $cc) + { + if(in_array($type,(new $cc)->getRegisteredExtensions())) + { + $answer = (new $cc())->handleUpload($_FILES['file']['tmp_name'],$hash); + break; + } + } + +/* if(in_array($type,(new ImageController)->getRegisteredExtensions())) { $answer = (new ImageController())->handleUpload($_FILES['file']['tmp_name'],$hash); } + //or, a text else if($type=='text') { @@ -56,7 +65,7 @@ if ($_FILES['file']["error"] == UPLOAD_ERR_OK) { $answer = (new VideoController())->handleUpload($_FILES['file']['tmp_name'],$hash); } - +*/ if(!$answer) $answer = array('status'=>'err','reason'=>'Unsupported filetype: '.$type,'filetype'=>$type); diff --git a/content-controllers/text/text.controller.php b/content-controllers/text/text.controller.php index 7567d10..8d4c54a 100644 --- a/content-controllers/text/text.controller.php +++ b/content-controllers/text/text.controller.php @@ -3,7 +3,7 @@ class TextController implements ContentController { //returns all extensions registered by this type of content - public function getRegisteredExtensions(){return array('txt');} + public function getRegisteredExtensions(){return array('txt','text','csv');} public function handleHash($hash,$url) { diff --git a/inc/core.php b/inc/core.php index 8b95d79..eadcda4 100644 --- a/inc/core.php +++ b/inc/core.php @@ -109,33 +109,17 @@ function architect($url) $extension = pathinfo($hash, PATHINFO_EXTENSION); - //First, check if URL is an image - if(in_array($extension,(new ImageController)->getRegisteredExtensions())) + foreach(loadAllContentControllers() as $cc) { - (new ImageController())->handleHash($hash,$u); - } - //or, a url - else if(in_array($extension,(new UrlController)->getRegisteredExtensions())) - { - var_dump("Url"); - } - //or, a text - else if(in_array($extension,(new TextController)->getRegisteredExtensions())) - { - (new TextController())->handleHash($hash,$u); - } - //or, a video - else if(in_array($extension,(new VideoController)->getRegisteredExtensions())) - { - (new VideoController())->handleHash($hash,$u); - } - //very odd. We know it's a valid hash but no controller says it's one of their kids - //oh well - else - { - var_dump("odd err"); + if(in_array($extension,(new $cc)->getRegisteredExtensions())) + { + (new $cc())->handleHash($hash,$u); + return; + } } + http_response_code(404); + die("404"); } //var_dump($u); @@ -227,8 +211,6 @@ function mightBeAHash($string) function autoload($className) { - if (file_exists(ROOT . DS . 'content-controllers' . DS . strtolower($className) . '.php')) - require_once(ROOT . DS . 'content-controllers' . DS . strtolower($className) . '.php'); if (file_exists(ROOT . DS . 'interfaces' . DS . strtolower($className) . '.interface.php')) require_once(ROOT . DS . 'interfaces' . DS . strtolower($className) . '.interface.php'); if ($className=='Encryption') @@ -491,13 +473,18 @@ function getStorageControllers() return $controllers; } -function getAllContentControllers() +function loadAllContentControllers() { + $allowedcontrollers = false; + if(defined('CONTENTCONTROLLERS') && CONTENTCONTROLLERS != '') + { + $allowedcontrollers = array_map('strtolower', explode(',',CONTENTCONTROLLERS)); + } $controllers = array(); if ($handle = opendir(ROOT.DS.'content-controllers')) { while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { - if(is_dir(ROOT.DS.'content-controllers'.DS.$entry) && file_exists(ROOT.DS.'content-controllers'.DS.$entry.DS."$entry.controller.php")) + if(is_dir(ROOT.DS.'content-controllers'.DS.$entry) && file_exists(ROOT.DS.'content-controllers'.DS.$entry.DS."$entry.controller.php") && ( ($allowedcontrollers!==false && in_array($entry,$allowedcontrollers) ) || $allowedcontrollers===false)) { $controllers[] = ucfirst($entry).'Controller'; include_once(ROOT.DS.'content-controllers'.DS.$entry.DS."$entry.controller.php"); @@ -513,7 +500,7 @@ function getAllContentControllers() function getAllContentFiletypes() { $types = array(); - $controllers = getAllContentControllers(true); + $controllers = loadAllContentControllers(); foreach($controllers as $c) { $types = array_merge($types,(new $c)->getRegisteredExtensions()); @@ -616,4 +603,20 @@ function isIPInRange( $ip, $range ) { $wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1; $netmask_decimal = ~ $wildcard_decimal; return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) ); +} + +function loadContentControllers() +{ + if(defined('CONTENTCONTROLLERS') && CONTENTCONTROLLERS != '') + { + $controllers = explode(',',CONTENTCONTROLLERS); + foreach($controllers as $controller) + { + $controller = strtolower($controller); + if(@file_exists(ROOT . DS . 'content-controllers' . DS. $controller. DS . $controller.'.controller.php')) + require_once(ROOT . DS . 'content-controllers' . DS. $controller. DS . $controller.'.controller.php'); + } + } + else + loadAllContentControllers(); } \ No newline at end of file diff --git a/index.php b/index.php index be94583..71c6e71 100644 --- a/index.php +++ b/index.php @@ -10,10 +10,7 @@ include_once(ROOT.DS.'inc'.DS.'config.inc.php'); //loading core and controllers include_once(ROOT.DS.'inc'.DS.'core.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'image'. DS . 'image.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'text'. DS . 'text.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'url'. DS . 'url.controller.php'); -require_once(ROOT . DS . 'content-controllers' . DS. 'video'. DS . 'video.controller.php'); +loadAllContentControllers(); //send the URL to the architect. It'll know what to do diff --git a/rtfm/CONFIG.md b/rtfm/CONFIG.md index 3c4497e..0a79257 100644 --- a/rtfm/CONFIG.md +++ b/rtfm/CONFIG.md @@ -22,6 +22,21 @@ In this file you can set the following options. For a simple working example con | UPLOAD_CODE (NOT IMPLEMENTED | string | If set, all uploads require this code via GET or POST variable "uploadcode" or upload will fail | | MAX_RESIZED_IMAGES (NOT IMPLEMENTED | string | If set, limits count of resized images/videos per file on server | +# Content controllers +PictShare is not limited to handling just images. Various content types including txt,mp4 and even url shortenings are supported. +By default all of these are enabled but if you only need one or more, you can whitelist them and all others won't be accessible. + +|Option | value type | What it does| +|--- | --- | ---| +| CONTENTCONTROLLERS | CSV string | If set, will whitelist content controllers for your instance. Must be uppercase and can be comma separated. Example: Only Pictures: `IMAGE`, Pictures and Videos: `IMAGE,VIDEO` | + +Available values for the `CONTENTCONTROLLERS` setting are: + +- IMAGE +- TEXT +- VIDEO +- URL + # Storage controllers PictShare has an extention system that allows handling of multiple storage solutions or backends. If a requested file is not found locally, PictShare will ask all configured storage controllers if they have it, then download and serve it to the user.