diff --git a/Gruntfile.js b/Gruntfile.js index 9369716..a9ec167 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -95,6 +95,12 @@ module.exports = function (grunt) { src: ['styles/**/*', 'highlight.pack.min.js'], dest: 'static/highlightjs' }, + { + expand: true, + cwd: 'node_modules/dropzone/dist/min', + src: ['dropzone.min.css', 'dropzone.min.js'], + dest: 'static/dropzone' + }, {expand: true, cwd: 'node_modules/jquery/dist', src: ['jquery.min.js'], dest: 'static/jquery'} ], }, diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 0976a5f..2ed0f3e 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -59,7 +59,7 @@ class DashboardController extends Controller return view()->render( $response, - ($this->session->get('admin', false) && $this->session->get('gallery_view', true)) ? 'dashboard/admin.twig' : 'dashboard/home.twig', + ($this->session->get('admin', false) && $this->session->get('gallery_view', true)) ? 'dashboard/list.twig' : 'dashboard/grid.twig', [ 'medias' => $query->getMedia(), 'next' => $page < floor($query->getPages()), diff --git a/app/Controllers/UploadController.php b/app/Controllers/UploadController.php index 38dd0c7..bb46e8c 100644 --- a/app/Controllers/UploadController.php +++ b/app/Controllers/UploadController.php @@ -16,6 +16,28 @@ use Slim\Exception\HttpUnauthorizedException; class UploadController extends Controller { + /** + * @param Request $request + * @param Response $response + * @return Response + * @throws \Twig\Error\LoaderError + * @throws \Twig\Error\RuntimeError + * @throws \Twig\Error\SyntaxError + */ + public function webUpload(Request $request, Response $response): Response + { + $user = $this->database->query('SELECT * FROM `users` WHERE `id` = ? LIMIT 1', $this->session->get('user_id'))->fetch(); + + if ($user->token === null || $user->token === '') { + $this->session->alert(lang('no_upload_token'), 'danger'); + return redirect($response, $request->getHeaderLine('Referer')); + } + + return view()->render($response, 'upload/web.twig', [ + 'user' => $user, + ]); + } + /** * @param Request $request * @param Response $response @@ -24,7 +46,6 @@ class UploadController extends Controller */ public function upload(Request $request, Response $response): Response { - $json = [ 'message' => null, 'version' => PLATFORM_VERSION, @@ -40,7 +61,16 @@ class UploadController extends Controller return json($response, $json, 400); } - if (isset($request->getUploadedFiles()['upload']) && $request->getUploadedFiles()['upload']->getError() === UPLOAD_ERR_INI_SIZE) { + $file = array_values($request->getUploadedFiles()); + /** @var \Psr\Http\Message\UploadedFileInterface|null $file */ + $file = isset($file[0]) ? $file[0] : null; + + if ($file === null) { + $json['message'] = 'Request without file attached.'; + return json($response, $json, 400); + } + + if ($file->getError() === UPLOAD_ERR_INI_SIZE) { $json['message'] = 'File too large (upload_max_filesize too low?).'; return json($response, $json, 400); } @@ -66,9 +96,6 @@ class UploadController extends Controller $code = humanRandomString(); } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `code` = ?', $code)->fetch()->count > 0); - /** @var \Psr\Http\Message\UploadedFileInterface $file */ - $file = $request->getUploadedFiles()['upload']; - $fileInfo = pathinfo($file->getClientFilename()); $storagePath = "$user->user_code/$code.$fileInfo[extension]"; @@ -169,12 +196,12 @@ class UploadController extends Controller if (!$user) { $this->session->alert(lang('token_not_found'), 'danger'); - return redirect($response, $request->getHeaderLine('HTTP_REFERER')); + return redirect($response, $request->getHeaderLine('Referer')); } if (!$user->active) { $this->session->alert(lang('account_disabled'), 'danger'); - return redirect($response, $request->getHeaderLine('HTTP_REFERER')); + return redirect($response, $request->getHeaderLine('Referer')); } if ($this->session->get('admin', false) || $user->id === $media->user_id) { @@ -232,7 +259,7 @@ class UploadController extends Controller throw new HttpNotFoundException($request); } - if($ext !== null && pathinfo($media->filename, PATHINFO_EXTENSION) !== $ext){ + if ($ext !== null && pathinfo($media->filename, PATHINFO_EXTENSION) !== $ext) { throw new HttpBadRequestException($request); } diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php index dba503d..8a77ffd 100644 --- a/app/Controllers/UserController.php +++ b/app/Controllers/UserController.php @@ -358,8 +358,8 @@ class UserController extends Controller } if ($user->token === null || $user->token === '') { - $this->session->alert('You don\'t have a personal upload token. (Click the update token button and try again)', 'danger'); - return redirect($response, $request->getHeaderLine('HTTP_REFERER')); + $this->session->alert(lang('no_upload_token'), 'danger'); + return redirect($response, $request->getHeaderLine('Referer')); } $json = [ @@ -404,8 +404,8 @@ class UserController extends Controller } if ($user->token === null || $user->token === '') { - $this->session->alert('You don\'t have a personal upload token. (Click the update token button and try again)', 'danger'); - return redirect($response, $request->getHeaderLine('HTTP_REFERER')); + $this->session->alert(lang('no_upload_token'), 'danger'); + return redirect($response, $request->getHeaderLine('Referer')); } return view()->render($response->withHeader('Content-Disposition', 'attachment;filename="xbackbone_uploader_'.$user->username.'.sh"'), diff --git a/app/routes.php b/app/routes.php index 6b63d9a..b084391 100644 --- a/app/routes.php +++ b/app/routes.php @@ -15,6 +15,7 @@ use Slim\Routing\RouteCollectorProxy; global $app; $app->group('', function (RouteCollectorProxy $group) { $group->get('/home[/page/{page}]', [DashboardController::class, 'home'])->setName('home'); + $group->get('/upload', [UploadController::class, 'webUpload'])->setName('upload.web'); $group->group('', function (RouteCollectorProxy $group) { $group->get('/home/switchView', [DashboardController::class, 'switchView'])->setName('switchView'); diff --git a/composer.lock b/composer.lock index 3d3bf30..539b4d0 100644 --- a/composer.lock +++ b/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "content-hash": "a5d4341b89b81518c0e488cd3bc47127", @@ -1862,15 +1862,15 @@ "authors": [ { "name": "Freek Van der Herten", + "role": "Developer", "email": "freek@spatie.be", - "homepage": "https://spatie.be", - "role": "Developer" + "homepage": "https://spatie.be" }, { "name": "Alex Vanderbist", + "role": "Developer", "email": "alex.vanderbist@gmail.com", - "homepage": "https://spatie.be", - "role": "Developer" + "homepage": "https://spatie.be" } ], "description": "A minimal implementation of Dropbox API v2", diff --git a/install/index.php b/install/index.php index f5c745e..d72cdcb 100644 --- a/install/index.php +++ b/install/index.php @@ -257,7 +257,7 @@ $app->post('/', function (Request $request, Response $response, Filesystem $stor cleanDirectory(__DIR__.'/../resources/cache'); cleanDirectory(__DIR__.'/../resources/sessions'); - removeDirectory(__DIR__.'/../install'); + //removeDirectory(__DIR__.'/../install'); // if is upgrading and existing installation, put it out maintenance if ($installed) { diff --git a/package-lock.json b/package-lock.json index 8128818..f92e725 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,9 +3,9 @@ "lockfileVersion": 1, "dependencies": { "@fortawesome/fontawesome-free": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.10.2.tgz", - "integrity": "sha512-9pw+Nsnunl9unstGEHQ+u41wBEQue6XPBsILXtJF/4fNN1L3avJcMF/gGF86rIjeTAgfLjTY9ndm68/X4f4idQ==" + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.11.2.tgz", + "integrity": "sha512-XiUPoS79r1G7PcpnNtq85TJ7inJWe0v+b5oZJZKb0pGHNIV6+UiNeQWiFGmuQ0aj7GEhnD/v9iqxIsjuRKtEnQ==" }, "abbrev": { "version": "1.1.1", @@ -359,6 +359,11 @@ "domelementtype": "1" } }, + "dropzone": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.5.1.tgz", + "integrity": "sha512-3VduRWLxx9hbVr42QieQN25mx/I61/mRdUSuxAmDGdDqZIN8qtP7tcKMa3KfpJjuGjOJGYYUzzeq6eGDnkzesA==" + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -744,9 +749,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -863,9 +868,9 @@ "dev": true }, "highlightjs": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/highlightjs/-/highlightjs-9.12.0.tgz", - "integrity": "sha512-eAhWMtDZaOZIQdxIP4UEB1vNp/CVXQPdMSihTSuaExhFIRC0BVpXbtP3mTP1hDoGOyh7nbB3cuC3sOPhG5wGDA==" + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/highlightjs/-/highlightjs-9.16.2.tgz", + "integrity": "sha512-FK1vmMj8BbEipEy8DLIvp71t5UsC7n2D6En/UfM/91PCwmOpj6f2iu0Y0coRC62KSRHHC+dquM2xMULV/X7NFg==" }, "hooker": { "version": "0.2.3", @@ -1043,9 +1048,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "loud-rejection": { @@ -1347,9 +1352,9 @@ } }, "popper.js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz", - "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==" + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.0.tgz", + "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==" }, "pretty-bytes": { "version": "3.0.1", @@ -1616,9 +1621,9 @@ } }, "tooltip.js": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/tooltip.js/-/tooltip.js-1.3.2.tgz", - "integrity": "sha512-DeDr9JxYx/lSvQ53ZCRFLxXrmrSyU3fLz6k+ITUTw69AIYtpWij/NmOJQscJ7BwY5lcEwWJWSfqqQWVvTMYZiw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tooltip.js/-/tooltip.js-1.3.3.tgz", + "integrity": "sha512-XWWuy/dBdF/F/YpRE955yqBZ4VdLfiTAUdOqoU+wJm6phJlMpEzl/iYHZ+qJswbeT9VG822bNfsETF9wzmoy5A==", "requires": { "popper.js": "^1.0.2" } diff --git a/package.json b/package.json index 4acab13..1025a71 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "dependencies": { - "@fortawesome/fontawesome-free": "^5.10.2", + "@fortawesome/fontawesome-free": "^5.11.2", "bootstrap": "^4.3.1", "clipboard": "^2.0.4", - "highlightjs": "^9.12.0", + "dropzone": "^5.5.1", + "highlightjs": "^9.16.2", "jquery": "^3.4.1", "plyr": "^3.5.6", - "popper.js": "^1.15.0", - "tooltip.js": "^1.3.2" + "popper.js": "^1.16.0", + "tooltip.js": "^1.3.3" }, "devDependencies": { "grunt": "^1.0.4", diff --git a/resources/lang/en.lang.php b/resources/lang/en.lang.php index a4cc596..e736e14 100644 --- a/resources/lang/en.lang.php +++ b/resources/lang/en.lang.php @@ -28,6 +28,7 @@ return [ 'date' => 'Date', 'raw' => 'Show raw', 'download' => 'Download', + 'upload' => 'Upload', 'delete' => 'Delete', 'publish' => 'Publish', 'hide' => 'Hide', @@ -99,4 +100,5 @@ return [ 'default_lang_behavior' => 'XBackBone will try to match the browser language by default (the fallback is English).', 'lang_set' => 'System language enforced to "%s"', 'prerelease_channel' => 'Prerelease Channel', + 'no_upload_token' => 'You don\'t have a personal upload token. (Generate one and try again)', ]; diff --git a/resources/lang/it.lang.php b/resources/lang/it.lang.php index 738e36a..a2aaf0f 100644 --- a/resources/lang/it.lang.php +++ b/resources/lang/it.lang.php @@ -27,6 +27,7 @@ return [ 'date' => 'Data', 'raw' => 'Vedi raw', 'download' => 'Scarica', + 'upload' => 'Carica', 'delete' => 'Elimina', 'publish' => 'Pubblica', 'hide' => 'Nascondi', @@ -99,4 +100,5 @@ return [ 'default_lang_behavior' => 'Per impostazione predefinita, XBackbone cercherà di abbinare la lingua del browser (il fallback è l\'Inglese).', 'lang_set' => 'Lingua di sistema applicata a "%s"', 'prerelease_channel' => 'Canale prerelease', + 'no_upload_token' => 'Non hai un token personale per l\'upload associato. (Generane uno e riprova)', ]; diff --git a/resources/templates/base.twig b/resources/templates/base.twig index 0804873..79f5215 100644 --- a/resources/templates/base.twig +++ b/resources/templates/base.twig @@ -17,6 +17,7 @@ + {% block head %}{% endblock %} @@ -35,6 +36,7 @@ + diff --git a/resources/templates/comp/navbar.twig b/resources/templates/comp/navbar.twig index 0831779..d9ed9e1 100644 --- a/resources/templates/comp/navbar.twig +++ b/resources/templates/comp/navbar.twig @@ -11,6 +11,11 @@ {{ lang('home') }} + {% if session.admin %}