forked from flashii/eeprom
Implement Index routing rather than stinky if statements.
This commit is contained in:
parent
4ecb410b3c
commit
e107ae152d
5 changed files with 413 additions and 364 deletions
112
debug-pages/test-v1.0.html
Normal file
112
debug-pages/test-v1.0.html
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<!doctype html>
|
||||||
|
<input type="file" id="-eeprom-file"/> <button id="-eeprom-abort">Abort</button> <progress id="-eeprom-progress" min="0" max="100" value="0"></progress> <span id="-eeprom-progress-done"></span> <span id="-eeprom-progress-total"></span><br/>
|
||||||
|
<div id="-eeprom-history"></div>
|
||||||
|
<script src="/js/eeprom-v1.0.js" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var eFile = document.getElementById('-eeprom-file'),
|
||||||
|
eAbort = document.getElementById('-eeprom-abort'),
|
||||||
|
eProgress = document.getElementById('-eeprom-progress'),
|
||||||
|
eProgressD = document.getElementById('-eeprom-progress-done'),
|
||||||
|
eProgressT = document.getElementById('-eeprom-progress-total'),
|
||||||
|
eHistory = document.getElementById('-eeprom-history'),
|
||||||
|
eTask = undefined;
|
||||||
|
|
||||||
|
eAbort.onclick = function() {
|
||||||
|
if(eTask)
|
||||||
|
eTask.abort();
|
||||||
|
};
|
||||||
|
|
||||||
|
var eClient = new EEPROM(1, '/uploads', 'Misuzu :cookie');
|
||||||
|
|
||||||
|
eFile.onchange = function() {
|
||||||
|
var task = eTask = eClient.createUpload(this.files[0]);
|
||||||
|
|
||||||
|
task.onProgress = function(progressInfo) {
|
||||||
|
eProgress.value = progressInfo.progress;
|
||||||
|
eProgressD.textContent = progressInfo.loaded;
|
||||||
|
eProgressT.textContent = progressInfo.total;
|
||||||
|
};
|
||||||
|
|
||||||
|
task.onFailure = function(errorInfo) {
|
||||||
|
if(!errorInfo.userAborted) {
|
||||||
|
var errorText = 'Was unable to upload file.';
|
||||||
|
|
||||||
|
switch(errorInfo.error) {
|
||||||
|
case EEPROM.ERR_INVALID:
|
||||||
|
errorText = 'Upload request was invalid.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_AUTH:
|
||||||
|
errorText = 'Upload authentication failed, refresh and try again.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_ACCESS:
|
||||||
|
errorText = 'You\'re not allowed to upload files.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_GONE:
|
||||||
|
errorText = 'Upload client has a configuration error or the server is gone.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_DMCA:
|
||||||
|
errorText = 'This file has been uploaded before and was removed for copyright reasons, you cannot upload this file.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_SERVER:
|
||||||
|
errorText = 'Upload server returned a critical error, try again later.';
|
||||||
|
break;
|
||||||
|
case EEPROM.ERR_SIZE:
|
||||||
|
if(errorInfo.maxSize < 1)
|
||||||
|
errorText = 'Selected file is too large.';
|
||||||
|
else {
|
||||||
|
var _t = ['bytes', 'KB', 'MB', 'GB', 'TB'],
|
||||||
|
_i = parseInt(Math.floor(Math.log(errorInfo.maxSize) / Math.log(1024))),
|
||||||
|
_s = Math.round(errorInfo.maxSize / Math.pow(1024, _i), 2);
|
||||||
|
|
||||||
|
errorText = 'Upload may not be larger than %1 %2.'.replace('%1', _s).replace('%2', _t[_i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
alert(errorText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
task.onComplete = function(fileInfo) {
|
||||||
|
eTask = undefined;
|
||||||
|
|
||||||
|
var elem = document.createElement('div');
|
||||||
|
elem.id = fileInfo.id;
|
||||||
|
|
||||||
|
var link = document.createElement('a');
|
||||||
|
link.textContent = fileInfo.id;
|
||||||
|
link.href = fileInfo.url;
|
||||||
|
link.target = '_blank';
|
||||||
|
elem.appendChild(link);
|
||||||
|
|
||||||
|
elem.appendChild(document.createTextNode(' '));
|
||||||
|
|
||||||
|
var del = document.createElement('button');
|
||||||
|
del.textContent = 'Delete';
|
||||||
|
del.onclick = function() {
|
||||||
|
var dTask = eClient.deleteUpload(fileInfo);
|
||||||
|
|
||||||
|
dTask.onFailure = function(reason) {
|
||||||
|
alert('Delete failed: ' + reason);
|
||||||
|
};
|
||||||
|
|
||||||
|
dTask.onSuccess = function() {
|
||||||
|
eHistory.removeChild(elem);
|
||||||
|
};
|
||||||
|
|
||||||
|
dTask.start();
|
||||||
|
};
|
||||||
|
elem.appendChild(del);
|
||||||
|
|
||||||
|
elem.appendChild(document.createTextNode(' '));
|
||||||
|
|
||||||
|
var json = document.createElement('code');
|
||||||
|
json.textContent = JSON.stringify(fileInfo);
|
||||||
|
elem.appendChild(json);
|
||||||
|
|
||||||
|
eHistory.appendChild(elem);
|
||||||
|
};
|
||||||
|
|
||||||
|
task.start();
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -13,6 +13,7 @@ define('PRM_DEBUG', is_file(PRM_ROOT . '/.debug'));
|
||||||
define('PRM_PUBLIC', PRM_ROOT . '/public');
|
define('PRM_PUBLIC', PRM_ROOT . '/public');
|
||||||
define('PRM_SOURCE', PRM_ROOT . '/src');
|
define('PRM_SOURCE', PRM_ROOT . '/src');
|
||||||
define('PRM_LIBRARY', PRM_ROOT . '/lib');
|
define('PRM_LIBRARY', PRM_ROOT . '/lib');
|
||||||
|
define('PRM_DEBUG_PAGES', PRM_ROOT . '/debug-pages');
|
||||||
define('PRM_UPLOADS', PRM_PUBLIC . '/data');
|
define('PRM_UPLOADS', PRM_PUBLIC . '/data');
|
||||||
define('PRM_THUMBS', PRM_PUBLIC . '/thumb');
|
define('PRM_THUMBS', PRM_PUBLIC . '/thumb');
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8a5423fea397e2f2adca0b9f46d1e5c21fd13c44
|
Subproject commit 9d99e10541cf8ba7407be0b53323cfa3ebfc37f5
|
542
public/index.php
542
public/index.php
|
@ -1,13 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
namespace EEPROM;
|
namespace EEPROM;
|
||||||
|
|
||||||
|
use Index\Http\HttpFx;
|
||||||
|
|
||||||
require_once __DIR__ . '/../eeprom.php';
|
require_once __DIR__ . '/../eeprom.php';
|
||||||
|
|
||||||
$reqMethod = $_SERVER['REQUEST_METHOD'];
|
|
||||||
$reqPath = '/' . trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
|
||||||
|
|
||||||
header('X-Powered-By: EEPROM');
|
|
||||||
|
|
||||||
function eepromOriginAllowed(string $origin): bool {
|
function eepromOriginAllowed(string $origin): bool {
|
||||||
$origin = mb_strtolower(parse_url($origin, PHP_URL_HOST));
|
$origin = mb_strtolower(parse_url($origin, PHP_URL_HOST));
|
||||||
|
|
||||||
|
@ -21,36 +18,39 @@ function eepromOriginAllowed(string $origin): bool {
|
||||||
return in_array($origin, $allowed);
|
return in_array($origin, $allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($_SERVER['HTTP_HOST'] !== Config::get('Uploads', 'api_domain')) {
|
$isApiDomain = $_SERVER['HTTP_HOST'] === Config::get('Uploads', 'api_domain');
|
||||||
$reqMethod = 'GET'; // short domain is read only, prevent deleting
|
$router = new HttpFx;
|
||||||
$reqPath = '/uploads/' . trim($reqPath, '/');
|
|
||||||
$isShortDomain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!empty($_SERVER['HTTP_ORIGIN'])) {
|
$router->use('/', function($response) {
|
||||||
if(!eepromOriginAllowed($_SERVER['HTTP_ORIGIN'])) {
|
$response->setPoweredBy('EEPROM');
|
||||||
http_response_code(403);
|
});
|
||||||
return;
|
|
||||||
|
$router->use('/', function($response, $request) {
|
||||||
|
$origin = $request->getHeaderLine('Origin');
|
||||||
|
|
||||||
|
if(!empty($origin)) {
|
||||||
|
if(!eepromOriginAllowed($origin))
|
||||||
|
return 403;
|
||||||
|
|
||||||
|
$response->setHeader('Access-Control-Allow-Origin', $origin);
|
||||||
|
$response->setHeader('Vary', 'Origin');
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
|
if($isApiDomain) {
|
||||||
header('Vary: Origin');
|
$router->use('/', function($response, $request) {
|
||||||
}
|
if($request->getMethod() === 'OPTIONS') {
|
||||||
|
$response->setHeader('Access-Control-Allow-Credentials', 'true');
|
||||||
if($reqMethod === 'OPTIONS') {
|
$response->setHeader('Access-Control-Allow-Headers', 'Authorization');
|
||||||
http_response_code(204);
|
$response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST, DELETE');
|
||||||
if(isset($isShortDomain))
|
return 204;
|
||||||
header('Access-Control-Allow-Methods: OPTIONS, GET');
|
|
||||||
else {
|
|
||||||
header('Access-Control-Allow-Credentials: true');
|
|
||||||
header('Access-Control-Allow-Headers: Authorization');
|
|
||||||
header('Access-Control-Allow-Methods: OPTIONS, GET, POST, DELETE');
|
|
||||||
}
|
}
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if(!isset($isShortDomain) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
$router->use('/', function($response, $request) use ($db) {
|
||||||
$authParts = explode(' ', $_SERVER['HTTP_AUTHORIZATION'], 2);
|
$auth = $request->getHeaderLine('Authorization');
|
||||||
|
if(!empty($auth)) {
|
||||||
|
$authParts = explode(' ', $auth, 2);
|
||||||
$authMethod = strval($authParts[0] ?? '');
|
$authMethod = strval($authParts[0] ?? '');
|
||||||
$authToken = strval($authParts[1] ?? '');
|
$authToken = strval($authParts[1] ?? '');
|
||||||
|
|
||||||
|
@ -66,230 +66,15 @@ if(!isset($isShortDomain) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||||
|
|
||||||
if(isset($authUserId) && $authUserId > 0)
|
if(isset($authUserId) && $authUserId > 0)
|
||||||
User::byId($db, $authUserId)->setActive();
|
User::byId($db, $authUserId)->setActive();
|
||||||
}
|
|
||||||
|
|
||||||
if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})(\.t)?/?$#', $reqPath, $matches)) {
|
|
||||||
$getNormal = empty($matches[2]);
|
|
||||||
$getThumbnail = isset($matches[2]) && $matches[2] === '.t';
|
|
||||||
|
|
||||||
try {
|
|
||||||
$uploadInfo = Upload::byId($db, $matches[1]);
|
|
||||||
} catch(UploadNotFoundException $ex) {
|
|
||||||
http_response_code(404);
|
|
||||||
echo 'File not found.';
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if($uploadInfo->isDMCA()) {
|
$router->get('/eeprom.js', function($response) {
|
||||||
http_response_code(451);
|
$response->accelRedirect('/js/eeprom-v1.0.js');
|
||||||
echo 'File is unavailable for copyright reasons.';
|
$response->setContentType('application/javascript; charset=utf-8');
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if($uploadInfo->isDeleted() || $uploadInfo->hasExpired()) {
|
$router->get('/stats.json', function() use ($db) {
|
||||||
http_response_code(404);
|
|
||||||
echo 'File not found.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($reqMethod === 'DELETE') {
|
|
||||||
if(!User::hasActive()) {
|
|
||||||
http_response_code(401);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(User::active()->isRestricted()
|
|
||||||
|| User::active()->getId() !== $uploadInfo->getUserId()) {
|
|
||||||
http_response_code(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
http_response_code(204);
|
|
||||||
$uploadInfo->delete($db, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_file($uploadInfo->getPath())) {
|
|
||||||
http_response_code(404);
|
|
||||||
echo 'Data is missing.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($getNormal) {
|
|
||||||
$uploadInfo->bumpAccess($db);
|
|
||||||
$uploadInfo->bumpExpiry($db);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileName = $uploadInfo->getName();
|
|
||||||
$contentType = $uploadInfo->getType();
|
|
||||||
|
|
||||||
if($contentType === 'application/octet-stream' || substr($contentType, 0, 5) === 'text/')
|
|
||||||
$contentType = 'text/plain';
|
|
||||||
|
|
||||||
$sourceDir = basename($getThumbnail ? PRM_THUMBS : PRM_UPLOADS);
|
|
||||||
|
|
||||||
if($getThumbnail && $uploadInfo->supportsThumbnail()) {
|
|
||||||
if(!is_file($uploadInfo->getThumbPath()))
|
|
||||||
$uploadInfo->createThumbnail();
|
|
||||||
$contentType = 'image/jpeg';
|
|
||||||
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '-thumb.jpg';
|
|
||||||
}
|
|
||||||
|
|
||||||
header(sprintf('X-Accel-Redirect: /%s/%s', $sourceDir, $uploadInfo->getId()));
|
|
||||||
header(sprintf('Content-Type: %s', $contentType));
|
|
||||||
header(sprintf('Content-Disposition: inline; filename="%s"', addslashes($fileName)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})\.json/?$#', $reqPath, $matches)) {
|
|
||||||
if(isset($isShortDomain)) {
|
|
||||||
http_response_code(404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$uploadInfo = Upload::byId($db, $matches[1]);
|
|
||||||
} catch(UploadNotFoundException $ex) {
|
|
||||||
http_response_code(404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode($uploadInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($reqPath === '/eeprom.js') {
|
|
||||||
header('Content-Type: application/javascript; charset=utf-8');
|
|
||||||
echo file_get_contents(PRM_ROOT . '/js/eeprom-v1.0.js');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($reqPath === '/test-v1.0.html' && PRM_DEBUG) {
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
|
||||||
|
|
||||||
$cookie = htmlspecialchars((string)filter_input(INPUT_COOKIE, 'msz_auth'));
|
|
||||||
|
|
||||||
echo <<<TEST
|
|
||||||
<!doctype html>
|
|
||||||
<input type="file" id="-eeprom-file"/> <button id="-eeprom-abort">Abort</button> <progress id="-eeprom-progress" min="0" max="100" value="0"></progress> <span id="-eeprom-progress-done"></span> <span id="-eeprom-progress-total"></span><br/>
|
|
||||||
<div id="-eeprom-history"></div>
|
|
||||||
<script src="/eeprom.js" type="text/javascript"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var eFile = document.getElementById('-eeprom-file'),
|
|
||||||
eAbort = document.getElementById('-eeprom-abort'),
|
|
||||||
eProgress = document.getElementById('-eeprom-progress'),
|
|
||||||
eProgressD = document.getElementById('-eeprom-progress-done'),
|
|
||||||
eProgressT = document.getElementById('-eeprom-progress-total'),
|
|
||||||
eHistory = document.getElementById('-eeprom-history'),
|
|
||||||
eTask = undefined;
|
|
||||||
|
|
||||||
eAbort.onclick = function() {
|
|
||||||
if(eTask)
|
|
||||||
eTask.abort();
|
|
||||||
};
|
|
||||||
|
|
||||||
var eClient = new EEPROM(1, '/uploads', 'Misuzu {$cookie}');
|
|
||||||
|
|
||||||
eFile.onchange = function() {
|
|
||||||
var task = eTask = eClient.createUpload(this.files[0]);
|
|
||||||
|
|
||||||
task.onProgress = function(progressInfo) {
|
|
||||||
eProgress.value = progressInfo.progress;
|
|
||||||
eProgressD.textContent = progressInfo.loaded;
|
|
||||||
eProgressT.textContent = progressInfo.total;
|
|
||||||
};
|
|
||||||
|
|
||||||
task.onFailure = function(errorInfo) {
|
|
||||||
if(!errorInfo.userAborted) {
|
|
||||||
var errorText = 'Was unable to upload file.';
|
|
||||||
|
|
||||||
switch(errorInfo.error) {
|
|
||||||
case EEPROM.ERR_INVALID:
|
|
||||||
errorText = 'Upload request was invalid.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_AUTH:
|
|
||||||
errorText = 'Upload authentication failed, refresh and try again.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_ACCESS:
|
|
||||||
errorText = 'You\'re not allowed to upload files.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_GONE:
|
|
||||||
errorText = 'Upload client has a configuration error or the server is gone.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_DMCA:
|
|
||||||
errorText = 'This file has been uploaded before and was removed for copyright reasons, you cannot upload this file.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_SERVER:
|
|
||||||
errorText = 'Upload server returned a critical error, try again later.';
|
|
||||||
break;
|
|
||||||
case EEPROM.ERR_SIZE:
|
|
||||||
if(errorInfo.maxSize < 1)
|
|
||||||
errorText = 'Selected file is too large.';
|
|
||||||
else {
|
|
||||||
var _t = ['bytes', 'KB', 'MB', 'GB', 'TB'],
|
|
||||||
_i = parseInt(Math.floor(Math.log(errorInfo.maxSize) / Math.log(1024))),
|
|
||||||
_s = Math.round(errorInfo.maxSize / Math.pow(1024, _i), 2);
|
|
||||||
|
|
||||||
errorText = 'Upload may not be larger than %1 %2.'.replace('%1', _s).replace('%2', _t[_i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
alert(errorText);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
task.onComplete = function(fileInfo) {
|
|
||||||
eTask = undefined;
|
|
||||||
|
|
||||||
var elem = document.createElement('div');
|
|
||||||
elem.id = fileInfo.id;
|
|
||||||
|
|
||||||
var link = document.createElement('a');
|
|
||||||
link.textContent = fileInfo.id;
|
|
||||||
link.href = fileInfo.url;
|
|
||||||
link.target = '_blank';
|
|
||||||
elem.appendChild(link);
|
|
||||||
|
|
||||||
elem.appendChild(document.createTextNode(' '));
|
|
||||||
|
|
||||||
var del = document.createElement('button');
|
|
||||||
del.textContent = 'Delete';
|
|
||||||
del.onclick = function() {
|
|
||||||
var dTask = eClient.deleteUpload(fileInfo);
|
|
||||||
|
|
||||||
dTask.onFailure = function(reason) {
|
|
||||||
alert('Delete failed: ' + reason);
|
|
||||||
};
|
|
||||||
|
|
||||||
dTask.onSuccess = function() {
|
|
||||||
eHistory.removeChild(elem);
|
|
||||||
};
|
|
||||||
|
|
||||||
dTask.start();
|
|
||||||
};
|
|
||||||
elem.appendChild(del);
|
|
||||||
|
|
||||||
elem.appendChild(document.createTextNode(' '));
|
|
||||||
|
|
||||||
var json = document.createElement('code');
|
|
||||||
json.textContent = JSON.stringify(fileInfo);
|
|
||||||
elem.appendChild(json);
|
|
||||||
|
|
||||||
eHistory.appendChild(elem);
|
|
||||||
};
|
|
||||||
|
|
||||||
task.start();
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
TEST;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: text/plain; charset=us-ascii');
|
|
||||||
|
|
||||||
if($reqPath === '/' || $reqPath === '/stats.json') {
|
|
||||||
$fileCount = 0;
|
$fileCount = 0;
|
||||||
$userCount = 0;
|
$userCount = 0;
|
||||||
$totalSize = 0;
|
$totalSize = 0;
|
||||||
|
@ -308,73 +93,64 @@ if($reqPath === '/' || $reqPath === '/stats.json') {
|
||||||
if($userStats->next())
|
if($userStats->next())
|
||||||
$userCount = $userStats->getInteger(0);
|
$userCount = $userStats->getInteger(0);
|
||||||
|
|
||||||
if($reqPath === '/stats.json') {
|
return [
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode([
|
|
||||||
'size' => $totalSize,
|
'size' => $totalSize,
|
||||||
'files' => $fileCount,
|
'files' => $fileCount,
|
||||||
'types' => $uniqueTypes,
|
'types' => $uniqueTypes,
|
||||||
'members' => $userCount,
|
'members' => $userCount,
|
||||||
]);
|
];
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
$router->get('/', function($response) {
|
||||||
header('X-Accel-Redirect: /index.html');
|
$response->accelRedirect('/index.html');
|
||||||
return;
|
$response->setContentType('text/html; charset=utf-8');
|
||||||
}
|
});
|
||||||
|
|
||||||
if($reqPath === '/uploads') {
|
$router->post('/uploads', function($response, $request) use ($db) {
|
||||||
if($reqMethod !== 'POST') {
|
if(!$request->isFormContent())
|
||||||
http_response_code(405);
|
return 400;
|
||||||
return;
|
|
||||||
}
|
$content = $request->getContent();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$appInfo = Application::byId($db, filter_input(INPUT_POST, 'src', FILTER_VALIDATE_INT));
|
$appInfo = Application::byId($db, (int)$content->getParam('src', FILTER_VALIDATE_INT));
|
||||||
} catch(ApplicationNotFoundException $ex) {
|
} catch(ApplicationNotFoundException $ex) {
|
||||||
http_response_code(404);
|
return 404;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!User::hasActive()) {
|
if(!User::hasActive())
|
||||||
http_response_code(401);
|
return 401;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$userInfo = User::active();
|
$userInfo = User::active();
|
||||||
|
|
||||||
if($userInfo->isRestricted()) {
|
if($userInfo->isRestricted())
|
||||||
http_response_code(403);
|
return 403;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(empty($_FILES['file']['tmp_name']) || !is_file($_FILES['file']['tmp_name'])) {
|
try {
|
||||||
http_response_code(400);
|
$file = $content->getUploadedFile('file');
|
||||||
return;
|
} catch(\RuntimeException $ex) {
|
||||||
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
$maxFileSize = $appInfo->getSizeLimit();
|
$maxFileSize = $appInfo->getSizeLimit();
|
||||||
if($appInfo->allowSizeMultiplier())
|
if($appInfo->allowSizeMultiplier())
|
||||||
$maxFileSize *= $userInfo->getSizeMultiplier();
|
$maxFileSize *= $userInfo->getSizeMultiplier();
|
||||||
|
|
||||||
$fileSize = filesize($_FILES['file']['tmp_name']);
|
$localFile = $file->getLocalFileName();
|
||||||
|
$fileSize = filesize($localFile);
|
||||||
|
|
||||||
if($_FILES['file']['size'] !== $fileSize || $fileSize > $maxFileSize) {
|
if($file->getSize() !== $fileSize || $fileSize > $maxFileSize) {
|
||||||
http_response_code(413);
|
$response->setHeader('Access-Control-Expose-Headers', 'X-EEPROM-Max-Size');
|
||||||
header('Access-Control-Expose-Headers: X-EEPROM-Max-Size');
|
$response->setHeader('X-EEPROM-Max-Size', $maxFileSize);
|
||||||
header('X-EEPROM-Max-Size: ' . $maxFileSize);
|
return 413;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash = hash_file('sha256', $_FILES['file']['tmp_name']);
|
$hash = hash_file('sha256', $localFile);
|
||||||
$fileInfo = Upload::byHash($db, $hash);
|
$fileInfo = Upload::byHash($db, $hash);
|
||||||
|
|
||||||
if($fileInfo !== null) {
|
if($fileInfo !== null) {
|
||||||
if($fileInfo->isDMCA()) {
|
if($fileInfo->isDMCA())
|
||||||
http_response_code(451);
|
return 451;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($fileInfo->getUserId() !== $userInfo->getId()
|
if($fileInfo->getUserId() !== $userInfo->getId()
|
||||||
|| $fileInfo->getApplicationId() !== $appInfo->getId())
|
|| $fileInfo->getApplicationId() !== $appInfo->getId())
|
||||||
|
@ -388,26 +164,186 @@ if($reqPath === '/uploads') {
|
||||||
try {
|
try {
|
||||||
$fileInfo = Upload::create(
|
$fileInfo = Upload::create(
|
||||||
$db, $appInfo, $userInfo,
|
$db, $appInfo, $userInfo,
|
||||||
$_FILES['file']['name'],
|
$file->getSuggestedFileName(),
|
||||||
mime_content_type($_FILES['file']['tmp_name']),
|
mime_content_type($localFile),
|
||||||
$fileSize, $hash,
|
$fileSize, $hash,
|
||||||
$appInfo->getExpiry(), true
|
$appInfo->getExpiry(), true
|
||||||
);
|
);
|
||||||
} catch(UploadCreationFailedException $ex) {
|
} catch(UploadCreationFailedException $ex) {
|
||||||
http_response_code(500);
|
return 500;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!move_uploaded_file($_FILES['file']['tmp_name'], $fileInfo->getPath())) {
|
try {
|
||||||
http_response_code(500);
|
$file->moveTo($fileInfo->getPath());
|
||||||
return;
|
} catch(\RuntimeException $ex) {
|
||||||
|
return 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
http_response_code(201);
|
$response->setStatusCode(201);
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
$response->setHeader('Content-Type', 'application/json; charset=utf-8');
|
||||||
echo json_encode($fileInfo);
|
return $fileInfo;
|
||||||
return;
|
});
|
||||||
|
|
||||||
|
$router->delete('/uploads/:fileid', function($response, $request, $fileId) use ($db) {
|
||||||
|
try {
|
||||||
|
$uploadInfo = Upload::byId($db, $fileId);
|
||||||
|
} catch(UploadNotFoundException $ex) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($uploadInfo->isDMCA()) {
|
||||||
|
$response->setContent('File is unavailable for copyright reasons.');
|
||||||
|
return 451;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($uploadInfo->isDeleted() || $uploadInfo->hasExpired()) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!User::hasActive())
|
||||||
|
return 401;
|
||||||
|
|
||||||
|
if(User::active()->isRestricted() || User::active()->getId() !== $uploadInfo->getUserId())
|
||||||
|
return 403;
|
||||||
|
|
||||||
|
$uploadInfo->delete($db, false);
|
||||||
|
return 204;
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/uploads/:filename', function($response, $request, $fileName) use ($db) {
|
||||||
|
$pathInfo = pathinfo($fileName);
|
||||||
|
$fileId = $pathInfo['filename'];
|
||||||
|
$fileExt = $pathInfo['extension'] ?? '';
|
||||||
|
$isThumbnail = $fileExt === 't';
|
||||||
|
$isJson = $fileExt === 'json';
|
||||||
|
|
||||||
|
if($fileExt !== '' && $fileExt !== 't' && $fileExt !== 'json')
|
||||||
|
return 404;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$uploadInfo = Upload::byId($db, $fileId);
|
||||||
|
} catch(UploadNotFoundException $ex) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($isJson)
|
||||||
|
return $uploadInfo;
|
||||||
|
|
||||||
|
if($uploadInfo->isDMCA()) {
|
||||||
|
$response->setContent('File is unavailable for copyright reasons.');
|
||||||
|
return 451;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($uploadInfo->isDeleted() || $uploadInfo->hasExpired()) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_file($uploadInfo->getPath())) {
|
||||||
|
$response->setContent('Data is missing.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$isThumbnail) {
|
||||||
|
$uploadInfo->bumpAccess($db);
|
||||||
|
$uploadInfo->bumpExpiry($db);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = $uploadInfo->getName();
|
||||||
|
$contentType = $uploadInfo->getType();
|
||||||
|
|
||||||
|
if($contentType === 'application/octet-stream' || str_starts_with($contentType, 'text/'))
|
||||||
|
$contentType = 'text/plain';
|
||||||
|
|
||||||
|
$sourceDir = basename($isThumbnail ? PRM_THUMBS : PRM_UPLOADS);
|
||||||
|
|
||||||
|
if($isThumbnail && $uploadInfo->supportsThumbnail()) {
|
||||||
|
if(!is_file($uploadInfo->getThumbPath()))
|
||||||
|
$uploadInfo->createThumbnail();
|
||||||
|
$contentType = 'image/jpeg';
|
||||||
|
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '-thumb.jpg';
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->accelRedirect(sprintf('/%s/%s', $sourceDir, $uploadInfo->getId()));
|
||||||
|
$response->setContentType($contentType);
|
||||||
|
$response->setFileName(addslashes($fileName));
|
||||||
|
});
|
||||||
|
|
||||||
|
if(PRM_DEBUG) {
|
||||||
|
$router->get('/test-v1.0.html', function($response) {
|
||||||
|
$response->setContentType('text/html; charset=utf-8');
|
||||||
|
return strtr(file_get_contents(PRM_DEBUG_PAGES . '/test-v1.0.html'), [
|
||||||
|
':cookie' => htmlspecialchars((string)filter_input(INPUT_COOKIE, 'msz_auth')),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$router->use('/', function($response, $request) {
|
||||||
|
if($request->getMethod() === 'OPTIONS') {
|
||||||
|
$response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/:filename', function($response, $request, $fileName) use ($db) {
|
||||||
|
$pathInfo = pathinfo($fileName);
|
||||||
|
$fileId = $pathInfo['filename'];
|
||||||
|
$fileExt = $pathInfo['extension'] ?? '';
|
||||||
|
$isThumbnail = $fileExt === 't';
|
||||||
|
|
||||||
|
if($fileExt !== '' && $fileExt !== 't')
|
||||||
|
return 404;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$uploadInfo = Upload::byId($db, $fileId);
|
||||||
|
} catch(UploadNotFoundException $ex) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($uploadInfo->isDMCA()) {
|
||||||
|
$response->setContent('File is unavailable for copyright reasons.');
|
||||||
|
return 451;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($uploadInfo->isDeleted() || $uploadInfo->hasExpired()) {
|
||||||
|
$response->setContent('File not found.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_file($uploadInfo->getPath())) {
|
||||||
|
$response->setContent('Data is missing.');
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$isThumbnail) {
|
||||||
|
$uploadInfo->bumpAccess($db);
|
||||||
|
$uploadInfo->bumpExpiry($db);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = $uploadInfo->getName();
|
||||||
|
$contentType = $uploadInfo->getType();
|
||||||
|
|
||||||
|
if($contentType === 'application/octet-stream' || str_starts_with($contentType, 'text/'))
|
||||||
|
$contentType = 'text/plain';
|
||||||
|
|
||||||
|
$sourceDir = basename($isThumbnail ? PRM_THUMBS : PRM_UPLOADS);
|
||||||
|
|
||||||
|
if($isThumbnail && $uploadInfo->supportsThumbnail()) {
|
||||||
|
if(!is_file($uploadInfo->getThumbPath()))
|
||||||
|
$uploadInfo->createThumbnail();
|
||||||
|
$contentType = 'image/jpeg';
|
||||||
|
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '-thumb.jpg';
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->accelRedirect(sprintf('/%s/%s', $sourceDir, $uploadInfo->getId()));
|
||||||
|
$response->setContentType($contentType);
|
||||||
|
$response->setFileName(addslashes($fileName));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
http_response_code(404);
|
$router->dispatch();
|
||||||
|
|
Loading…
Reference in a new issue