2
0
Fork 0
forked from flashii/eeprom

Attempt at fixing bogus 'File not found' errors.

This commit is contained in:
flash 2023-11-07 21:33:46 +00:00
parent 7ae79a012b
commit c546bf6da8
4 changed files with 57 additions and 49 deletions

View file

@ -1,6 +1,7 @@
<?php <?php
namespace EEPROM; namespace EEPROM;
use RuntimeException;
use Index\Http\HttpFx; use Index\Http\HttpFx;
require_once __DIR__ . '/../eeprom.php'; require_once __DIR__ . '/../eeprom.php';
@ -139,7 +140,7 @@ if($isApiDomain) {
try { try {
$appInfo = Application::byId($db, (int)$content->getParam('src', FILTER_VALIDATE_INT)); $appInfo = Application::byId($db, (int)$content->getParam('src', FILTER_VALIDATE_INT));
} catch(ApplicationNotFoundException $ex) { } catch(RuntimeException $ex) {
return 404; return 404;
} }
@ -153,7 +154,7 @@ if($isApiDomain) {
try { try {
$file = $content->getUploadedFile('file'); $file = $content->getUploadedFile('file');
} catch(\RuntimeException $ex) { } catch(RuntimeException $ex) {
return 400; return 400;
} }
@ -171,7 +172,9 @@ if($isApiDomain) {
} }
$hash = hash_file('sha256', $localFile); $hash = hash_file('sha256', $localFile);
$fileInfo = Upload::byHash($db, $hash);
// this is stupid: dmca status is stored as a file record rather than in a separate table requiring this hack ass garbage
$fileInfo = Upload::byUserHash($db, $userInfo, $hash) ?? Upload::byHash($db, $hash);
if($fileInfo !== null) { if($fileInfo !== null) {
if($fileInfo->isDMCA()) if($fileInfo->isDMCA())
@ -185,26 +188,17 @@ if($isApiDomain) {
if(!empty($fileInfo)) { if(!empty($fileInfo)) {
if($fileInfo->isDeleted()) if($fileInfo->isDeleted())
$fileInfo->restore($db); $fileInfo->restore($db);
$fileInfo->bumpExpiry($db);
} else { } else {
try { $fileInfo = Upload::create(
$fileInfo = Upload::create( $db, $appInfo, $userInfo,
$db, $appInfo, $userInfo, $file->getSuggestedFileName(),
$file->getSuggestedFileName(), mime_content_type($localFile),
mime_content_type($localFile), $fileSize, $hash,
$fileSize, $hash, $appInfo->getExpiry(), true
$appInfo->getExpiry(), true );
);
} catch(UploadCreationFailedException $ex) {
\Sentry\captureException($ex);
return 500;
}
try { $file->moveTo($fileInfo->getPath());
$file->moveTo($fileInfo->getPath());
} catch(\RuntimeException $ex) {
\Sentry\captureException($ex);
return 500;
}
} }
$response->setStatusCode(201); $response->setStatusCode(201);
@ -215,7 +209,7 @@ if($isApiDomain) {
$router->delete('/uploads/:fileid', function($response, $request, $fileId) use ($db) { $router->delete('/uploads/:fileid', function($response, $request, $fileId) use ($db) {
try { try {
$uploadInfo = Upload::byId($db, $fileId); $uploadInfo = Upload::byId($db, $fileId);
} catch(UploadNotFoundException $ex) { } catch(RuntimeException $ex) {
$response->setContent('File not found.'); $response->setContent('File not found.');
return 404; return 404;
} }
@ -252,7 +246,7 @@ if($isApiDomain) {
try { try {
$uploadInfo = Upload::byId($db, $fileId); $uploadInfo = Upload::byId($db, $fileId);
} catch(UploadNotFoundException $ex) { } catch(RuntimeException $ex) {
$response->setContent('File not found.'); $response->setContent('File not found.');
return 404; return 404;
} }
@ -318,7 +312,7 @@ if($isApiDomain) {
try { try {
$uploadInfo = Upload::byId($db, $fileId); $uploadInfo = Upload::byId($db, $fileId);
} catch(UploadNotFoundException $ex) { } catch(RuntimeException $ex) {
$response->setContent('File not found.'); $response->setContent('File not found.');
return 404; return 404;
} }

View file

@ -1,13 +1,11 @@
<?php <?php
namespace EEPROM; namespace EEPROM;
use Exception; use RuntimeException;
use JsonSerializable; use JsonSerializable;
use Index\Data\IDbConnection; use Index\Data\IDbConnection;
use Index\Data\DbType; use Index\Data\DbType;
class ApplicationNotFoundException extends Exception {}
final class Application implements JsonSerializable { final class Application implements JsonSerializable {
public function __construct( public function __construct(
private int $id = 0, private int $id = 0,
@ -54,9 +52,6 @@ final class Application implements JsonSerializable {
} }
public static function byId(IDbConnection $conn, int $appId): self { public static function byId(IDbConnection $conn, int $appId): self {
if($appId < 1)
throw new ApplicationNotFoundException;
$get = $conn->prepare( $get = $conn->prepare(
'SELECT `app_id`, `app_name`, `app_size_limit`, `app_expiry`, `app_allow_size_multiplier`,' 'SELECT `app_id`, `app_name`, `app_size_limit`, `app_expiry`, `app_allow_size_multiplier`,'
. ' UNIX_TIMESTAMP(`app_created`) AS `app_created` FROM `prm_applications` WHERE `app_id` = ?' . ' UNIX_TIMESTAMP(`app_created`) AS `app_created` FROM `prm_applications` WHERE `app_id` = ?'
@ -66,7 +61,7 @@ final class Application implements JsonSerializable {
$result = $get->getResult(); $result = $get->getResult();
if(!$result->next()) if(!$result->next())
throw new ApplicationNotFoundException; throw new RuntimeException('Application $appId not found.');
return new static( return new static(
$result->getInteger(0), $result->getInteger(0),

View file

@ -2,15 +2,14 @@
namespace EEPROM; namespace EEPROM;
use Exception; use Exception;
use InvalidArgumentException;
use RuntimeException;
use Imagick; use Imagick;
use JsonSerializable; use JsonSerializable;
use Index\Data\IDbConnection; use Index\Data\IDbConnection;
use Index\Data\IDbResult; use Index\Data\IDbResult;
use Index\Data\DbType; use Index\Data\DbType;
class UploadNotFoundException extends Exception {};
class UploadCreationFailedException extends Exception {};
final class Upload implements JsonSerializable { final class Upload implements JsonSerializable {
private const ID_CHARS = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789-_'; private const ID_CHARS = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789-_';
@ -216,8 +215,14 @@ final class Upload implements JsonSerializable {
$appId = $app->getId(); $appId = $app->getId();
$userId = $user->getId(); $userId = $user->getId();
if(strpos($fileType, '/') === false || $fileSize < 1 || strlen($fileHash) !== 64 || $fileExpiry < 0) if(strpos($fileType, '/') === false)
throw new UploadCreationFailedException('Bad args.'); throw new InvalidArgumentException('$fileType must contain a /');
if($fileSize < 1)
throw new InvalidArgumentException('$fileSize must be more than 0.');
if(strlen($fileHash) !== 64)
throw new InvalidArgumentException('$fileHash must be 64 characters.');
if($fileExpiry < 0)
throw new InvalidArgumentException('$fileExpiry must be a positive integer.');
$id = self::generateId(); $id = self::generateId();
$create = $conn->prepare( $create = $conn->prepare(
@ -239,11 +244,7 @@ final class Upload implements JsonSerializable {
$create->addParameter(10, $bumpExpiry ? $fileExpiry : 0, DbType::INTEGER); $create->addParameter(10, $bumpExpiry ? $fileExpiry : 0, DbType::INTEGER);
$create->execute(); $create->execute();
try { return self::byId($conn, $id);
return self::byId($conn, $id);
} catch(UploadNotFoundException $ex) {
throw new UploadCreationFailedException;
}
} }
private static function constructDb(IDbResult $result): self { private static function constructDb(IDbResult $result): self {
@ -282,7 +283,7 @@ final class Upload implements JsonSerializable {
$result = $get->getResult(); $result = $get->getResult();
if(!$result->next()) if(!$result->next())
throw new UploadNotFoundException; throw new RuntimeException('Upload $id not found.');
return self::constructDb($result); return self::constructDb($result);
} }
@ -309,6 +310,29 @@ final class Upload implements JsonSerializable {
return self::constructDb($result); return self::constructDb($result);
} }
public static function byUserHash(IDbConnection $conn, User|string $userInfo, string $hash): ?self {
$get = $conn->prepare(
'SELECT `upload_id`, `app_id`, `user_id`, `upload_name`, `upload_type`, `upload_size`, `upload_bump`,'
. ' UNIX_TIMESTAMP(`upload_created`) AS `upload_created`,'
. ' UNIX_TIMESTAMP(`upload_accessed`) AS `upload_accessed`,'
. ' UNIX_TIMESTAMP(`upload_expires`) AS `upload_expires`,'
. ' UNIX_TIMESTAMP(`upload_deleted`) AS `upload_deleted`,'
. ' UNIX_TIMESTAMP(`upload_dmca`) AS `upload_dmca`,'
. ' INET6_NTOA(`upload_ip`) AS `upload_ip`,'
. ' LOWER(HEX(`upload_hash`)) AS `upload_hash`'
. ' FROM `prm_uploads` WHERE `upload_hash` = UNHEX(?) AND `user_id` = ?'
);
$get->addParameter(1, $hash, DbType::STRING);
$get->addParameter(2, $userInfo instanceof User ? $userInfo->getId() : $userInfo);
$get->execute();
$result = $get->getResult();
if(!$result->next())
return null;
return self::constructDb($result);
}
public static function deleted(IDbConnection $conn): array { public static function deleted(IDbConnection $conn): array {
$result = $conn->query( $result = $conn->query(
'SELECT `upload_id`, `app_id`, `user_id`, `upload_name`, `upload_type`, `upload_size`, `upload_bump`,' 'SELECT `upload_id`, `app_id`, `user_id`, `upload_name`, `upload_type`, `upload_size`, `upload_bump`,'

View file

@ -1,13 +1,11 @@
<?php <?php
namespace EEPROM; namespace EEPROM;
use Exception; use RuntimeException;
use JsonSerializable; use JsonSerializable;
use Index\Data\IDbConnection; use Index\Data\IDbConnection;
use Index\Data\DbType; use Index\Data\DbType;
class UserNotFoundException extends Exception {}
class User implements JsonSerializable { class User implements JsonSerializable {
private static $active; private static $active;
@ -63,9 +61,6 @@ class User implements JsonSerializable {
} }
public static function byId(IDbConnection $conn, int $userId): self { public static function byId(IDbConnection $conn, int $userId): self {
if($userId < 1)
throw new UserNotFoundException;
$create = $conn->prepare('INSERT IGNORE INTO `prm_users` (`user_id`) VALUES (?)'); $create = $conn->prepare('INSERT IGNORE INTO `prm_users` (`user_id`) VALUES (?)');
$create->addParameter(1, $userId, DbType::INTEGER); $create->addParameter(1, $userId, DbType::INTEGER);
$create->execute(); $create->execute();
@ -79,7 +74,7 @@ class User implements JsonSerializable {
$result = $get->getResult(); $result = $get->getResult();
if(!$result->next()) if(!$result->next())
throw new UserNotFoundException; throw new RuntimeException('User not found.');
return new User( return new User(
$result->getInteger(0), $result->getInteger(0),