updated plugin Menu Icons
version 0.13.14
This commit is contained in:
169
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Resolver.php
vendored
Normal file
169
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Resolver.php
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\ElementReference;
|
||||
|
||||
use enshrined\svgSanitize\data\XPath;
|
||||
use enshrined\svgSanitize\Exceptions\NestingException;
|
||||
use enshrined\svgSanitize\Helper;
|
||||
|
||||
class Resolver
|
||||
{
|
||||
/**
|
||||
* @var XPath
|
||||
*/
|
||||
protected $xPath;
|
||||
|
||||
/**
|
||||
* @var Subject[]
|
||||
*/
|
||||
protected $subjects = [];
|
||||
|
||||
/**
|
||||
* @var array DOMElement[]
|
||||
*/
|
||||
protected $elementsToRemove = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $useNestingLimit;
|
||||
|
||||
public function __construct(XPath $xPath, $useNestingLimit)
|
||||
{
|
||||
$this->xPath = $xPath;
|
||||
$this->useNestingLimit = $useNestingLimit;
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
$this->collectIdentifiedElements();
|
||||
$this->processReferences();
|
||||
$this->determineInvalidSubjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves one subject by element.
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @param bool $considerChildren Whether to search in Subject's children as well
|
||||
* @return Subject|null
|
||||
*/
|
||||
public function findByElement(\DOMElement $element, $considerChildren = false)
|
||||
{
|
||||
foreach ($this->subjects as $subject) {
|
||||
if (
|
||||
$element === $subject->getElement()
|
||||
|| $considerChildren && Helper::isElementContainedIn($element, $subject->getElement())
|
||||
) {
|
||||
return $subject;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves subjects (plural!) by element id - in theory malformed
|
||||
* DOM might have same ids assigned to different elements and leaving
|
||||
* it to client/browser implementation which element to actually use.
|
||||
*
|
||||
* @param string $elementId
|
||||
* @return Subject[]
|
||||
*/
|
||||
public function findByElementId($elementId)
|
||||
{
|
||||
return array_filter(
|
||||
$this->subjects,
|
||||
function (Subject $subject) use ($elementId) {
|
||||
return $elementId === $subject->getElementId();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects elements having `id` attribute (those that can be referenced).
|
||||
*/
|
||||
protected function collectIdentifiedElements()
|
||||
{
|
||||
/** @var \DOMNodeList|\DOMElement[] $elements */
|
||||
$elements = $this->xPath->query('//*[@id]');
|
||||
foreach ($elements as $element) {
|
||||
$this->subjects[$element->getAttribute('id')] = new Subject($element, $this->useNestingLimit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes references from and to elements having `id` attribute concerning
|
||||
* their occurrence in `<use ... xlink:href="#identifier">` statements.
|
||||
*/
|
||||
protected function processReferences()
|
||||
{
|
||||
$useNodeName = $this->xPath->createNodeName('use');
|
||||
foreach ($this->subjects as $subject) {
|
||||
$useElements = $this->xPath->query(
|
||||
$useNodeName . '[@href or @xlink:href]',
|
||||
$subject->getElement()
|
||||
);
|
||||
|
||||
/** @var \DOMElement $useElement */
|
||||
foreach ($useElements as $useElement) {
|
||||
$useId = Helper::extractIdReferenceFromHref(
|
||||
Helper::getElementHref($useElement)
|
||||
);
|
||||
if ($useId === null || !isset($this->subjects[$useId])) {
|
||||
continue;
|
||||
}
|
||||
$subject->addUse($this->subjects[$useId]);
|
||||
$this->subjects[$useId]->addUsedIn($subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines and tags infinite loops.
|
||||
*/
|
||||
protected function determineInvalidSubjects()
|
||||
{
|
||||
foreach ($this->subjects as $subject) {
|
||||
|
||||
if (in_array($subject->getElement(), $this->elementsToRemove)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$useId = Helper::extractIdReferenceFromHref(
|
||||
Helper::getElementHref($subject->getElement())
|
||||
);
|
||||
|
||||
try {
|
||||
if ($useId === $subject->getElementId()) {
|
||||
$this->markSubjectAsInvalid($subject);
|
||||
} elseif ($subject->hasInfiniteLoop()) {
|
||||
$this->markSubjectAsInvalid($subject);
|
||||
}
|
||||
} catch (NestingException $e) {
|
||||
$this->elementsToRemove[] = $e->getElement();
|
||||
$this->markSubjectAsInvalid($subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the elements that caused a nesting exception.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getElementsToRemove() {
|
||||
return $this->elementsToRemove;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Subject is invalid for some reason, therefore we should
|
||||
* remove it and all it's child usages.
|
||||
*
|
||||
* @param Subject $subject
|
||||
*/
|
||||
protected function markSubjectAsInvalid(Subject $subject) {
|
||||
$this->elementsToRemove = array_merge(
|
||||
$this->elementsToRemove,
|
||||
$subject->clearInternalAndGetAffectedElements()
|
||||
);
|
||||
}
|
||||
}
|
153
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Subject.php
vendored
Normal file
153
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Subject.php
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\ElementReference;
|
||||
|
||||
class Subject
|
||||
{
|
||||
/**
|
||||
* @var \DOMElement
|
||||
*/
|
||||
protected $element;
|
||||
|
||||
/**
|
||||
* @var Usage[]
|
||||
*/
|
||||
protected $useCollection = [];
|
||||
|
||||
/**
|
||||
* @var Usage[]
|
||||
*/
|
||||
protected $usedInCollection = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $useNestingLimit;
|
||||
|
||||
/**
|
||||
* Subject constructor.
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @param int $useNestingLimit
|
||||
*/
|
||||
public function __construct(\DOMElement $element, $useNestingLimit)
|
||||
{
|
||||
$this->element = $element;
|
||||
$this->useNestingLimit = $useNestingLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DOMElement
|
||||
*/
|
||||
public function getElement()
|
||||
{
|
||||
return $this->element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getElementId()
|
||||
{
|
||||
return $this->element->getAttribute('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $subjects Previously processed subjects
|
||||
* @param int $level The current level of nesting.
|
||||
* @return bool
|
||||
* @throws \enshrined\svgSanitize\Exceptions\NestingException
|
||||
*/
|
||||
public function hasInfiniteLoop(array $subjects = [], $level = 1)
|
||||
{
|
||||
if ($level > $this->useNestingLimit) {
|
||||
throw new \enshrined\svgSanitize\Exceptions\NestingException('Nesting level too high, aborting', 1570713498, null, $this->getElement());
|
||||
}
|
||||
|
||||
if (in_array($this, $subjects, true)) {
|
||||
return true;
|
||||
}
|
||||
$subjects[] = $this;
|
||||
foreach ($this->useCollection as $usage) {
|
||||
if ($usage->getSubject()->hasInfiniteLoop($subjects, $level + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Subject $subject
|
||||
*/
|
||||
public function addUse(Subject $subject)
|
||||
{
|
||||
if ($subject === $this) {
|
||||
throw new \LogicException('Cannot add self usage', 1570713416);
|
||||
}
|
||||
$identifier = $subject->getElementId();
|
||||
if (isset($this->useCollection[$identifier])) {
|
||||
$this->useCollection[$identifier]->increment();
|
||||
return;
|
||||
}
|
||||
$this->useCollection[$identifier] = new Usage($subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Subject $subject
|
||||
*/
|
||||
public function addUsedIn(Subject $subject)
|
||||
{
|
||||
if ($subject === $this) {
|
||||
throw new \LogicException('Cannot add self as usage', 1570713417);
|
||||
}
|
||||
$identifier = $subject->getElementId();
|
||||
if (isset($this->usedInCollection[$identifier])) {
|
||||
$this->usedInCollection[$identifier]->increment();
|
||||
return;
|
||||
}
|
||||
$this->usedInCollection[$identifier] = new Usage($subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $accumulated
|
||||
* @return int
|
||||
*/
|
||||
public function countUse($accumulated = false)
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($this->useCollection as $use) {
|
||||
$useCount = $use->getSubject()->countUse();
|
||||
$count += $use->getCount() * ($accumulated ? 1 + $useCount : max(1, $useCount));
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function countUsedIn()
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($this->usedInCollection as $usedIn) {
|
||||
$count += $usedIn->getCount() * max(1, $usedIn->getSubject()->countUsedIn());
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the internal arrays (to free up memory as they can get big)
|
||||
* and return all the child usages DOMElement's
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function clearInternalAndGetAffectedElements()
|
||||
{
|
||||
$elements = array_map(function(Usage $usage) {
|
||||
return $usage->getSubject()->getElement();
|
||||
}, $this->useCollection);
|
||||
|
||||
$this->usedInCollection = [];
|
||||
$this->useCollection = [];
|
||||
|
||||
return $elements;
|
||||
}
|
||||
}
|
49
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Usage.php
vendored
Normal file
49
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/ElementReference/Usage.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\ElementReference;
|
||||
|
||||
class Usage
|
||||
{
|
||||
/**
|
||||
* @var Subject
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* @param Subject $subject
|
||||
* @param int $count
|
||||
*/
|
||||
public function __construct(Subject $subject, $count = 1)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
$this->count = (int)$count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $by
|
||||
*/
|
||||
public function increment($by = 1)
|
||||
{
|
||||
$this->count += (int)$by;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Subject
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCount()
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
}
|
36
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Exceptions/NestingException.php
vendored
Normal file
36
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Exceptions/NestingException.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class NestingException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @var \DOMElement
|
||||
*/
|
||||
protected $element;
|
||||
|
||||
/**
|
||||
* NestingException constructor.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Exception|null $previous
|
||||
* @param \DOMElement|null $element
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, Exception $previous = null, \DOMElement $element = null)
|
||||
{
|
||||
$this->element = $element;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element that caused the exception.
|
||||
*
|
||||
* @return \DOMElement
|
||||
*/
|
||||
public function getElement()
|
||||
{
|
||||
return $this->element;
|
||||
}
|
||||
}
|
53
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Helper.php
vendored
Normal file
53
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Helper.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize;
|
||||
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
* @param \DOMElement $element
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getElementHref(\DOMElement $element)
|
||||
{
|
||||
if ($element->hasAttribute('href')) {
|
||||
return $element->getAttribute('href');
|
||||
}
|
||||
if ($element->hasAttributeNS('http://www.w3.org/1999/xlink', 'href')) {
|
||||
return $element->getAttributeNS('http://www.w3.org/1999/xlink', 'href');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $href
|
||||
* @return string|null
|
||||
*/
|
||||
public static function extractIdReferenceFromHref($href)
|
||||
{
|
||||
if (!is_string($href) || strpos($href, '#') !== 0) {
|
||||
return null;
|
||||
}
|
||||
return substr($href, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMElement $needle
|
||||
* @param \DOMElement $haystack
|
||||
* @return bool
|
||||
*/
|
||||
public static function isElementContainedIn(\DOMElement $needle, \DOMElement $haystack)
|
||||
{
|
||||
if ($needle === $haystack) {
|
||||
return true;
|
||||
}
|
||||
foreach ($haystack->childNodes as $childNode) {
|
||||
if (!$childNode instanceof \DOMElement) {
|
||||
continue;
|
||||
}
|
||||
if (self::isElementContainedIn($needle, $childNode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
701
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Sanitizer.php
vendored
Normal file
701
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/Sanitizer.php
vendored
Normal file
@ -0,0 +1,701 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize;
|
||||
|
||||
use enshrined\svgSanitize\data\AllowedAttributes;
|
||||
use enshrined\svgSanitize\data\AllowedTags;
|
||||
use enshrined\svgSanitize\data\AttributeInterface;
|
||||
use enshrined\svgSanitize\data\TagInterface;
|
||||
use enshrined\svgSanitize\data\XPath;
|
||||
use enshrined\svgSanitize\ElementReference\Resolver;
|
||||
|
||||
/**
|
||||
* Class Sanitizer
|
||||
*
|
||||
* @package enshrined\svgSanitize
|
||||
*/
|
||||
class Sanitizer
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \DOMDocument
|
||||
*/
|
||||
protected $xmlDocument;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedTags;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedAttrs;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $xmlLoaderValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $xmlErrorHandlerPreviousValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $minifyXML = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $removeRemoteReferences = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $useThreshold = 1000;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $removeXMLTag = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $xmlOptions = LIBXML_NOEMPTYTAG;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $xmlIssues = array();
|
||||
|
||||
/**
|
||||
* @var Resolver
|
||||
*/
|
||||
protected $elementReferenceResolver;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $useNestingLimit = 15;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $allowHugeFiles = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
// Load default tags/attributes
|
||||
$this->allowedAttrs = array_map('strtolower', AllowedAttributes::getAttributes());
|
||||
$this->allowedTags = array_map('strtolower', AllowedTags::getTags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the DOMDocument
|
||||
*/
|
||||
protected function resetInternal()
|
||||
{
|
||||
$this->xmlDocument = new \DOMDocument();
|
||||
$this->xmlDocument->preserveWhiteSpace = false;
|
||||
$this->xmlDocument->strictErrorChecking = false;
|
||||
$this->xmlDocument->formatOutput = !$this->minifyXML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set XML options to use when saving XML
|
||||
* See: DOMDocument::saveXML
|
||||
*
|
||||
* @param int $xmlOptions
|
||||
*/
|
||||
public function setXMLOptions($xmlOptions)
|
||||
{
|
||||
$this->xmlOptions = $xmlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get XML options to use when saving XML
|
||||
* See: DOMDocument::saveXML
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getXMLOptions()
|
||||
{
|
||||
return $this->xmlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of allowed tags
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllowedTags()
|
||||
{
|
||||
return $this->allowedTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom allowed tags
|
||||
*
|
||||
* @param TagInterface $allowedTags
|
||||
*/
|
||||
public function setAllowedTags(TagInterface $allowedTags)
|
||||
{
|
||||
$this->allowedTags = array_map('strtolower', $allowedTags::getTags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of allowed attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllowedAttrs()
|
||||
{
|
||||
return $this->allowedAttrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom allowed attributes
|
||||
*
|
||||
* @param AttributeInterface $allowedAttrs
|
||||
*/
|
||||
public function setAllowedAttrs(AttributeInterface $allowedAttrs)
|
||||
{
|
||||
$this->allowedAttrs = array_map('strtolower', $allowedAttrs::getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we remove references to remote files?
|
||||
*
|
||||
* @param bool $removeRemoteRefs
|
||||
*/
|
||||
public function removeRemoteReferences($removeRemoteRefs = false)
|
||||
{
|
||||
$this->removeRemoteReferences = $removeRemoteRefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get XML issues.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getXmlIssues() {
|
||||
return $this->xmlIssues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can we allow huge files?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getAllowHugeFiles() {
|
||||
return $this->allowHugeFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether we can allow huge files.
|
||||
*
|
||||
* @param bool $allowHugeFiles
|
||||
*/
|
||||
public function setAllowHugeFiles( $allowHugeFiles ) {
|
||||
$this->allowHugeFiles = $allowHugeFiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitize the passed string
|
||||
*
|
||||
* @param string $dirty
|
||||
* @return string|false
|
||||
*/
|
||||
public function sanitize($dirty)
|
||||
{
|
||||
// Don't run on an empty string
|
||||
if (empty($dirty)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Strip php tags
|
||||
$dirty = preg_replace('/<\?(=|php)(.+?)\?>/i', '', $dirty);
|
||||
|
||||
$this->resetInternal();
|
||||
$this->setUpBefore();
|
||||
|
||||
$loaded = $this->xmlDocument->loadXML($dirty, $this->getAllowHugeFiles() ? LIBXML_PARSEHUGE : 0);
|
||||
|
||||
// If we couldn't parse the XML then we go no further. Reset and return false
|
||||
if (!$loaded) {
|
||||
$this->resetAfter();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pre-process all identified elements
|
||||
$xPath = new XPath($this->xmlDocument);
|
||||
$this->elementReferenceResolver = new Resolver($xPath, $this->useNestingLimit);
|
||||
$this->elementReferenceResolver->collect();
|
||||
$elementsToRemove = $this->elementReferenceResolver->getElementsToRemove();
|
||||
|
||||
// Start the cleaning process
|
||||
$this->startClean($this->xmlDocument->childNodes, $elementsToRemove);
|
||||
|
||||
// Save cleaned XML to a variable
|
||||
if ($this->removeXMLTag) {
|
||||
$clean = $this->xmlDocument->saveXML($this->xmlDocument->documentElement, $this->xmlOptions);
|
||||
} else {
|
||||
$clean = $this->xmlDocument->saveXML($this->xmlDocument, $this->xmlOptions);
|
||||
}
|
||||
|
||||
$this->resetAfter();
|
||||
|
||||
// Remove any extra whitespaces when minifying
|
||||
if ($this->minifyXML) {
|
||||
$clean = preg_replace('/\s+/', ' ', $clean);
|
||||
}
|
||||
|
||||
// Return result
|
||||
return $clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up libXML before we start
|
||||
*/
|
||||
protected function setUpBefore()
|
||||
{
|
||||
// This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
|
||||
// disabled by default, so this function is no longer needed to protect against XXE attacks.
|
||||
if (\LIBXML_VERSION < 20900) {
|
||||
// Turn off the entity loader
|
||||
$this->xmlLoaderValue = libxml_disable_entity_loader(true);
|
||||
}
|
||||
|
||||
// Suppress the errors because we don't really have to worry about formation before cleansing.
|
||||
// See reset in resetAfter().
|
||||
$this->xmlErrorHandlerPreviousValue = libxml_use_internal_errors(true);
|
||||
|
||||
// Reset array of altered XML
|
||||
$this->xmlIssues = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the class after use
|
||||
*/
|
||||
protected function resetAfter()
|
||||
{
|
||||
// This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
|
||||
// disabled by default, so this function is no longer needed to protect against XXE attacks.
|
||||
if (\LIBXML_VERSION < 20900) {
|
||||
// Reset the entity loader
|
||||
libxml_disable_entity_loader($this->xmlLoaderValue);
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($this->xmlErrorHandlerPreviousValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the cleaning with tags, then we move onto attributes and hrefs later
|
||||
*
|
||||
* @param \DOMNodeList $elements
|
||||
* @param array $elementsToRemove
|
||||
*/
|
||||
protected function startClean(\DOMNodeList $elements, array $elementsToRemove)
|
||||
{
|
||||
// loop through all elements
|
||||
// we do this backwards so we don't skip anything if we delete a node
|
||||
// see comments at: http://php.net/manual/en/class.domnamednodemap.php
|
||||
for ($i = $elements->length - 1; $i >= 0; $i--) {
|
||||
/** @var \DOMElement $currentElement */
|
||||
$currentElement = $elements->item($i);
|
||||
|
||||
/**
|
||||
* If the element has exceeded the nesting limit, we should remove it.
|
||||
*
|
||||
* As it's only <use> elements that cause us issues with nesting DOS attacks
|
||||
* we should check what the element is before removing it. For now we'll only
|
||||
* remove <use> elements.
|
||||
*/
|
||||
if (in_array($currentElement, $elementsToRemove) && 'use' === $currentElement->nodeName) {
|
||||
$currentElement->parentNode->removeChild($currentElement);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Invalid \'' . $currentElement->tagName . '\'',
|
||||
'line' => $currentElement->getLineNo(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($currentElement instanceof \DOMElement) {
|
||||
// If the tag isn't in the whitelist, remove it and continue with next iteration
|
||||
if (!in_array(strtolower($currentElement->tagName), $this->allowedTags)) {
|
||||
$currentElement->parentNode->removeChild($currentElement);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious tag \'' . $currentElement->tagName . '\'',
|
||||
'line' => $currentElement->getLineNo(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->cleanHrefs( $currentElement );
|
||||
|
||||
$this->cleanXlinkHrefs( $currentElement );
|
||||
|
||||
$this->cleanAttributesOnWhitelist($currentElement);
|
||||
|
||||
if (strtolower($currentElement->tagName) === 'use') {
|
||||
if ($this->isUseTagDirty($currentElement)
|
||||
|| $this->isUseTagExceedingThreshold($currentElement)
|
||||
) {
|
||||
$currentElement->parentNode->removeChild($currentElement);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious \'' . $currentElement->tagName . '\'',
|
||||
'line' => $currentElement->getLineNo(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Strip out font elements that will break out of foreign content.
|
||||
if (strtolower($currentElement->tagName) === 'font') {
|
||||
$breaksOutOfForeignContent = false;
|
||||
for ($x = $currentElement->attributes->length - 1; $x >= 0; $x--) {
|
||||
// get attribute name
|
||||
$attrName = $currentElement->attributes->item( $x )->name;
|
||||
|
||||
if (in_array(strtolower($attrName), ['face', 'color', 'size'])) {
|
||||
$breaksOutOfForeignContent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($breaksOutOfForeignContent) {
|
||||
$currentElement->parentNode->removeChild($currentElement);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious tag \'' . $currentElement->tagName . '\'',
|
||||
'line' => $currentElement->getLineNo(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->cleanUnsafeNodes($currentElement);
|
||||
|
||||
if ($currentElement->hasChildNodes()) {
|
||||
$this->startClean($currentElement->childNodes, $elementsToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allow attributes that are on the whitelist
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
*/
|
||||
protected function cleanAttributesOnWhitelist(\DOMElement $element)
|
||||
{
|
||||
for ($x = $element->attributes->length - 1; $x >= 0; $x--) {
|
||||
// get attribute name
|
||||
$attrName = $element->attributes->item($x)->name;
|
||||
|
||||
// Remove attribute if not in whitelist
|
||||
if (!in_array(strtolower($attrName), $this->allowedAttrs) && !$this->isAriaAttribute(strtolower($attrName)) && !$this->isDataAttribute(strtolower($attrName))) {
|
||||
|
||||
$element->removeAttribute($attrName);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious attribute \'' . $attrName . '\'',
|
||||
'line' => $element->getLineNo(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for when a namespace isn't imported properly.
|
||||
* Such as xlink:href when the xlink namespace isn't imported.
|
||||
* We have to do this as the link is still ran in this case.
|
||||
*/
|
||||
if (false !== strpos($attrName, 'href')) {
|
||||
$href = $element->getAttribute($attrName);
|
||||
if (false === $this->isHrefSafeValue($href)) {
|
||||
$element->removeAttribute($attrName);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious attribute \'href\'',
|
||||
'line' => $element->getLineNo(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Do we want to strip remote references?
|
||||
if($this->removeRemoteReferences) {
|
||||
// Remove attribute if it has a remote reference
|
||||
if (isset($element->attributes->item($x)->value) && $this->hasRemoteReference($element->attributes->item($x)->value)) {
|
||||
$element->removeAttribute($attrName);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious attribute \'' . $attrName . '\'',
|
||||
'line' => $element->getLineNo(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the xlink:hrefs of script and data embeds
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
*/
|
||||
protected function cleanXlinkHrefs(\DOMElement $element)
|
||||
{
|
||||
$xlinks = $element->getAttributeNS('http://www.w3.org/1999/xlink', 'href');
|
||||
if (false === $this->isHrefSafeValue($xlinks)) {
|
||||
$element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious attribute \'href\'',
|
||||
'line' => $element->getLineNo(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the hrefs of script and data embeds
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
*/
|
||||
protected function cleanHrefs(\DOMElement $element)
|
||||
{
|
||||
$href = $element->getAttribute('href');
|
||||
if (false === $this->isHrefSafeValue($href)) {
|
||||
$element->removeAttribute('href');
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious attribute \'href\'',
|
||||
'line' => $element->getLineNo(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allow whitelisted starts to be within the href.
|
||||
*
|
||||
* This will stop scripts etc from being passed through, with or without attempting to hide bypasses.
|
||||
* This stops the need for us to use a complicated script regex.
|
||||
*
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isHrefSafeValue($value) {
|
||||
|
||||
// Allow empty values
|
||||
if (empty($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow fragment identifiers.
|
||||
if ('#' === substr($value, 0, 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow relative URIs.
|
||||
if ('/' === substr($value, 0, 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow HTTPS domains.
|
||||
if ('https://' === substr($value, 0, 8)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow HTTP domains.
|
||||
if ('http://' === substr($value, 0, 7)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow known data URIs.
|
||||
if (in_array(substr($value, 0, 14), array(
|
||||
'data:image/png', // PNG
|
||||
'data:image/gif', // GIF
|
||||
'data:image/jpg', // JPG
|
||||
'data:image/jpe', // JPEG
|
||||
'data:image/pjp', // PJPEG
|
||||
))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow known short data URIs.
|
||||
if (in_array(substr($value, 0, 12), array(
|
||||
'data:img/png', // PNG
|
||||
'data:img/gif', // GIF
|
||||
'data:img/jpg', // JPG
|
||||
'data:img/jpe', // JPEG
|
||||
'data:img/pjp', // PJPEG
|
||||
))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes non-printable ASCII characters from string & trims it
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function removeNonPrintableCharacters($value)
|
||||
{
|
||||
return trim(preg_replace('/[^ -~]/xu','',$value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this attribute value have a remote reference?
|
||||
*
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasRemoteReference($value)
|
||||
{
|
||||
$value = $this->removeNonPrintableCharacters($value);
|
||||
|
||||
$wrapped_in_url = preg_match('~^url\(\s*[\'"]\s*(.*)\s*[\'"]\s*\)$~xi', $value, $match);
|
||||
if (!$wrapped_in_url){
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = trim($match[1], '\'"');
|
||||
|
||||
return preg_match('~^((https?|ftp|file):)?//~xi', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we minify the output?
|
||||
*
|
||||
* @param bool $shouldMinify
|
||||
*/
|
||||
public function minify($shouldMinify = false)
|
||||
{
|
||||
$this->minifyXML = (bool) $shouldMinify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we remove the XML tag in the header?
|
||||
*
|
||||
* @param bool $removeXMLTag
|
||||
*/
|
||||
public function removeXMLTag($removeXMLTag = false)
|
||||
{
|
||||
$this->removeXMLTag = (bool) $removeXMLTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether `<use ... xlink:href="#identifier">` elements shall be
|
||||
* removed in case expansion would exceed this threshold.
|
||||
*
|
||||
* @param int $useThreshold
|
||||
*/
|
||||
public function useThreshold($useThreshold = 1000)
|
||||
{
|
||||
$this->useThreshold = (int)$useThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if an attribute is an aria attribute or not
|
||||
*
|
||||
* @param $attributeName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAriaAttribute($attributeName)
|
||||
{
|
||||
return strpos($attributeName, 'aria-') === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if an attribute is an data attribute or not
|
||||
*
|
||||
* @param $attributeName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isDataAttribute($attributeName)
|
||||
{
|
||||
return strpos($attributeName, 'data-') === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure our use tag is only referencing internal resources
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return bool
|
||||
*/
|
||||
protected function isUseTagDirty(\DOMElement $element)
|
||||
{
|
||||
$href = Helper::getElementHref($element);
|
||||
return $href && strpos($href, '#') !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether `<use ... xlink:href="#identifier">` is expanded
|
||||
* recursively in order to create DoS scenarios. The amount of a actually
|
||||
* used element needs to be below `$this->useThreshold`.
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return bool
|
||||
*/
|
||||
protected function isUseTagExceedingThreshold(\DOMElement $element)
|
||||
{
|
||||
if ($this->useThreshold <= 0) {
|
||||
return false;
|
||||
}
|
||||
$useId = Helper::extractIdReferenceFromHref(
|
||||
Helper::getElementHref($element)
|
||||
);
|
||||
if ($useId === null) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->elementReferenceResolver->findByElementId($useId) as $subject) {
|
||||
if ($subject->countUse() >= $this->useThreshold) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the nesting limit for <use> tags.
|
||||
*
|
||||
* @param $limit
|
||||
*/
|
||||
public function setUseNestingLimit($limit)
|
||||
{
|
||||
$this->useNestingLimit = (int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove nodes that are either invalid or malformed.
|
||||
*
|
||||
* @param \DOMNode $currentElement The current element.
|
||||
*/
|
||||
protected function cleanUnsafeNodes(\DOMNode $currentElement) {
|
||||
// Replace CDATA node with encoded text node
|
||||
if ($currentElement instanceof \DOMCdataSection) {
|
||||
$textNode = $currentElement->ownerDocument->createTextNode($currentElement->nodeValue);
|
||||
$currentElement->parentNode->replaceChild($textNode, $currentElement);
|
||||
// If the element doesn't have a tagname, remove it and continue with next iteration
|
||||
} elseif (!$currentElement instanceof \DOMElement && !$currentElement instanceof \DOMText) {
|
||||
$currentElement->parentNode->removeChild($currentElement);
|
||||
$this->xmlIssues[] = array(
|
||||
'message' => 'Suspicious node \'' . $currentElement->nodeName . '\'',
|
||||
'line' => $currentElement->getLineNo(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $currentElement->childNodes && $currentElement->childNodes->length > 0 ) {
|
||||
for ($j = $currentElement->childNodes->length - 1; $j >= 0; $j--) {
|
||||
/** @var \DOMElement $childElement */
|
||||
$childElement = $currentElement->childNodes->item($j);
|
||||
$this->cleanUnsafeNodes($childElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
356
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AllowedAttributes.php
vendored
Normal file
356
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AllowedAttributes.php
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\data;
|
||||
|
||||
/**
|
||||
* Class AllowedAttributes
|
||||
*
|
||||
* @package enshrined\svgSanitize\data
|
||||
*/
|
||||
class AllowedAttributes implements AttributeInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAttributes()
|
||||
{
|
||||
return array(
|
||||
// HTML
|
||||
'about',
|
||||
'accept',
|
||||
'action',
|
||||
'align',
|
||||
'alt',
|
||||
'autocomplete',
|
||||
'background',
|
||||
'bgcolor',
|
||||
'border',
|
||||
'cellpadding',
|
||||
'cellspacing',
|
||||
'checked',
|
||||
'cite',
|
||||
'class',
|
||||
'clear',
|
||||
'color',
|
||||
'cols',
|
||||
'colspan',
|
||||
'coords',
|
||||
'crossorigin',
|
||||
'datetime',
|
||||
'default',
|
||||
'dir',
|
||||
'disabled',
|
||||
'download',
|
||||
'enctype',
|
||||
'encoding',
|
||||
'face',
|
||||
'for',
|
||||
'headers',
|
||||
'height',
|
||||
'hidden',
|
||||
'high',
|
||||
'href',
|
||||
'hreflang',
|
||||
'id',
|
||||
'integrity',
|
||||
'ismap',
|
||||
'label',
|
||||
'lang',
|
||||
'list',
|
||||
'loop',
|
||||
'low',
|
||||
'max',
|
||||
'maxlength',
|
||||
'media',
|
||||
'method',
|
||||
'min',
|
||||
'multiple',
|
||||
'name',
|
||||
'noshade',
|
||||
'novalidate',
|
||||
'nowrap',
|
||||
'open',
|
||||
'optimum',
|
||||
'pattern',
|
||||
'placeholder',
|
||||
'poster',
|
||||
'preload',
|
||||
'pubdate',
|
||||
'radiogroup',
|
||||
'readonly',
|
||||
'rel',
|
||||
'required',
|
||||
'rev',
|
||||
'reversed',
|
||||
'role',
|
||||
'rows',
|
||||
'rowspan',
|
||||
'spellcheck',
|
||||
'scope',
|
||||
'selected',
|
||||
'shape',
|
||||
'size',
|
||||
'sizes',
|
||||
'span',
|
||||
'srclang',
|
||||
'start',
|
||||
'src',
|
||||
'srcset',
|
||||
'step',
|
||||
'style',
|
||||
'summary',
|
||||
'tabindex',
|
||||
'title',
|
||||
'type',
|
||||
'usemap',
|
||||
'valign',
|
||||
'value',
|
||||
'version',
|
||||
'width',
|
||||
'xmlns',
|
||||
|
||||
// SVG
|
||||
'accent-height',
|
||||
'accumulate',
|
||||
'additivive',
|
||||
'alignment-baseline',
|
||||
'ascent',
|
||||
'attributename',
|
||||
'attributetype',
|
||||
'azimuth',
|
||||
'basefrequency',
|
||||
'baseline-shift',
|
||||
'begin',
|
||||
'bias',
|
||||
'by',
|
||||
'class',
|
||||
'clip',
|
||||
'clip-path',
|
||||
'clip-rule',
|
||||
'color',
|
||||
'color-interpolation',
|
||||
'color-interpolation-filters',
|
||||
'color-profile',
|
||||
'color-rendering',
|
||||
'cx',
|
||||
'cy',
|
||||
'd',
|
||||
'dx',
|
||||
'dy',
|
||||
'diffuseconstant',
|
||||
'direction',
|
||||
'display',
|
||||
'divisor',
|
||||
'dur',
|
||||
'edgemode',
|
||||
'elevation',
|
||||
'end',
|
||||
'fill',
|
||||
'fill-opacity',
|
||||
'fill-rule',
|
||||
'filter',
|
||||
'filterUnits',
|
||||
'flood-color',
|
||||
'flood-opacity',
|
||||
'font-family',
|
||||
'font-size',
|
||||
'font-size-adjust',
|
||||
'font-stretch',
|
||||
'font-style',
|
||||
'font-variant',
|
||||
'font-weight',
|
||||
'fx',
|
||||
'fy',
|
||||
'g1',
|
||||
'g2',
|
||||
'glyph-name',
|
||||
'glyphref',
|
||||
'gradientunits',
|
||||
'gradienttransform',
|
||||
'height',
|
||||
'href',
|
||||
'id',
|
||||
'image-rendering',
|
||||
'in',
|
||||
'in2',
|
||||
'k',
|
||||
'k1',
|
||||
'k2',
|
||||
'k3',
|
||||
'k4',
|
||||
'kerning',
|
||||
'keypoints',
|
||||
'keysplines',
|
||||
'keytimes',
|
||||
'lang',
|
||||
'lengthadjust',
|
||||
'letter-spacing',
|
||||
'kernelmatrix',
|
||||
'kernelunitlength',
|
||||
'lighting-color',
|
||||
'local',
|
||||
'marker-end',
|
||||
'marker-mid',
|
||||
'marker-start',
|
||||
'markerheight',
|
||||
'markerunits',
|
||||
'markerwidth',
|
||||
'maskcontentunits',
|
||||
'maskunits',
|
||||
'max',
|
||||
'mask',
|
||||
'media',
|
||||
'method',
|
||||
'mode',
|
||||
'min',
|
||||
'name',
|
||||
'numoctaves',
|
||||
'offset',
|
||||
'operator',
|
||||
'opacity',
|
||||
'order',
|
||||
'orient',
|
||||
'orientation',
|
||||
'origin',
|
||||
'overflow',
|
||||
'paint-order',
|
||||
'path',
|
||||
'pathlength',
|
||||
'patterncontentunits',
|
||||
'patterntransform',
|
||||
'patternunits',
|
||||
'points',
|
||||
'preservealpha',
|
||||
'preserveaspectratio',
|
||||
'r',
|
||||
'rx',
|
||||
'ry',
|
||||
'radius',
|
||||
'refx',
|
||||
'refy',
|
||||
'repeatcount',
|
||||
'repeatdur',
|
||||
'restart',
|
||||
'result',
|
||||
'rotate',
|
||||
'scale',
|
||||
'seed',
|
||||
'shape-rendering',
|
||||
'specularconstant',
|
||||
'specularexponent',
|
||||
'spreadmethod',
|
||||
'stddeviation',
|
||||
'stitchtiles',
|
||||
'stop-color',
|
||||
'stop-opacity',
|
||||
'stroke-dasharray',
|
||||
'stroke-dashoffset',
|
||||
'stroke-linecap',
|
||||
'stroke-linejoin',
|
||||
'stroke-miterlimit',
|
||||
'stroke-opacity',
|
||||
'stroke',
|
||||
'stroke-width',
|
||||
'style',
|
||||
'surfacescale',
|
||||
'tabindex',
|
||||
'targetx',
|
||||
'targety',
|
||||
'transform',
|
||||
'text-anchor',
|
||||
'text-decoration',
|
||||
'text-rendering',
|
||||
'textlength',
|
||||
'type',
|
||||
'u1',
|
||||
'u2',
|
||||
'unicode',
|
||||
'values',
|
||||
'viewbox',
|
||||
'visibility',
|
||||
'vector-effect',
|
||||
'vert-adv-y',
|
||||
'vert-origin-x',
|
||||
'vert-origin-y',
|
||||
'width',
|
||||
'word-spacing',
|
||||
'wrap',
|
||||
'writing-mode',
|
||||
'xchannelselector',
|
||||
'ychannelselector',
|
||||
'x',
|
||||
'x1',
|
||||
'x2',
|
||||
'xmlns',
|
||||
'y',
|
||||
'y1',
|
||||
'y2',
|
||||
'z',
|
||||
'zoomandpan',
|
||||
|
||||
// MathML
|
||||
'accent',
|
||||
'accentunder',
|
||||
'align',
|
||||
'bevelled',
|
||||
'close',
|
||||
'columnsalign',
|
||||
'columnlines',
|
||||
'columnspan',
|
||||
'denomalign',
|
||||
'depth',
|
||||
'dir',
|
||||
'display',
|
||||
'displaystyle',
|
||||
'fence',
|
||||
'frame',
|
||||
'height',
|
||||
'href',
|
||||
'id',
|
||||
'largeop',
|
||||
'length',
|
||||
'linethickness',
|
||||
'lspace',
|
||||
'lquote',
|
||||
'mathbackground',
|
||||
'mathcolor',
|
||||
'mathsize',
|
||||
'mathvariant',
|
||||
'maxsize',
|
||||
'minsize',
|
||||
'movablelimits',
|
||||
'notation',
|
||||
'numalign',
|
||||
'open',
|
||||
'rowalign',
|
||||
'rowlines',
|
||||
'rowspacing',
|
||||
'rowspan',
|
||||
'rspace',
|
||||
'rquote',
|
||||
'scriptlevel',
|
||||
'scriptminsize',
|
||||
'scriptsizemultiplier',
|
||||
'selection',
|
||||
'separator',
|
||||
'separators',
|
||||
'slope',
|
||||
'stretchy',
|
||||
'subscriptshift',
|
||||
'supscriptshift',
|
||||
'symmetric',
|
||||
'voffset',
|
||||
'width',
|
||||
'xmlns',
|
||||
|
||||
// XML
|
||||
'xlink:href',
|
||||
'xml:id',
|
||||
'xlink:title',
|
||||
'xml:space',
|
||||
'xmlns:xlink',
|
||||
);
|
||||
}
|
||||
}
|
99
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AllowedTags.php
vendored
Normal file
99
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AllowedTags.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\data;
|
||||
|
||||
/**
|
||||
* Class AllowedTags
|
||||
*
|
||||
* @package enshrined\svgSanitize\data
|
||||
*/
|
||||
class AllowedTags implements TagInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of tags
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTags()
|
||||
{
|
||||
return array (
|
||||
// HTML
|
||||
'a',
|
||||
'font',
|
||||
'image',
|
||||
'style',
|
||||
|
||||
// SVG
|
||||
'svg',
|
||||
'altglyph',
|
||||
'altglyphdef',
|
||||
'altglyphitem',
|
||||
'animatecolor',
|
||||
'animatemotion',
|
||||
'animatetransform',
|
||||
'circle',
|
||||
'clippath',
|
||||
'defs',
|
||||
'desc',
|
||||
'ellipse',
|
||||
'filter',
|
||||
'font',
|
||||
'g',
|
||||
'glyph',
|
||||
'glyphref',
|
||||
'hkern',
|
||||
'image',
|
||||
'line',
|
||||
'lineargradient',
|
||||
'marker',
|
||||
'mask',
|
||||
'metadata',
|
||||
'mpath',
|
||||
'path',
|
||||
'pattern',
|
||||
'polygon',
|
||||
'polyline',
|
||||
'radialgradient',
|
||||
'rect',
|
||||
'stop',
|
||||
'switch',
|
||||
'symbol',
|
||||
'text',
|
||||
'textpath',
|
||||
'title',
|
||||
'tref',
|
||||
'tspan',
|
||||
'use',
|
||||
'view',
|
||||
'vkern',
|
||||
|
||||
// SVG Filters
|
||||
'feBlend',
|
||||
'feColorMatrix',
|
||||
'feComponentTransfer',
|
||||
'feComposite',
|
||||
'feConvolveMatrix',
|
||||
'feDiffuseLighting',
|
||||
'feDisplacementMap',
|
||||
'feDistantLight',
|
||||
'feFlood',
|
||||
'feFuncA',
|
||||
'feFuncB',
|
||||
'feFuncG',
|
||||
'feFuncR',
|
||||
'feGaussianBlur',
|
||||
'feMerge',
|
||||
'feMergeNode',
|
||||
'feMorphology',
|
||||
'feOffset',
|
||||
'fePointLight',
|
||||
'feSpecularLighting',
|
||||
'feSpotLight',
|
||||
'feTile',
|
||||
'feTurbulence',
|
||||
|
||||
//text
|
||||
'#text'
|
||||
);
|
||||
}
|
||||
}
|
18
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AttributeInterface.php
vendored
Normal file
18
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/AttributeInterface.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\data;
|
||||
|
||||
/**
|
||||
* Class AttributeInterface
|
||||
*
|
||||
* @package enshrined\svgSanitize\data
|
||||
*/
|
||||
interface AttributeInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAttributes();
|
||||
}
|
19
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/TagInterface.php
vendored
Normal file
19
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/TagInterface.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\data;
|
||||
|
||||
/**
|
||||
* Interface TagInterface
|
||||
*
|
||||
* @package enshrined\svgSanitize\tags
|
||||
*/
|
||||
interface TagInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of tags
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTags();
|
||||
|
||||
}
|
64
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/XPath.php
vendored
Normal file
64
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/data/XPath.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace enshrined\svgSanitize\data;
|
||||
|
||||
class XPath extends \DOMXPath
|
||||
{
|
||||
const DEFAULT_NAMESPACE_PREFIX = 'svg';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultNamespaceURI;
|
||||
|
||||
public function __construct(\DOMDocument $doc)
|
||||
{
|
||||
parent::__construct($doc);
|
||||
$this->handleDefaultNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $nodeName
|
||||
* @return string
|
||||
*/
|
||||
public function createNodeName($nodeName)
|
||||
{
|
||||
if (empty($this->defaultNamespaceURI)) {
|
||||
return $nodeName;
|
||||
}
|
||||
return self::DEFAULT_NAMESPACE_PREFIX . ':' . $nodeName;
|
||||
}
|
||||
|
||||
protected function handleDefaultNamespace()
|
||||
{
|
||||
$rootElements = $this->getRootElements();
|
||||
|
||||
if (count($rootElements) !== 1) {
|
||||
throw new \LogicException(
|
||||
sprintf('Got %d svg elements, expected exactly one', count($rootElements)),
|
||||
1570870568
|
||||
);
|
||||
}
|
||||
$this->defaultNamespaceURI = (string)$rootElements[0]->namespaceURI;
|
||||
|
||||
if ($this->defaultNamespaceURI !== '') {
|
||||
$this->registerNamespace(self::DEFAULT_NAMESPACE_PREFIX, $this->defaultNamespaceURI);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DOMElement[]
|
||||
*/
|
||||
protected function getRootElements()
|
||||
{
|
||||
$rootElements = [];
|
||||
$elements = $this->document->getElementsByTagName('svg');
|
||||
/** @var \DOMElement $element */
|
||||
foreach ($elements as $element) {
|
||||
if ($element->parentNode !== $this->document) {
|
||||
continue;
|
||||
}
|
||||
$rootElements[] = $element;
|
||||
}
|
||||
return $rootElements;
|
||||
}
|
||||
}
|
192
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/svg-scanner.php
vendored
Normal file
192
wp-content/plugins/menu-icons/vendor/enshrined/svg-sanitize/src/svg-scanner.php
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Simple program that uses svg-sanitizer
|
||||
* to find issues in files specified on the
|
||||
* command line, and prints a JSON output with
|
||||
* the issues found on exit.
|
||||
*/
|
||||
|
||||
require_once( __DIR__ . '/data/AttributeInterface.php' );
|
||||
require_once( __DIR__ . '/data/TagInterface.php' );
|
||||
require_once( __DIR__ . '/data/AllowedAttributes.php' );
|
||||
require_once( __DIR__ . '/data/AllowedTags.php' );
|
||||
require_once( __DIR__ . '/data/XPath.php' );
|
||||
require_once( __DIR__ . '/ElementReference/Resolver.php' );
|
||||
require_once( __DIR__ . '/ElementReference/Subject.php' );
|
||||
require_once( __DIR__ . '/ElementReference/Usage.php' );
|
||||
require_once( __DIR__ . '/Exceptions/NestingException.php' );
|
||||
require_once( __DIR__ . '/Helper.php' );
|
||||
require_once( __DIR__ . '/Sanitizer.php' );
|
||||
|
||||
/*
|
||||
* Print array as JSON and then
|
||||
* exit program with a particular
|
||||
* exit-code.
|
||||
*/
|
||||
|
||||
function sysexit(
|
||||
$results,
|
||||
$status
|
||||
) {
|
||||
echo json_encode(
|
||||
$results,
|
||||
JSON_PRETTY_PRINT
|
||||
);
|
||||
|
||||
exit( $status );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main part begins
|
||||
*/
|
||||
|
||||
global $argv;
|
||||
|
||||
/*
|
||||
* Set up results array, to
|
||||
* be printed on exit.
|
||||
*/
|
||||
$results = array(
|
||||
'totals' => array(
|
||||
'errors' => 0,
|
||||
),
|
||||
|
||||
'files' => array(
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Catch files to scan from $argv.
|
||||
*/
|
||||
|
||||
$files_to_scan = $argv;
|
||||
unset( $files_to_scan[0] );
|
||||
|
||||
$files_to_scan = array_values(
|
||||
$files_to_scan
|
||||
);
|
||||
|
||||
/*
|
||||
* Catch no file specified.
|
||||
*/
|
||||
|
||||
if ( empty( $files_to_scan ) ) {
|
||||
$results['totals']['errors']++;
|
||||
$results['messages'] = array(
|
||||
array( 'No files to scan specified' ),
|
||||
);
|
||||
|
||||
sysexit(
|
||||
$results,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the SVG scanner.
|
||||
*
|
||||
* Make sure to allow custom attributes,
|
||||
* and to remove remote references.
|
||||
*/
|
||||
$sanitizer = new enshrined\svgSanitize\Sanitizer();
|
||||
|
||||
$sanitizer->removeRemoteReferences( true );
|
||||
|
||||
/*
|
||||
* Scan each file specified to be scanned.
|
||||
*/
|
||||
|
||||
foreach( $files_to_scan as $file_name ) {
|
||||
/*
|
||||
* Read SVG file.
|
||||
*/
|
||||
$svg_file = @file_get_contents( $file_name );
|
||||
|
||||
/*
|
||||
* If not found, report that and continue.
|
||||
*/
|
||||
if ( false === $svg_file ) {
|
||||
$results['totals']['errors']++;
|
||||
|
||||
$results['files'][ $file_name ][] = array(
|
||||
'errors' => 1,
|
||||
'messages' => array(
|
||||
array(
|
||||
'message' => 'File specified could not be read (' . $file_name . ')',
|
||||
'line' => null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanitize file and get issues found.
|
||||
*/
|
||||
$sanitize_status = $sanitizer->sanitize( $svg_file );
|
||||
|
||||
$xml_issues = $sanitizer->getXmlIssues();
|
||||
|
||||
/*
|
||||
* If we find no issues, simply note that.
|
||||
*/
|
||||
if ( empty( $xml_issues ) && ( false !== $sanitize_status ) ) {
|
||||
$results['files'][ $file_name ] = array(
|
||||
'errors' => 0,
|
||||
'messages' => array()
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Could not sanitize the file.
|
||||
*/
|
||||
else if (
|
||||
( '' === $sanitize_status ) ||
|
||||
( false === $sanitize_status )
|
||||
) {
|
||||
$results['totals']['errors']++;
|
||||
|
||||
$results['files'][ $file_name ] = array(
|
||||
'errors' => 1,
|
||||
'messages' => array(
|
||||
array(
|
||||
'message' => 'Unable to sanitize file \'' . $file_name . '\'' ,
|
||||
'line' => null,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we find issues, note it and update statistics.
|
||||
*/
|
||||
|
||||
else {
|
||||
$results['totals']['errors'] += count( $xml_issues );
|
||||
|
||||
$results['files'][ $file_name ] = array(
|
||||
'errors' => count( $xml_issues ),
|
||||
'messages' => $xml_issues,
|
||||
);
|
||||
}
|
||||
|
||||
unset( $svg_file );
|
||||
unset( $xml_issues );
|
||||
unset( $sanitize_status );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Exit with a status
|
||||
* that reflects what issues
|
||||
* we found.
|
||||
*/
|
||||
sysexit(
|
||||
$results,
|
||||
( $results['totals']['errors'] === 0 ? 0 : 1 )
|
||||
);
|
Reference in New Issue
Block a user