praiadeseselle/site/modules/FileValidatorSvgSanitizer/FileValidatorSvgSanitizer.module.php

197 lines
5.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php namespace ProcessWire;
/**
* Validates and/or sanitizes SVG files in ProcessWire
*
* Uses the svg-sanitizer library:
* https://github.com/darylldoyle/svg-sanitizer
*
* The FileValidatorModule interface and this module file are MIT licensed,
* while the svg-sanitizer library in the /svgSanitize/ dir is GPL 2.0.
* As a result, if your installation does not support GPL code, you should
* inquire with the developer of the sanitizer lib before using this module
* in your project: https://github.com/darylldoyle
*
* Originally developed by Adrian and Ryan in 2015 and updated in 2020
* to change the SVG sanitizer library this module uses. Additional updates
* were also made in 2021.
*
* @property int|bool $removeRemoteReferences
* @property int|bool $minify
* @property string $customTags
* @property string $customAttrs
*
*/
class FileValidatorSvgSanitizer extends FileValidatorModule {
public static function getModuleInfo() {
return array(
'title' => 'SVG File Sanitizer/Validator',
'summary' => 'Validates and/or sanitizes uploaded SVG files.',
'version' => 5,
'author' => 'Adrian and Ryan',
'autoload' => false,
'singular' => false,
'validates' => array('svg'),
'requires' => 'ProcessWire>=3.0.148',
);
}
/**
* @var \enshrined\svgSanitize\Sanitizer
*
*/
protected $svgSanitizer = null;
/**
* Construct
*
*/
public function __construct() {
$this->set('removeRemoteReferences', 1);
$this->set('minify', 0);
$this->set('customTags', '');
$this->set('customAttrs', '');
}
/**
* Module init
*
*/
public function init() {
$this->getSvgSanitizer();
}
/**
* Get the SVG Sanitizer instance
*
* @return \enshrined\svgSanitize\Sanitizer
*
*/
public function getSvgSanitizer() {
if($this->svgSanitizer !== null) return $this->svgSanitizer;
$ns = 'enshrined\svgSanitize';
$classLoader = $this->wire()->classLoader;
if(!$classLoader->hasNamespace($ns)) $classLoader->addNamespace($ns, __DIR__ . '/svgSanitize/');
$className = $ns . '\Sanitizer';
$this->svgSanitizer = new $className();
$this->svgSanitizer->removeRemoteReferences((bool) $this->removeRemoteReferences);
$this->svgSanitizer->minify((bool) $this->minify);
list($tags, $attrs) = array($this->customTags, $this->customAttrs);
if($tags || $attrs) {
require_once(__DIR__ . '/FileValidatorSvgSanitizer.data.php');
if($tags) {
FileValidatorSvgSanitizerTags::add($tags);
$this->svgSanitizer->setAllowedTags(new FileValidatorSvgSanitizerTags());
}
if($attrs) {
FileValidatorSvgSanitizerAttributes::add($attrs);
$this->svgSanitizer->setAllowedAttrs(new FileValidatorSvgSanitizerAttributes());
}
}
return $this->svgSanitizer;
}
/**
* Is the given SVG file valid?
*
* This is for implementation of PW's FileValidator interface.
*
* This method should return:
* - boolean TRUE if file is valid
* - boolean FALSE if file is not valid
* - integer 1 if file is valid as a result of sanitization performed by this method
*
* If method wants to explain why the file is not valid, it should call $this->error('reason why not valid').
*
* @param string $filename Full path and filename to the file
* @return bool|int
*
*/
protected function isValidFile($filename) {
$svgSanitizer = $this->getSvgSanitizer();
$svgDirty = file_get_contents($filename);
$svgClean = $svgSanitizer->sanitize($svgDirty);
$svgIssues = $svgSanitizer->getXmlIssues();
if(!empty($svgIssues)) {
// log found issues
$issues = array();
foreach($svgIssues as $issue) {
$issue = "$issue[message] (line $issue[line])";
$issues[$issue] = $issue;
}
if($svgClean === false) {
foreach($issues as $issue) $this->error($issue);
} else if(count($issues)) {
$this->log("SvgSanitizer: " . basename($filename) . ": " . implode(', ', $issues));
}
}
if($svgClean === false) {
// sanitize failed
return false;
} else if($svgDirty === $svgClean) {
// no changes after sanitization, file is ok. this is sort of unlikely
// as SvgSanitizer seems to apply minor changes either way
return true;
}
// write new sanitized svg file
$files = $this->wire()->files;
$files->unlink($filename);
if($files->filePutContents($filename, $svgClean) === false) return false;
return 1;
}
/**
* Return the data from the default whitelist
*
* This method doesnt do anything for this module, it is just here if you want to
* know what are the whitelisted tags and attributes.
*
* @return array
*
*/
public function getDefaultWhitelist() {
return array(
'tags' => \enshrined\svgSanitize\data\AllowedTags::getTags(),
'attributes' => \enshrined\svgSanitize\data\AllowedAttributes::getAttributes(),
);
}
/**
* Return data from the customized whitelist
*
* @return array
*
*/
public function getWhitelist() {
$this->getSvgSanitizer();
return array(
'tags' => FileValidatorSvgSanitizerTags::getTags(),
'attributes' => FileValidatorSvgSanitizerAttributes::getAttributes(),
);
}
/**
* Install
*
* @throws WireException
*
*/
public function ___install() {
$exts = get_loaded_extensions();
if(!in_array('dom', $exts)) {
throw new WireException('This module requires the PHP “dom” extension (ext-dom)');
}
if(!in_array('libxml', $exts)) {
throw new WireException('This module requires the PHP “libxml” extension (ext-libxml)');
}
}
}