UploadController.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /*
  3. * @copyright Copyright (c) 2019 Sergio Brighenti <sergio@brighenti.me>
  4. *
  5. * @author Sergio Brighenti <sergio@brighenti.me>
  6. *
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. */
  21. namespace App\Controllers;
  22. use League\Flysystem\FileExistsException;
  23. use Psr\Http\Message\ResponseInterface as Response;
  24. use Psr\Http\Message\ServerRequestInterface as Request;
  25. class UploadController extends Controller
  26. {
  27. /**
  28. * @param Request $request
  29. * @param Response $response
  30. *
  31. * @throws \Twig\Error\RuntimeError
  32. * @throws \Twig\Error\SyntaxError
  33. * @throws \Twig\Error\LoaderError
  34. *
  35. * @return Response
  36. */
  37. public function webUpload(Request $request, Response $response): Response
  38. {
  39. $user = $this->database->query('SELECT * FROM `users` WHERE `id` = ? LIMIT 1', $this->session->get('user_id'))->fetch();
  40. if ($user->token === null || $user->token === '') {
  41. $this->session->alert(lang('no_upload_token'), 'danger');
  42. return redirect($response, $request->getHeaderLine('Referer'));
  43. }
  44. return view()->render($response, 'upload/web.twig', array(
  45. 'user' => $user,
  46. ));
  47. }
  48. /**
  49. * @param Request $request
  50. * @param Response $response
  51. *
  52. * @throws FileExistsException
  53. *
  54. * @return Response
  55. */
  56. public function upload(Request $request, Response $response): Response
  57. {
  58. $json = array(
  59. 'message' => null,
  60. 'version' => PLATFORM_VERSION,
  61. );
  62. if ($this->config['maintenance']) {
  63. $json['message'] = 'Endpoint under maintenance.';
  64. return json($response, $json, 503);
  65. }
  66. if ($request->getServerParams()['CONTENT_LENGTH'] > stringToBytes(ini_get('post_max_size'))) {
  67. $json['message'] = 'File too large (post_max_size too low?).';
  68. return json($response, $json, 400);
  69. }
  70. $file = array_values($request->getUploadedFiles());
  71. /** @var \Psr\Http\Message\UploadedFileInterface|null $file */
  72. $file = isset($file[0]) ? $file[0] : null;
  73. if ($file === null) {
  74. $json['message'] = 'Request without file attached.';
  75. return json($response, $json, 400);
  76. }
  77. if ($file->getError() === UPLOAD_ERR_INI_SIZE) {
  78. $json['message'] = 'File too large (upload_max_filesize too low?).';
  79. return json($response, $json, 400);
  80. }
  81. if (param($request, 'token') === null) {
  82. $json['message'] = 'Token not specified.';
  83. return json($response, $json, 400);
  84. }
  85. $user = $this->database->query('SELECT * FROM `users` WHERE `token` = ? LIMIT 1', param($request, 'token'))->fetch();
  86. if (!$user) {
  87. $json['message'] = 'Token specified not found.';
  88. return json($response, $json, 404);
  89. }
  90. if (!$user->active) {
  91. $json['message'] = 'Account disabled.';
  92. return json($response, $json, 401);
  93. }
  94. do {
  95. $code = humanRandomString();
  96. } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `code` = ?', $code)->fetch()->count > 0);
  97. $fileInfo = pathinfo($file->getClientFilename());
  98. $storagePath = "$user->user_code/$code.$fileInfo[extension]";
  99. $this->storage->writeStream($storagePath, $file->getStream()->detach());
  100. $this->database->query('INSERT INTO `uploads`(`user_id`, `code`, `filename`, `storage_path`) VALUES (?, ?, ?, ?)', array(
  101. $user->id,
  102. $code,
  103. $file->getClientFilename(),
  104. $storagePath,
  105. ));
  106. $json['message'] = 'OK.';
  107. $json['url'] = urlFor("/{$user->user_code}/{$code}.{$fileInfo['extension']}");
  108. $this->logger->info("User $user->username uploaded new media.", array($this->database->getPdo()->lastInsertId()));
  109. return json($response, $json, 201);
  110. }
  111. }