瀏覽代碼

Added support for sharex deletion url

Sergio Brighenti 6 年之前
父節點
當前提交
4b25b842b1

+ 8 - 0
CHANGELOG.md

@@ -1,3 +1,11 @@
+## v2.1
++ Improved theme style.
++ Improved page redirecting.
++ Allow e-mail login.
++ Support for ShareX deletion URL.
++ Fixed HTTP/2 push preload.
++ Added video.js support.
+
 ## v2.0
 + Migrated from Flight to Slim 3 framework.
 + Added install wizard (using the CLI is no longer required).

+ 55 - 4
app/Controllers/UploadController.php

@@ -83,7 +83,7 @@ class UploadController extends Controller
 	{
 		$media = $this->getMedia($args['userCode'], $args['mediaCode']);
 
-		if (!$media || !$media->published && Session::get('user_id') !== $media->user_id && !Session::get('admin', false)) {
+		if (!$media || (!$media->published && Session::get('user_id') !== $media->user_id && !Session::get('admin', false))) {
 			throw new NotFoundException($request, $response);
 		}
 
@@ -108,10 +108,11 @@ class UploadController extends Controller
 				}
 
 			} catch (FileNotFoundException $e) {
-				throw $e;
+				throw new NotFoundException($request, $response);
 			}
 
 			return $this->view->render($response, 'upload/public.twig', [
+				'delete_token' => isset($args['token']) ? $args['token'] : null,
 				'media' => $media,
 				'type' => $mime,
 				'extension' => pathinfo($media->filename, PATHINFO_EXTENSION),
@@ -119,6 +120,52 @@ class UploadController extends Controller
 		}
 	}
 
