mirror of
https://github.com/flarum/framework.git
synced 2024-11-26 18:33:40 +08:00
Validate PSR-compatible file upload
Instead of converting the uploaded file object to an UploadedFile instance from Symfony, because the latter is compatible with Laravel's validation, let's re-implement the validation for the three rules we were using. The benefit: we can now avoid copying the uploaded file to a temporary location just to do the wrapping. In the next step, we will remove the temporary file and let the uploader / Intervention Image handle the PSR stream directly.
This commit is contained in:
parent
085d3cdba6
commit
46ec54d52d
|
@ -10,14 +10,76 @@
|
|||
namespace Flarum\User;
|
||||
|
||||
use Flarum\Foundation\AbstractValidator;
|
||||
use Flarum\Foundation\ValidationException;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Symfony\Component\Mime\MimeTypes;
|
||||
|
||||
class AvatarValidator extends AbstractValidator
|
||||
{
|
||||
protected $rules = [
|
||||
'avatar' => [
|
||||
'required',
|
||||
'mimes:jpeg,png,bmp,gif',
|
||||
'max:2048'
|
||||
]
|
||||
];
|
||||
/**
|
||||
* Throw an exception if a model is not valid.
|
||||
*
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function assertValid(array $attributes)
|
||||
{
|
||||
$this->assertFileRequired($attributes['avatar']);
|
||||
$this->assertFileMimes($attributes['avatar']);
|
||||
$this->assertFileSize($attributes['avatar']);
|
||||
}
|
||||
|
||||
protected function assertFileRequired(UploadedFileInterface $file)
|
||||
{
|
||||
if ($file->getError() !== UPLOAD_ERR_OK) {
|
||||
$this->raise('required');
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertFileMimes(UploadedFileInterface $file)
|
||||
{
|
||||
$allowedTypes = $this->getAllowedTypes();
|
||||
|
||||
// Block PHP files masquerading as images
|
||||
$phpExtensions = ['php', 'php3', 'php4', 'php5', 'phtml'];
|
||||
$fileExtension = pathinfo($file->getClientFilename(), PATHINFO_EXTENSION);
|
||||
|
||||
if (in_array(trim(strtolower($fileExtension)), $phpExtensions)) {
|
||||
$this->raise('mimes', [':values' => implode(', ', $allowedTypes)]);
|
||||
}
|
||||
|
||||
$guessedExtension = MimeTypes::getDefault()->getExtensions($file->getClientMediaType())[0] ?? null;
|
||||
|
||||
if (! in_array($guessedExtension, $allowedTypes)) {
|
||||
$this->raise('mimes', [':values' => implode(', ', $allowedTypes)]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertFileSize(UploadedFileInterface $file)
|
||||
{
|
||||
$maxSize = $this->getMaxSize();
|
||||
|
||||
if ($file->getSize() / 1024 > $maxSize) {
|
||||
$this->raise('max.file', [':max' => $maxSize]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function raise($error, array $parameters = [])
|
||||
{
|
||||
$message = $this->translator->trans(
|
||||
"validation.$error",
|
||||
$parameters + [':attribute' => 'avatar']
|
||||
);
|
||||
|
||||
throw new ValidationException(['avatar' => $message]);
|
||||
}
|
||||
|
||||
protected function getMaxSize()
|
||||
{
|
||||
return 2048;
|
||||
}
|
||||
|
||||
protected function getAllowedTypes()
|
||||
{
|
||||
return ['jpeg', 'png', 'bmp', 'gif'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ use Flarum\User\Event\AvatarSaving;
|
|||
use Flarum\User\UserRepository;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Intervention\Image\ImageManager;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
class UploadAvatarHandler
|
||||
{
|
||||
|
@ -65,6 +64,7 @@ class UploadAvatarHandler
|
|||
* @param UploadAvatar $command
|
||||
* @return \Flarum\User\User
|
||||
* @throws \Flarum\User\Exception\PermissionDeniedException
|
||||
* @throws \Flarum\Foundation\ValidationException
|
||||
*/
|
||||
public function handle(UploadAvatar $command)
|
||||
{
|
||||
|
@ -82,15 +82,6 @@ class UploadAvatarHandler
|
|||
$file->moveTo($tmpFile);
|
||||
|
||||
try {
|
||||
$file = new UploadedFile(
|
||||
$tmpFile,
|
||||
$file->getClientFilename(),
|
||||
$file->getClientMediaType(),
|
||||
$file->getSize(),
|
||||
$file->getError(),
|
||||
true
|
||||
);
|
||||
|
||||
$this->validator->assertValid(['avatar' => $file]);
|
||||
|
||||
$image = (new ImageManager)->make($tmpFile);
|
||||
|
|
Loading…
Reference in New Issue
Block a user