diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 0484e44dd6..f136985529 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -35,16 +35,6 @@ // cspell:ignore abiword -/** - * The regex pattern used when checking for insecure file types. - * - * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use - * \Drupal\Core\File\FileSystemInterface::INSECURE_EXTENSION_REGEX. - * - * @see https://www.drupal.org/node/3032541 - */ -define('FILE_INSECURE_EXTENSION_REGEX', FileSystemInterface::INSECURE_EXTENSION_REGEX); - // Load all Field module hooks for File. require_once __DIR__ . '/file.field.inc'; @@ -723,252 +713,6 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL return isset($delta) ? $files[$delta] : $files; } -/** - * Saves a file upload to a new location. - * - * @param \SplFileInfo $file_info - * The file upload to save. - * @param string $form_field_name - * A string that is the associative array key of the upload form element in - * the form array. - * @param array $validators - * (optional) An associative array of callback functions used to validate the - * file. - * @param bool $destination - * (optional) A string containing the URI that the file should be copied to. - * @param int $replace - * (optional) The replace behavior when the destination file already exists. - * - * @return \Drupal\file\FileInterface|false - * The created file entity or FALSE if the uploaded file not saved. - * - * @throws \Drupal\Core\Entity\EntityStorageException - * - * @internal - * This method should only be called from file_save_upload(). Use that method - * instead. - * - * @deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use - * \Drupal\file\Upload\FileUploadHandler::handleFileUpload() instead. - * - * @see https://www.drupal.org/node/3239547 - * @see file_save_upload() - */ -function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $validators = [], $destination = FALSE, $replace = FileSystemInterface::EXISTS_REPLACE) { - @trigger_error(__METHOD__ . '() is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Use \Drupal\file\Upload\FileUploadHandler::handleFileUpload() instead. See https://www.drupal.org/node/3239547', E_USER_DEPRECATED); - $user = \Drupal::currentUser(); - // Remember the original filename so we can print a message if it changes. - $original_file_name = $file_info->getClientOriginalName(); - // Check for file upload errors and return FALSE for this file if a lower - // level system error occurred. For a complete list of errors: - // See http://php.net/manual/features.file-upload.errors.php. - switch ($file_info->getError()) { - case UPLOAD_ERR_INI_SIZE: - case UPLOAD_ERR_FORM_SIZE: - \Drupal::messenger()->addError(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', ['%file' => $original_file_name, '%maxsize' => format_size(Environment::getUploadMaxSize())])); - return FALSE; - - case UPLOAD_ERR_PARTIAL: - case UPLOAD_ERR_NO_FILE: - \Drupal::messenger()->addError(t('The file %file could not be saved because the upload did not complete.', ['%file' => $original_file_name])); - return FALSE; - - case UPLOAD_ERR_OK: - // Final check that this is a valid upload, if it isn't, use the - // default error handler. - if (is_uploaded_file($file_info->getRealPath())) { - break; - } - - default: - // Unknown error - \Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $original_file_name])); - return FALSE; - - } - - // Build a list of allowed extensions. - $extensions = ''; - if (isset($validators['file_validate_extensions'])) { - if (isset($validators['file_validate_extensions'][0])) { - // Build the list of non-munged extensions if the caller provided them. - $extensions = $validators['file_validate_extensions'][0]; - } - else { - // If 'file_validate_extensions' is set and the list is empty then the - // caller wants to allow any extension. In this case we have to remove the - // validator or else it will reject all extensions. - unset($validators['file_validate_extensions']); - } - } - else { - // No validator was provided, so add one using the default list. - // Build a default non-munged safe list for - // \Drupal\system\EventSubscriber\SecurityFileUploadEventSubscriber::sanitizeName(). - $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'; - $validators['file_validate_extensions'] = []; - $validators['file_validate_extensions'][0] = $extensions; - } - - // If the destination is not provided, use the temporary directory. - if (empty($destination)) { - $destination = 'temporary://'; - } - - /** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager */ - $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager'); - - // Assert that the destination contains a valid stream. - $destination_scheme = $stream_wrapper_manager::getScheme($destination); - if (!$stream_wrapper_manager->isValidScheme($destination_scheme)) { - \Drupal::messenger()->addError(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination])); - return FALSE; - } - - // A file URI may already have a trailing slash or look like "public://". - if (substr($destination, -1) != '/') { - $destination .= '/'; - } - - // Call an event to sanitize the filename and to attempt to address security - // issues caused by common server setups. - $event = new FileUploadSanitizeNameEvent($original_file_name, $extensions); - \Drupal::service('event_dispatcher')->dispatch($event); - - // Begin building the file entity. - $values = [ - 'uid' => $user->id(), - 'status' => 0, - // This will be replaced later with a filename based on the destination. - 'filename' => $event->getFilename(), - 'uri' => $file_info->getRealPath(), - 'filesize' => $file_info->getSize(), - ]; - $file = File::create($values); - - /** @var \Drupal\Core\File\FileSystemInterface $file_system */ - $file_system = \Drupal::service('file_system'); - try { - // Use the result of the sanitization event as the destination name. - $file->destination = $file_system->getDestinationFilename($destination . $event->getFilename(), $replace); - } - catch (FileException $e) { - \Drupal::messenger()->addError(t('The file %filename could not be uploaded because the name is invalid.', ['%filename' => $file->getFilename()])); - return FALSE; - } - - $guesser = \Drupal::service('file.mime_type.guesser'); - $file->setMimeType($guesser->guessMimeType($values['filename'])); - $file->source = $form_field_name; - - // If the destination is FALSE then $replace === FILE_EXISTS_ERROR and - // there's an existing file, so we need to bail. - if ($file->destination === FALSE) { - \Drupal::messenger()->addError(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', ['%source' => $form_field_name, '%directory' => $destination])); - return FALSE; - } - - // Add in our check of the file name length. - $validators['file_validate_name_length'] = []; - - // Call the validation functions specified by this function's caller. - $errors = file_validate($file, $validators); - - // Check for errors. - if (!empty($errors)) { - $message = [ - 'error' => [ - '#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()]), - ], - 'item_list' => [ - '#theme' => 'item_list', - '#items' => $errors, - ], - ]; - // @todo Add support for render arrays in - // \Drupal\Core\Messenger\MessengerInterface::addMessage()? - // @see https://www.drupal.org/node/2505497. - \Drupal::messenger()->addError(\Drupal::service('renderer')->renderPlain($message)); - return FALSE; - } - - $file->setFileUri($file->destination); - if (!$file_system->moveUploadedFile($file_info->getRealPath(), $file->getFileUri())) { - \Drupal::messenger()->addError(t('File upload error. Could not move uploaded file.')); - \Drupal::logger('file')->notice('Upload error. Could not move uploaded file %file to destination %destination.', ['%file' => $file->getFilename(), '%destination' => $file->getFileUri()]); - return FALSE; - } - - // Update the filename with any changes as a result of the renaming due to an - // existing file. - $file->setFilename(\Drupal::service('file_system')->basename($file->destination)); - - // If the filename has been modified, let the user know. - if ($file->getFilename() !== $original_file_name) { - if ($event->isSecurityRename()) { - $message = t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]); - } - else { - $message = t('Your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]); - } - \Drupal::messenger()->addStatus($message); - } - - // Set the permissions on the new file. - $file_system->chmod($file->getFileUri()); - - // If we are replacing an existing file re-use its database record. - // @todo Do not create a new entity in order to update it. See - // https://www.drupal.org/node/2241865. - if ($replace == FileSystemInterface::EXISTS_REPLACE) { - $existing_files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $file->getFileUri()]); - if (count($existing_files)) { - $existing = reset($existing_files); - $file->fid = $existing->id(); - $file->setOriginalId($existing->id()); - } - } - - // Update the filename with any changes as a result of security or renaming - // due to an existing file. - $file->setFilename(\Drupal::service('file_system')->basename($file->destination)); - - // We can now validate the file object itself before it's saved. - $violations = $file->validate(); - foreach ($violations as $violation) { - $errors[] = $violation->getMessage(); - } - if (!empty($errors)) { - $message = [ - 'error' => [ - '#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()]), - ], - 'item_list' => [ - '#theme' => 'item_list', - '#items' => $errors, - ], - ]; - // @todo Add support for render arrays in - // \Drupal\Core\Messenger\MessengerInterface::addMessage()? - // @see https://www.drupal.org/node/2505497. - \Drupal::messenger()->addError(\Drupal::service('renderer')->renderPlain($message)); - return FALSE; - } - - // If we made it this far it's safe to record this file in the database. - $file->save(); - - // Allow an anonymous user who creates a non-public file to see it. See - // \Drupal\file\FileAccessControlHandler::checkAccess(). - if ($user->isAnonymous() && $destination_scheme !== 'public') { - $session = \Drupal::request()->getSession(); - $allowed_temp_files = $session->get('anonymous_allowed_file_ids', []); - $allowed_temp_files[$file->id()] = $file->id(); - $session->set('anonymous_allowed_file_ids', $allowed_temp_files); - } - return $file; -} - /** * Determines the preferred upload progress implementation. *