diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 2c89147..b79b66d 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -842,7 +842,28 @@ function file_save_upload($form_field_name, $validators = array(), $destination if (substr($destination, -1) != '/') { $destination .= '/'; } - $file->destination = file_destination($destination . $file->getFilename(), $replace); + + // If the transliteration option is enabled, transliterate the filename. + if (\Drupal::config('system.file')->get('filename_transliteration')) { + $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId(); + + // Transliterate and sanitize the destination filename. + $filename = \Drupal::transliteration()->transliterate($file->getFilename(), $langcode, ''); + + // Replace whitespace. + $filename = str_replace(' ', '_', $filename); + // Remove remaining unsafe characters. + $filename = preg_replace('![^0-9A-Za-z_.-]!', '', $filename); + // Remove multiple consecutive non-alphabetical characters. + $filename = preg_replace('/(_)_+|(\.)\.+|(-)-+/', '\\1\\2\\3', $filename); + // Force lowercase to prevent issues on case-insensitive file systems. + $filename = Unicode::strtolower($filename); + } + else { + $filename = $file->getFilename(); + } + + $file->destination = file_destination($destination . $filename, $replace); // If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and // there's an existing file so we need to bail. if ($file->destination === FALSE) { diff --git a/core/modules/system/config/install/system.file.yml b/core/modules/system/config/install/system.file.yml index ec8c053..73b6fd7 100644 --- a/core/modules/system/config/install/system.file.yml +++ b/core/modules/system/config/install/system.file.yml @@ -3,3 +3,4 @@ default_scheme: 'public' path: temporary: '' temporary_maximum_age: 21600 +filename_transliteration: false diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index e34d375..cd47f4d 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -282,6 +282,9 @@ system.file: temporary_maximum_age: type: integer label: 'Maximum age for temporary files' + filename_transliteration: + type: boolean + label: 'Transliterate names of uploaded files' system.image: type: config_object diff --git a/core/modules/system/src/Form/FileSystemForm.php b/core/modules/system/src/Form/FileSystemForm.php index 9271bf4..b4610a8 100644 --- a/core/modules/system/src/Form/FileSystemForm.php +++ b/core/modules/system/src/Form/FileSystemForm.php @@ -131,6 +131,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => t('Orphaned files are not referenced from any content but remain in the file system and may appear in administrative listings. Warning: If enabled, orphaned files will be permanently deleted and may not be recoverable.'), ); + $form['filename_transliteration'] = array( + '#type' => 'checkbox', + '#title' => t('Enable filename transliteration'), + '#default_value' => $config->get('filename_transliteration'), + '#description' => t('Check if transliteration should be enabled for uploaded filenames.'), + ); + return parent::buildForm($form, $form_state); } @@ -140,7 +147,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { public function submitForm(array &$form, FormStateInterface $form_state) { $config = $this->config('system.file') ->set('path.temporary', $form_state->getValue('file_temporary_path')) - ->set('temporary_maximum_age', $form_state->getValue('temporary_maximum_age')); + ->set('temporary_maximum_age', $form_state->getValue('temporary_maximum_age')) + ->set('filename_transliteration', $form_state->getValue('filename_transliteration')); if ($form_state->hasValue('file_default_scheme')) { $config->set('default_scheme', $form_state->getValue('file_default_scheme'));