Skip to content

Instantly share code, notes, and snippets.

@mikitsu
Last active March 1, 2020 18:33
Show Gist options
  • Save mikitsu/3a4f19f27a2c54c3cfb7eabd3dea9dff to your computer and use it in GitHub Desktop.
Save mikitsu/3a4f19f27a2c54c3cfb7eabd3dea9dff to your computer and use it in GitHub Desktop.
Simple PHP uploader
<?php
// the location of the configuration/state data in JSON format
$CONFIG_FILE = '/path/to/config.json';
/* Config file format:
* The configuration file is a JSON object with the following (sub-keys):
* - 'users': an object mapping user names to objects with the following keys:
* - 'password': the user's password, in the format accepted by password_verify
* - 'upload interval': the time limit between successive uploads by the user, in seconds
* - 'upload directory': the directory to place the user's uploads in; this should end in the path separator.
* - 'max file size': the maximum uploadable file size, in bytes
* - 'max saved files': the maximum number of files to be kept. Old files will be deleted if neccessary. null to keep all files.
* - 'defaults': default values for user settings 'upload interval', 'max file size', 'max saved files' and 'upload directory'
* - '_internal': internal data structure (don't touch)
*/
function send_status($number){
$stati = [500 => "Internal Server Error", 400 => "Bad Request", 401 => "Unauthorized", 413 => "Payload too large", 429 => "Too many requests"];
header($_SERVER['SERVER_PROTOCOL']." $number ".$stati[$number]);
}
$config = json_decode(file_get_contents($CONFIG_FILE), TRUE);
if ($config == NULL){
send_status(500);
} else {
if (!array_key_exists('_internal', $config)){
$config['_internal'] = ['last upload' => []];
}
if (isset($_SERVER['PHP_AUTH_USER'])){
$user = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];
} else {
$user = $_POST['username'];
$password = $_POST['password'];
}
if (array_key_exists($user, $config['users'])){
$uconfig = array_merge($config['defaults'], $config['users'][$user]);
if (password_verify($password, $uconfig['password'])){
$dir = $uconfig['upload directory'];
if (substr($dir, -1) != '/'){
$dir .= '/';
}
if (!($file_name = array_keys($_FILES)[0])){
send_status(400);
}else if (array_key_exists($user, $config['_internal']['last upload'])
&& time() < $config['_internal']['last upload'][$user] + $uconfig['upload interval']){
send_status(429);
}else if ($_FILES[$file_name]['size'] > $uconfig['max file size']){
send_status(413);
}else if (move_uploaded_file($_FILES[$file_name]['tmp_name'],
$dir.$user.'-'.date('c'))){
$config['_internal']['last upload'][$user] = time();
if ($uconfig['max saved files'] !== NULL){
$files = [];
foreach(scandir($dir, TRUE) as $potential_file){
if (is_file($dir.$potential_file)
&& substr($potential_file, 0, strlen($user)) === $user){
array_push($files, $potential_file);
}
}
foreach(array_slice($files, $uconfig['max saved files']) as $old_file){
$old_file = $dir . $old_file;
unlink($old_file);
}
}
} else {
send_status(500);
}
} else {
send_status(401);
echo 'Wrong password';
}
} else {
send_status(401);
echo 'user unknown';
}
file_put_contents($CONFIG_FILE, json_encode($config));
}
?>
{
"users": {
"test": {
"password": "$2y$10$2cTYPE3RUzZltUE86cp31O0Xy2KZn0wApF1xko.WxQrlxIte.UtDC",
"upload directory": "/path/to/uploads/",
"upload interval": 5
},
"user-2": {
"password": "$2y$10$.4LGqtDExkTFc62lz9vLm.r3xXHzuzPf81xP8pNbpAzOdkixZuoAy",
"upload directory": "/path/to/other/uploads/",
"max file size": 1000000
}
},
"defaults": {
"max file size": 1000,
"max saved files": 5,
"upload interval": 3600
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment