'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 doesn’t 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)'); } } }