From 566d22575eea2dd3f224899eda2617de623d7314 Mon Sep 17 00:00:00 2001 From: Banana Date: Sat, 21 Dec 2019 18:21:13 +0100 Subject: [PATCH] a lot... --- README | 29 +++++++++++++- documentation/setup.txt | 4 +- webroot/.htaccess | 6 ++- webroot/index.php | 52 +++++++++++++++++++----- webroot/lib/summoner.class.php | 73 ++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 15 deletions(-) diff --git a/README b/README index 7c16ba7..65b7808 100644 --- a/README +++ b/README @@ -1,5 +1,30 @@ selfpaste is a small self hosting paste service. +It is not the aim to replace any other well know paste service. It is an experiment +and build for private use only. + +This tool uses PHP fileinfo: https://www.php.net/manual/en/intro.fileinfo.php + + The functions in this module try to guess the content type and encoding of a file + by looking for certain magic byte sequences at specific positions within the file. + While this is not a bullet proof approach the heuristics used do a very good job. + +It is not really bullet proof, but it does the job. Everything can be manipulated +to look alike something it isn't. + +So, here is a friendly REMINDER: + + - Use at own risk. + - Don't open it up to the public + - Check regularly what is added + - Clean everything what you do not know + - You provide the service by hosting it. Your are responsible for it! + - Change your secret often. + +# Why json as a response? +In cases the upload is over post_max_size the request will not be "arrive". +Meaning the script does not receive enough information to work with. +In this case we return the start page. Which is a valid HTTP 200 status response. +So the client can not only rely in the HTTP status code alone. # Third party resources -Link shortening inspired and some code used from: https://www.jwz.org/base64-shortlinks/ -UAC image from: https://doomwiki.org/wiki/File:UAC_insignia.png \ No newline at end of file +Link shortening inspired and some code used from: https://www.jwz.org/base64-shortlinks/ \ No newline at end of file diff --git a/documentation/setup.txt b/documentation/setup.txt index e3ba56a..34c7435 100644 --- a/documentation/setup.txt +++ b/documentation/setup.txt @@ -1,2 +1,4 @@ Change upload_max_filesize and php_value post_max_size in webroot/.htaccess -Change ENDPOINT variable in selfpaste.sh client file. \ No newline at end of file +Change ENDPOINT variable in selfpaste.sh client file. +Change the SELFPASTE_UPLOAD_SECRET in config.php and client file. +Change SELFPASTE_ALLOWED_FILETYPES to your needs. \ No newline at end of file diff --git a/webroot/.htaccess b/webroot/.htaccess index a043516..c10a925 100644 --- a/webroot/.htaccess +++ b/webroot/.htaccess @@ -14,5 +14,9 @@ AddDefaultCharset utf-8 RewriteRule ^(.*)$ index.php?s=$1 [QSA,L] +# post_max_size should be greater then upload_max_filesize +# otherwise there will be no feedback and it looks like +# nothing has happened +# if post is greater than post_max_size set in php.ini, no feedback is given... +php_value post_max_size 2M php_value upload_max_filesize 1M -php_value post_max_size 1M \ No newline at end of file diff --git a/webroot/index.php b/webroot/index.php index 418fafb..85729a4 100644 --- a/webroot/index.php +++ b/webroot/index.php @@ -29,6 +29,7 @@ if(!empty($_urlToParse)) { } } +# error reporting ini_set('log_errors',true); ini_set('error_log','./logs/error.log'); if(DEBUG === true) { @@ -40,6 +41,8 @@ else { # static helper class require 'lib/summoner.class.php'; +# config file +require 'config.php'; $_short = false; if(isset($_GET['s']) && !empty($_GET['s'])) { @@ -48,26 +51,53 @@ if(isset($_GET['s']) && !empty($_GET['s'])) { } $_create = false; -if(isset($_POST['c']) && !empty($_GET['s'])) { - $_create = trim($_GET['s']); - $_create = Summoner::validate($_short,'nospace') ? $_short : false; +if(isset($_POST['dl']) && !empty($_POST['dl']) + && isset($_FILES['pasty']) && !empty($_FILES['pasty']) + && $_POST['dl'] === SELFPASTE_UPLOAD_SECRET) { + $_create = true; } $contentType = 'Content-type: text/html; charset=UTF-8'; -$contentBody = 'welcome'; +$contentView = 'welcome'; +$httpResponseCode = 200; if(!empty($_short)) { - + $contentView = 'view'; } +elseif ($_create === true) { + $contentView = 'created'; + $contentBody = array( + 'message' => 'Something went wrong.', + 'status' => '400' + ); + $contentType = 'Content-type:application/json;charset=utf-8'; + $httpResponseCode = 400; + + $_file = $_FILES['pasty']; + + $_checks = array('fileupload','filetype','store'); + $_do['status'] = false; + foreach($_checks as $_check) { + if(method_exists('Summoner',$_check)) { + $_do = Summoner::$_check($_file); + if($_do['status'] !== true) { + break; + } + } + } -var_dump($_POST); -var_dump($_FILES); -var_dump($_SERVER); + if($_do['status'] === true) { + $contentBody = array( + 'message' => $_do['message'], + 'status' => '200' + ); + } +} -# header information header($contentType); -if(file_exists('view/'.$contentBody.'.inc.php')) { - require_once 'view/'.$contentBody.'.inc.php'; +http_response_code($httpResponseCode); +if(file_exists('view/'.$contentView.'.inc.php')) { + require_once 'view/'.$contentView.'.inc.php'; } else { error_log('Content body file missing. '.var_export($_SERVER,true),3,'./logs/error.log'); diff --git a/webroot/lib/summoner.class.php b/webroot/lib/summoner.class.php index a000128..8f3b2da 100644 --- a/webroot/lib/summoner.class.php +++ b/webroot/lib/summoner.class.php @@ -136,4 +136,77 @@ class Summoner { return (substr($haystack, -$length) === $needle); } + + + /** + * Simple helper to detect the $_FILE upload status + * Expects an array from $_FILE + * @param $file + * @return array + */ + static function fileupload($file) { + $message = "Unknown upload error"; + $status = false; + + if(isset($file['error'])) { + switch ($file['error']) { + case UPLOAD_ERR_OK: + $message = "There is no error, the file uploaded with success."; + $status = true; + break; + case UPLOAD_ERR_INI_SIZE: + $message = "The uploaded file exceeds the upload_max_filesize directive in php.ini"; + break; + case UPLOAD_ERR_FORM_SIZE: + $message = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"; + break; + case UPLOAD_ERR_PARTIAL: + $message = "The uploaded file was only partially uploaded"; + break; + case UPLOAD_ERR_NO_FILE: + $message = "No file was uploaded"; + break; + case UPLOAD_ERR_NO_TMP_DIR: + $message = "Missing a temporary folder"; + break; + case UPLOAD_ERR_CANT_WRITE: + $message = "Failed to write file to disk"; + break; + case UPLOAD_ERR_EXTENSION: + $message = "File upload stopped by extension"; + break; + } + } + + return array( + 'message' => $message, + 'status' => $status + ); + } + + /** + * Simple helper to detect the $_FILE type + * Expects an array from $_FILE + * + * @see https://www.php.net/manual/en/intro.fileinfo.php + * + * @param $file + * @return array + */ + static function filetype($file) { + $message = "Filetype not suported"; + $status = false; + + if(isset($file['tmp_name'])) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $file['tmp_name']); + finfo_close($finfo); + var_dump($mime); + } + + return array( + 'message' => $message, + 'status' => $status + ); + } } -- 2.39.5