+	/**
+	 * @param Request $request
+	 * @param Response $response
+	 * @param $args
+	 * @return Response
+	 * @throws NotFoundException
+	 * @throws UnauthorizedException
+	 */
+	public function deleteByToken(Request $request, Response $response, $args): Response
+	{
+		$media = $this->getMedia($args['userCode'], $args['mediaCode']);
+
+		if (!$media) {
+			throw new NotFoundException($request, $response);
+		}
+
+		$user = $this->database->query('SELECT `id`, `active` FROM `users` WHERE `token` = ? LIMIT 1', $args['token'])->fetch();
+
+		if (!$user) {
+			Session::alert('Token specified not found.', 'danger');
+			return $response->withRedirect($request->getHeaderLine('HTTP_REFERER'));
+		}
+
+		if (!$user->active) {
+			Session::alert('Account disabled.', 'danger');
+			return $response->withRedirect($request->getHeaderLine('HTTP_REFERER'));
+		}
+
+		if (Session::get('admin', false) || $user->id === $media->user_id) {
+
+			$filesystem = $this->getStorage();
+			try {
+				$filesystem->delete($media->storage_path);
+			} catch (FileNotFoundException $e) {
+				throw new NotFoundException($request, $response);
+			} finally {
+				$this->database->query('DELETE FROM `uploads` WHERE `id` = ?', $media->mediaId);
+				$this->logger->info('User ' . $user->username . ' deleted a media via token.', [$media->mediaId]);
+			}
+		} else {
+			throw new UnauthorizedException();
+		}
+
+		return redirect($response, '/home');
+	}
+
 	/**
 	 * @param Request $request
 	 * @param Response $response
@@ -212,6 +259,10 @@ class UploadController extends Controller
 	{
 		$media = $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', $args['id'])->fetch();
 
+		if (!$media) {
+			throw new NotFoundException($request, $response);
+		}
+
 		if (Session::get('admin', false) || $media->user_id === Session::get('user_id')) {
 
 			$filesystem = $this->getStorage();
@@ -240,7 +291,7 @@ class UploadController extends Controller
 	{
 		$mediaCode = pathinfo($mediaCode)['filename'];
 
-		$media = $this->database->query('SELECT * FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_code` = ? AND `uploads`.`code` = ? LIMIT 1', [
+		$media = $this->database->query('SELECT `uploads`.*, `users`.*, `users`.`id` AS `userId`, `uploads`.`id` AS `mediaId` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_code` = ? AND `uploads`.`code` = ? LIMIT 1', [
 			$userCode,
 			$mediaCode,
 		])->fetch();
@@ -282,7 +333,7 @@ class UploadController extends Controller
 			ob_end_clean();
 			return $response
 				->withHeader('Content-Type', $mime)
-				->withHeader('Content-Disposition', $disposition . ';filename="' . $media->filename . '"')
+				->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"')
 				->withHeader('Content-Length', $storage->getSize($media->storage_path))
 				->withBody(new Stream($storage->readStream($media->storage_path)));
 		}

+ 1 - 1
app/Controllers/UserController.php

@@ -348,7 +348,7 @@ class UserController extends Controller
 			],
 			'URL' => '$json:url$',
 			'ThumbnailURL' => '$json:url$/raw',
-			'DeletionURL' => '$json:url$/delete',
+			'DeletionURL' => '$json:url$/delete/' . $user->token,
 		];
 
 		return $response

+ 2 - 0
app/routes.php

@@ -35,5 +35,7 @@ $app->map(['GET', 'POST'], '/logout', \App\Controllers\LoginController::class .
 $app->post('/upload', \App\Controllers\UploadController::class . ':upload');
 
 $app->get('/{userCode}/{mediaCode}', \App\Controllers\UploadController::class . ':show');
+$app->get('/{userCode}/{mediaCode}/delete/{token}', \App\Controllers\UploadController::class . ':show');
+$app->post('/{userCode}/{mediaCode}/delete/{token}', \App\Controllers\UploadController::class . ':deleteByToken');
 $app->get('/{userCode}/{mediaCode}/raw', \App\Controllers\UploadController::class . ':showRaw');
 $app->get('/{userCode}/{mediaCode}/download', \App\Controllers\UploadController::class . ':download');

+ 4 - 1
bootstrap/app.php

@@ -27,9 +27,12 @@ $config = array_replace_recursive([
 		'username' => null,
 		'password' => null,
 	],
-	'routerCacheFile' => __DIR__ . '/../resources/cache/routes.cache.php',
 ], require __DIR__ . '/../config.php');
 
+if (!$config['displayErrorDetails']) {
+	$config['routerCacheFile'] = __DIR__ . '/../resources/cache/routes.cache.php';
+}
+
 $container = new Container(['settings' => $config]);
 
 $container['logger'] = function ($container) {

+ 1 - 1
composer.json

@@ -1,6 +1,6 @@
 {
   "name": "sergix44/xbackbone",
-  "version": "2.0",
+  "version": "2.1",
   "description": "A lightweight ShareX PHP backend",
   "type": "project",
   "require": {

+ 2 - 1
package.json

@@ -1,12 +1,13 @@
 {
   "dependencies": {
+    "@fortawesome/fontawesome-free": "^5.4.1",
     "bootstrap": "^4.1.3",
     "clipboard": "^2.0.1",
     "highlightjs": "^9.10.0",
     "jquery": "^3.3.1",
     "popper.js": "^1.14.4",
     "tooltip.js": "^1.3.0",
-    "@fortawesome/fontawesome-free": "^5.4.1"
+    "video.js": "^7.3.0"
   },
   "devDependencies": {
     "grunt": "^1.0",

+ 19 - 5
resources/templates/upload/public.twig

@@ -23,8 +23,20 @@
         </div>
     </nav>
     <div class="container-fluid">
+        {% include 'comp/alert.twig' %}
         <div class="row ml-auto mr-auto">
             <div class="col-md-12 justify-content-center">
+                {% if delete_token is not null %}
+                    <form method="post" action="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}/delete/{{ delete_token }}">
+                        <div class="text-center mb-4">
+                            <p>Are you sure you want to delete this item? It will be gone <b>forever</b>!</p>
+                            <div class="btn-group">
+                                <button type="submit" class="btn btn-danger"><i class="fas fa-trash"></i> Yes</button>
+                                <a href="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}" class="btn btn-secondary">No</a>
+                            </div>
+                        </div>
+                    </form>
+                {% endif %}
                 {% if type starts with 'image' %}
                     <div class="row mb-2">
                         <div class="col-md-12">
@@ -48,11 +60,13 @@
                         </div>
                     </div>
                 {% elseif type starts with 'video' %}
-                    <video width="100%"  class="video-js" controls preload="auto">
-                        <source src="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}/raw" type="{{ type }}">
-                        Your browser does not support HTML5 video.
-                        <a href="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
-                    </video>
+                    <div class="video-content">
+                        <video class="video-js vjs-fluid vjs-big-play-centered" data-setup='{"controls": true, "autoplay": true, "preload": "auto"}'>
+                            <source src="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}/raw" type="{{ type }}">
+                            Your browser does not support HTML5 video.
+                            <a href="{{ config.base_url }}/{{ media.user_code }}/{{ media.code }}.{{ extension }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
+                        </video>
+                    </div>
                 {% else %}
                     <div class="text-center">
                         <div class="row mb-2">

+ 6 - 0
src/css/app.css

@@ -60,4 +60,10 @@ body {
     height: 40px;
     line-height: 40px;
     text-align: right;
+}
+
+.video-content {
+    width: 80%;
+    margin-right: auto;
+    margin-left: auto;
 }