Skip to content

Commit

Permalink
SA-CORE-2021-008 by klausi, xjm, larowlan, alexpott, samuel.mortenson…
Browse files Browse the repository at this point in the history
…, mcdruid, kim.pepper
  • Loading branch information
xjm committed Sep 14, 2021
1 parent 280194a commit d34d38a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 9 deletions.
29 changes: 25 additions & 4 deletions core/modules/file/src/Plugin/rest/resource/FileUploadResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,28 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) {
$file->setMimeType($this->mimeTypeGuesser->guess($prepared_filename));
@trigger_error('\Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Implement \Symfony\Component\Mime\MimeTypeGuesserInterface instead. See https://www.drupal.org/node/3133341', E_USER_DEPRECATED);
}
$file->setFileUri($file_uri);
$file->setFileUri($temp_file_path);
// Set the size. This is done in File::preSave() but we validate the file
// before it is saved.
$file->setSize(@filesize($temp_file_path));

// Validate the file entity against entity-level validation and field-level
// validators.
$this->validate($file, $validators);
// Validate the file against field-level validators first while the file is
// still a temporary file. Validation is split up in 2 steps to be the same
// as in _file_save_upload_single().
// For backwards compatibility this part is copied from ::validate() to
// leave that method behavior unchanged.
// @todo Improve this with a file uploader service in
// https://www.drupal.org/project/drupal/issues/2940383
$errors = file_validate($file, $validators);

if (!empty($errors)) {
$message = "Unprocessable Entity: file validation failed.\n";
$message .= implode("\n", array_map([PlainTextOutput::class, 'renderFromHtml'], $errors));

throw new UnprocessableEntityHttpException($message);
}

$file->setFileUri($file_uri);
// Move the file to the correct location after validation. Use
// FileSystemInterface::EXISTS_ERROR as the file location has already been
// determined above in FileSystem::getDestinationFilename().
Expand All @@ -297,6 +310,9 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) {
throw new HttpException(500, 'Temporary file could not be moved to file location');
}

// Second step of the validation on the file object itself now.
$this->resourceValidate($file);

$file->save();

$this->lock->release($lock_id);
Expand Down Expand Up @@ -449,6 +465,11 @@ protected function validateAndLoadFieldDefinition($entity_type_id, $bundle, $fie
/**
* Validates the file.
*
* @todo this method is unused in this class because file validation needs to
* be split up in 2 steps in ::post(). Add a deprecation notice as soon as a
* central core file upload service can be used in this class.
* See https://www.drupal.org/project/drupal/issues/2940383
*
* @param \Drupal\file\FileInterface $file
* The file entity to validate.
* @param array $validators
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\Token;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Entity\EntityConstraintViolationList;
use Drupal\file\Entity\File;
use Drupal\file\Plugin\Field\FieldType\FileFieldItemList;
use Psr\Log\LoggerInterface;
Expand Down Expand Up @@ -195,18 +196,37 @@ public function handleFileUploadForField(FieldDefinitionInterface $field_definit
@trigger_error('\Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Implement \Symfony\Component\Mime\MimeTypeGuesserInterface instead. See https://www.drupal.org/node/3133341', E_USER_DEPRECATED);
$file->setMimeType($this->mimeTypeGuesser->guess($prepared_filename));
}
$file->setFileUri($file_uri);
$file->setFileUri($temp_file_path);
// Set the size. This is done in File::preSave() but we validate the file
// before it is saved.
$file->setSize(@filesize($temp_file_path));

// Validate the file entity against entity-level validation and field-level
// validators.
$violations = $this->validate($file, $validators);
if ($violations->count() > 0) {
// Validate the file against field-level validators first while the file is
// still a temporary file. Validation is split up in 2 steps to be the same
// as in _file_save_upload_single().
// For backwards compatibility this part is copied from ::validate() to
// leave that method behavior unchanged.
// @todo Improve this with a file uploader service in
// https://www.drupal.org/project/drupal/issues/2940383
$errors = file_validate($file, $validators);
if (!empty($errors)) {
$violations = new EntityConstraintViolationList($file);
$translator = new DrupalTranslator();
$entity = EntityAdapter::createFromEntity($file);
foreach ($errors as $error) {
$violation = new ConstraintViolation($translator->trans($error),
$error,
[],
$entity,
'',
NULL
);
$violations->add($violation);
}
return $violations;
}

$file->setFileUri($file_uri);
// Move the file to the correct location after validation. Use
// FileSystemInterface::EXISTS_ERROR as the file location has already been
// determined above in FileSystem::getDestinationFilename().
Expand All @@ -217,6 +237,16 @@ public function handleFileUploadForField(FieldDefinitionInterface $field_definit
throw new HttpException(500, 'Temporary file could not be moved to file location');
}

// Second step of the validation on the file object itself now.
$violations = $file->validate();

// Remove violations of inaccessible fields as they cannot stem from our
// changes.
$violations->filterByFieldAccess();
if ($violations->count() > 0) {
return $violations;
}

$file->save();

$this->lock->release($lock_id);
Expand Down Expand Up @@ -355,6 +385,11 @@ protected function streamUploadData() {
/**
* Validates the file.
*
* @todo this method is unused in this class because file validation needs to
* be split up in 2 steps in ::handleFileUploadForField(). Add a deprecation
* notice as soon as a central core file upload service can be used in this
* class. See https://www.drupal.org/project/drupal/issues/2940383
*
* @param \Drupal\file\FileInterface $file
* The file entity to validate.
* @param array $validators
Expand Down

0 comments on commit d34d38a

Please sign in to comment.