diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2747591 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/Tests/ export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/.gitignore b/.gitignore index a18580d..b35aa4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,13 @@ +.DS_Store +.build .idea/ /out/ +vendor/ .idea_modules/ atlassian-ide-plugin.xml com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties +composer.lock composer.phar -/vendor/ diff --git a/Classes/Hooks/DataHandlerHook.php b/Classes/Hooks/DataHandlerHook.php new file mode 100644 index 0000000..be9ad6e --- /dev/null +++ b/Classes/Hooks/DataHandlerHook.php @@ -0,0 +1,44 @@ +isSvgFile($filename)) { + $svgService->sanitizeSvgFile($filename); + } + } +} diff --git a/Classes/Hooks/GeneralUtilityHook.php b/Classes/Hooks/GeneralUtilityHook.php new file mode 100644 index 0000000..44f1854 --- /dev/null +++ b/Classes/Hooks/GeneralUtilityHook.php @@ -0,0 +1,49 @@ +isSvgFile($filename)) { + $svgService->sanitizeSvgFile($filename); + } + } +} diff --git a/Classes/Service/SvgSanitizerService.php b/Classes/Service/SvgSanitizerService.php new file mode 100644 index 0000000..80af18f --- /dev/null +++ b/Classes/Service/SvgSanitizerService.php @@ -0,0 +1,72 @@ +getMimeType(), ['image/svg+xml', 'application/svg+xml'], true); + } + + /** + * @param string $fileNameAndPath + * @param string $outputFileNameAndPath + * @throws \BadFunctionCallException + */ + public function sanitizeSvgFile($fileNameAndPath, $outputFileNameAndPath = null) + { + if ($outputFileNameAndPath === null) { + $outputFileNameAndPath = $fileNameAndPath; + } + $dirtySVG = file_get_contents($fileNameAndPath); + $cleanSVG = $this->sanitizeAndReturnSvgContent($dirtySVG); + if ($cleanSVG !== $dirtySVG) { + file_put_contents($outputFileNameAndPath, $cleanSVG); + } + } + + /** + * @param string $dirtySVG + * + * @return string + * @throws \BadFunctionCallException + */ + public function sanitizeAndReturnSvgContent($dirtySVG) + { + $extensionBasePath = ExtensionManagementUtility::extPath('svg_sanitizer'); + if (!class_exists(Sanitizer::class)) { + @include 'phar://' . $extensionBasePath . 'Libraries/enshrined-svg-sanitize.phar/vendor/autoload.php'; + } + $sanitizer = new Sanitizer(); + $sanitizer->removeRemoteReferences(true); + return $sanitizer->sanitize($dirtySVG); + } +} diff --git a/Classes/Service/UpdateService.php b/Classes/Service/UpdateService.php new file mode 100644 index 0000000..774371e --- /dev/null +++ b/Classes/Service/UpdateService.php @@ -0,0 +1,56 @@ +getQueryBuilderForTable('sys_file_storage'); + $rows = $queryBuilder + ->select('uid') + ->from('sys_file_storage') + ->where($queryBuilder->expr()->eq('is_writable', 1)) + ->execute() + ->fetchAll(); + + $resourceFactory = ResourceFactory::getInstance(); + foreach ($rows as $row) { + $filter = GeneralUtility::makeInstance(FileExtensionFilter::class); + $filter->setAllowedFileExtensions(['svg']); + + $storage = $resourceFactory->getStorageObject((int)$row['uid']); + $storage->setFileAndFolderNameFilters([[$filter, 'filterFileList']]); + $files = $storage->getFilesInFolder($storage->getRootLevelFolder(), 0, 0, true, true); + + $svgSanitizerService = GeneralUtility::makeInstance(SvgSanitizerService::class); + foreach ($files as $file) { + $oldFileContent = $file->getContents(); + $newFileContent = $svgSanitizerService->sanitizeAndReturnSvgContent($oldFileContent); + if ($oldFileContent !== $newFileContent) { + $file->setContents($newFileContent); + } + } + } + return true; + } +} diff --git a/Classes/SignalSlot/ResourceStorage.php b/Classes/SignalSlot/ResourceStorage.php new file mode 100644 index 0000000..467f65c --- /dev/null +++ b/Classes/SignalSlot/ResourceStorage.php @@ -0,0 +1,78 @@ +isSvgFile($sourceFilePath)) { + $svgService->sanitizeSvgFile($sourceFilePath); + } + } + + /** + * @param FileInterface $file + * @param string $localFilePath + * + * @throws \InvalidArgumentException + */ + public function preFileReplace($file, $localFilePath) + { + $svgService = GeneralUtility::makeInstance(SvgSanitizerService::class); + if ($svgService->isSvgFile($localFilePath)) { + $svgService->sanitizeSvgFile($localFilePath); + } + } + + /** + * @param FileInterface $file + * @param string $content + * + * @throws \InvalidArgumentException + */ + public function postFileSetContents($file, $content) + { + $svgService = GeneralUtility::makeInstance(SvgSanitizerService::class); + if ($svgService->isSvgFile($file->getForLocalProcessing(false))) { + $newContent = $svgService->sanitizeAndReturnSvgContent($content); + // prevent endless loop because this hook is called again and again and again and... + if ($newContent !== $content) { + $file->setContents($newContent); + } + } + } +} diff --git a/Classes/Updates/v8/SanitizeExistingSVG.php b/Classes/Updates/v8/SanitizeExistingSVG.php new file mode 100644 index 0000000..38af7ab --- /dev/null +++ b/Classes/Updates/v8/SanitizeExistingSVG.php @@ -0,0 +1,103 @@ +isWizardDone()) { + return false; + } + return true; + } + + /** + * Second step: Ask user to sanitize existing SVG files + * + * @param string $inputPrefix input prefix, all names of form fields have to start with this. Append custom name in [ ... ] + * @return string HTML output + */ + public function getUserInput($inputPrefix) + { + $markup = []; + $markup[] = '
'; + $markup[] = '
Are you really sure?
'; + $markup[] = '
'; + $markup[] = '

This upgrade wizard will sanitize all SVG file in the fileadmin folder.

'; + $markup[] = '

This means that the content of your SVG files will be changed. This automatic process can break your SVG files.

'; + $markup[] = '

PLEASE: Create a backup of your SVG files, before starting this wizard!

'; + $markup[] = '

Are you really sure, you want to do this now?

'; + $markup[] = '
'; + $markup[] = ' '; + $markup[] = ' '; + $markup[] = '
'; + $markup[] = '
'; + $markup[] = '
'; + return implode(LF, $markup); + } + + /** + * Performs the update + * + * @param array &$databaseQueries Queries done in this update + * @param string &$customMessage Custom message + * + * @return bool + * @throws \RuntimeException + * @throws \InvalidArgumentException + */ + public function performUpdate(array &$databaseQueries, &$customMessage) + { + $requestParams = GeneralUtility::_GP('install'); + if (!isset($requestParams['values']['T3G\SvgSanitizer\Updates\SanitizeExistingSVG']['sanitize'])) { + return false; + } + $sanitize = (int)$requestParams['values']['T3G\SvgSanitizer\Updates\SanitizeExistingSVG']['sanitize']; + + if ($sanitize === 1) { + GeneralUtility::makeInstance(UpdateService::class)->executeUpdate(); + } + + // Mark v9 upgrade wizard also as done (bad hack, but required) + GeneralUtility::makeInstance(Registry::class)->set('installUpdate', 'T3G\SvgSanitizer\Updates\v9\SanitizeExistingSVG', 1); + $this->markWizardAsDone(); + return true; + } +} diff --git a/Classes/Updates/v9/SanitizeExistingSVG.php b/Classes/Updates/v9/SanitizeExistingSVG.php new file mode 100644 index 0000000..e5ad716 --- /dev/null +++ b/Classes/Updates/v9/SanitizeExistingSVG.php @@ -0,0 +1,125 @@ +confirmation = new Confirmation( + 'Are you really sure?', + $this->getDescription(), + false, + 'yes, please sanitize', + 'no, don\'t sanitize', + false + ); + } + + /** + * Return the identifier for this wizard + * This should be the same string as used in the ext_localconf class registration + * + * @return string + */ + public function getIdentifier(): string + { + // this is the origin class name to prevent trouble with class renaming + return 'T3G\SvgSanitizer\Updates\SanitizeExistingSVG'; + } + + /** + * Return the speaking name of this wizard + * + * @return string + */ + public function getTitle(): string + { + return '[EXT:svg_sanitizer] Scan and sanitize existing SVG files in fileadmin folder'; + } + + /** + * Return the description for this wizard + * + * @return string + */ + public function getDescription(): string + { + return 'This upgrade wizard will sanitize all SVG file in the fileadmin folder.' + . ' This means that the content of your SVG files will be changed. This automatic process can break your SVG files.' + . ' PLEASE: Create a backup of your SVG files, before starting this wizard!' + . ' Are you really sure, you want to do this now?'; + } + + /** + * Is an update necessary? + * + * Is used to determine whether a wizard needs to be run. + * Check if data for migration exists. + * + * @return bool + */ + public function updateNecessary(): bool + { + return true; + } + + /** + * Execute the update + * + * Called when a wizard reports that an update is necessary + * + * @return bool + */ + public function executeUpdate(): bool + { + return GeneralUtility::makeInstance(UpdateService::class)->executeUpdate(); + } + + /** + * Returns an array of class names of Prerequisite classes + * + * This way a wizard can define dependencies like "database up-to-date" or + * "reference index updated" + * + * @return string[] + */ + public function getPrerequisites(): array + { + return []; + } + + /** + * Return a confirmation message instance + * + * @return Confirmation + */ + public function getConfirmation(): Confirmation + { + return $this->confirmation; + } +} diff --git a/Libraries/enshrined-svg-sanitize.phar b/Libraries/enshrined-svg-sanitize.phar new file mode 100755 index 0000000..3fa2287 Binary files /dev/null and b/Libraries/enshrined-svg-sanitize.phar differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..40ac914 --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# SVG Sanitizer + +This extension sanitize every SVG file which is uploaded to the TYPO3 System but only for the default options. +Please read the following section for all the details carfully. + +## Important to know + +This extension remove all script and data values in attributes. +This means, that also an embedded PNG is removed. example: + +``` + // before parser + + // after parser + +``` + +## What this extension does + +- Hooks into FAL API: ``ResourceFactory::addFile()`` and ``ResourceFactory::replaceFile()`` +- Hooks into FAL API: ``ResourceStorage::setFileContents()`` +- Hooks into DataHandler: Handling files for group/select function +- Hooks into ``GeneralUtility::upload_copy_move()`` +- Hooks into ``GeneralUtility::upload_to_tempfile()`` +- Provide an upgrade wizard for existing SVG files (please read the warnings in the upgrade wizard carefully) + +## WARNING + +This extension can sanitize the files only if the upload happens by the defined ways above. +For example, if a third party extension allows an upload and not make use of the core APIs described above, the sanitizer can't sanitize these files. + +## Credits + +Thanks to Daryll Doyle and his [svg-sanitizer library](https://github.com/darylldoyle/svg-sanitizer) + +## Bundling PHAR of external library + +The process of bundling a composer package into a dedicated PHAR archive has been taken +from blog post ["How to use PHP libraries in legacy extensions"](http://insight.helhum.io/post/148112375750/how-to-use-php-libraries-in-legacy-extensions). + +First install bundler package `clue/phar-composer` globally + +``` +composer global require clue/phar-composer +``` + +Then inside the extension folder create the PHAR archive +(in case global composer binaries are not part of the PATH environment, it's +possible to invoke `~/.composer/vendor/bin/phar-composer)` directly) + +``` +cd typo3conf/ext/svg_sanitizer +phar-composer build enshrined/svg-sanitize Libraries/enshrined-svg-sanitize.phar +``` + +## Issue Reporting + +Please report any issues with the extension at [Github](https://github.com/TYPO3GmbH/svg_sanitizer/issues). \ No newline at end of file diff --git a/Tests/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg new file mode 100644 index 0000000..01db9ad --- /dev/null +++ b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Clean.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Tests/Fixtures/CleanSVG/TYPO3_Logo_Data.svg b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Data.svg new file mode 100644 index 0000000..4e44498 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Data.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Tests/Fixtures/CleanSVG/TYPO3_Logo_Script.svg b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Script.svg new file mode 100644 index 0000000..01db9ad --- /dev/null +++ b/Tests/Fixtures/CleanSVG/TYPO3_Logo_Script.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Tests/Fixtures/CleanSVG/billion_laughs.svg b/Tests/Fixtures/CleanSVG/billion_laughs.svg new file mode 100644 index 0000000..e69de29 diff --git a/Tests/Fixtures/CleanSVG/entity.svg b/Tests/Fixtures/CleanSVG/entity.svg new file mode 100644 index 0000000..a7c49b4 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/entity.svg @@ -0,0 +1,4 @@ + + + &lab; + diff --git a/Tests/Fixtures/CleanSVG/entity_2.svg b/Tests/Fixtures/CleanSVG/entity_2.svg new file mode 100644 index 0000000..cf31461 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/entity_2.svg @@ -0,0 +1,4 @@ + + + &lab2; + diff --git a/Tests/Fixtures/CleanSVG/html.svg b/Tests/Fixtures/CleanSVG/html.svg new file mode 100644 index 0000000..ae395b7 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/html.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Tests/Fixtures/CleanSVG/simple.svg b/Tests/Fixtures/CleanSVG/simple.svg new file mode 100644 index 0000000..ae395b7 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/simple.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Tests/Fixtures/CleanSVG/xlink_laughs.svg b/Tests/Fixtures/CleanSVG/xlink_laughs.svg new file mode 100644 index 0000000..dc37126 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/xlink_laughs.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/Fixtures/CleanSVG/xss.svg b/Tests/Fixtures/CleanSVG/xss.svg new file mode 100644 index 0000000..9e0f3c8 --- /dev/null +++ b/Tests/Fixtures/CleanSVG/xss.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Tests/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg new file mode 100644 index 0000000..01db9ad --- /dev/null +++ b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Clean.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Tests/Fixtures/DirtySVG/TYPO3_Logo_Data.svg b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Data.svg new file mode 100644 index 0000000..0a01474 --- /dev/null +++ b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Data.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Tests/Fixtures/DirtySVG/TYPO3_Logo_Script.svg b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Script.svg new file mode 100644 index 0000000..e1170d4 --- /dev/null +++ b/Tests/Fixtures/DirtySVG/TYPO3_Logo_Script.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/Tests/Fixtures/DirtySVG/billion_laughs.svg b/Tests/Fixtures/DirtySVG/billion_laughs.svg new file mode 100644 index 0000000..dc94140 --- /dev/null +++ b/Tests/Fixtures/DirtySVG/billion_laughs.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + +]> + + &lol10; + \ No newline at end of file diff --git a/Tests/Fixtures/DirtySVG/entity.svg b/Tests/Fixtures/DirtySVG/entity.svg new file mode 100644 index 0000000..bc2d3de --- /dev/null +++ b/Tests/Fixtures/DirtySVG/entity.svg @@ -0,0 +1,5 @@ + +]> + + &lab; + \ No newline at end of file diff --git a/Tests/Fixtures/DirtySVG/entity_2.svg b/Tests/Fixtures/DirtySVG/entity_2.svg new file mode 100644 index 0000000..19d3a5b --- /dev/null +++ b/Tests/Fixtures/DirtySVG/entity_2.svg @@ -0,0 +1,8 @@ + + + +]> + + &lab2; + \ No newline at end of file diff --git a/Tests/Fixtures/DirtySVG/html.svg b/Tests/Fixtures/DirtySVG/html.svg new file mode 100644 index 0000000..31bd359 --- /dev/null +++ b/Tests/Fixtures/DirtySVG/html.svg @@ -0,0 +1,14 @@ + + + + + + + +

HTML Injection for phishing

+ +
+
+ diff --git a/Tests/Fixtures/DirtySVG/simple.svg b/Tests/Fixtures/DirtySVG/simple.svg new file mode 100644 index 0000000..29fc853 --- /dev/null +++ b/Tests/Fixtures/DirtySVG/simple.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Tests/Fixtures/DirtySVG/xlink_laughs.svg b/Tests/Fixtures/DirtySVG/xlink_laughs.svg new file mode 100644 index 0000000..01c676a --- /dev/null +++ b/Tests/Fixtures/DirtySVG/xlink_laughs.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tests/Fixtures/DirtySVG/xss.svg b/Tests/Fixtures/DirtySVG/xss.svg new file mode 100644 index 0000000..f6aa93d --- /dev/null +++ b/Tests/Fixtures/DirtySVG/xss.svg @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/Tests/Unit/Service/SvgSanitizerServiceTest.php b/Tests/Unit/Service/SvgSanitizerServiceTest.php new file mode 100644 index 0000000..000b441 --- /dev/null +++ b/Tests/Unit/Service/SvgSanitizerServiceTest.php @@ -0,0 +1,77 @@ +files() + ->in($basePath . 'DirtySVG/') + ->name('*.svg'); + $data = []; + foreach ($finder as $file) { + $fileName = $file->getFilename(); + $data[$fileName] = ['DirtySVG/' . $fileName, 'CleanSVG/' . $fileName]; + } + return $data; + } + + /** + * @param string $inputFile + * @param string $expectedOutputFile + * @dataProvider svgImagesDataProvider + */ + public function testThatImagesCanBeCleaned($inputFile, $expectedOutputFile) + { + $basePath = dirname(__DIR__ . '/../../../') . '/Fixtures/'; + $service = new SvgSanitizerService(); + self::assertStringEqualsFile( + $basePath . $expectedOutputFile, + $service->sanitizeAndReturnSvgContent(file_get_contents($basePath . $inputFile)) + ); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..44de461 --- /dev/null +++ b/composer.json @@ -0,0 +1,54 @@ +{ + "name": "t3g/svg-sanitizer", + "description": "Sanitize SVG files on upload", + "type": "typo3-cms-extension", + "license": "GPL-2.0-or-later", + "authors": [ + { + "name": "TYPO3 GmbH", + "role": "Developer", + "homepage": "https://typo3.com/" + }, + { + "name": "Frank Nägler", + "role": "Developer", + "homepage": "https://naegler.hamburg/" + } + ], + "replace": { + "t3g/svg_sanitizer": "self.version" + }, + "config": { + "sort-packages": true, + "discard-changes": true, + "vendor-dir": ".build/vendor", + "bin-dir": ".build/bin" + }, + "extra": { + "typo3/cms": { + "extension-key": "svg_sanitizer", + "web-dir": ".build" + } + }, + "autoload": { + "psr-4": { + "T3G\\SvgSanitizer\\": "Classes/" + } + }, + "autoload-dev": { + "psr-4": { + "T3G\\SvgSanitizer\\Tests\\": "Tests/" + } + }, + "require": { + "enshrined/svg-sanitize": "^0.13.2", + "typo3/cms-core": "^8.7.13 || ^9.2 || ^10.1", + "typo3/cms-extbase": "^8.7.13 || ^9.2 || ^10.1", + "typo3/cms-install": "^8.7.13 || ^9.2 || ^10.1" + }, + "require-dev": { + "bk2k/extension-helper": "^1.0", + "phpunit/phpunit": "^6.2", + "roave/security-advisories": "dev-master" + } +} diff --git a/ext_emconf.php b/ext_emconf.php new file mode 100644 index 0000000..cf66bc1 --- /dev/null +++ b/ext_emconf.php @@ -0,0 +1,28 @@ + 'SVG Sanitizer', + 'description' => 'Sanitize SVG files on upload', + 'category' => 'extension', + 'constraints' => [ + 'depends' => [ + 'typo3' => '8.7.13-10.4.99' + ], + 'conflicts' => [], + ], + 'autoload' => [ + 'psr-4' => [ + 'T3G\\SvgSanitizer\\' => 'Classes', + ], + ], + 'state' => 'stable', + 'uploadfolder' => 0, + 'createDirs' => '', + 'clearCacheOnLoad' => 1, + 'author' => 'Frank Nägler', + 'author_email' => 'frank.naegler@typo3.com', + 'author_company' => 'TYPO3 GmbH', + 'version' => '1.0.0', +]; diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..27439d1 --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,45 @@ +connect( + \TYPO3\CMS\Core\Resource\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PreFileAdd, + \T3G\SvgSanitizer\SignalSlot\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PreFileAdd + ); + $signalSlotDispatcher + ->connect( + \TYPO3\CMS\Core\Resource\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PreFileReplace, + \T3G\SvgSanitizer\SignalSlot\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PreFileReplace + ); + $signalSlotDispatcher + ->connect( + \TYPO3\CMS\Core\Resource\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PostFileSetContents, + \T3G\SvgSanitizer\SignalSlot\ResourceStorage::class, + \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PostFileSetContents + ); + + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Core\Utility\GeneralUtility']['moveUploadedFile'][] + = \T3G\SvgSanitizer\Hooks\GeneralUtilityHook::class . '->processMoveUploadedFile'; + + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['T3G\SvgSanitizer\Updates\SanitizeExistingSVG'] + = \T3G\SvgSanitizer\Updates\v8\SanitizeExistingSVG::class; + if (\TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) >= 9005000) { + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['T3G\SvgSanitizer\Updates\SanitizeExistingSVG'] + = \T3G\SvgSanitizer\Updates\v9\SanitizeExistingSVG::class; + } + + // The following hooks have been removed with v10: + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processUpload']['svg_sanitizer'] + = \T3G\SvgSanitizer\Hooks\DataHandlerHook::class; + +});