Файловый менеджер - Редактировать - /var/www/html/ElementReference.zip
Ðазад
PK ! �o�6 Resolver.phpnu �[��� <?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() ); } }PK ! � ]c Subject.phpnu �[��� <?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; } }PK ! �U-]� � Usage.phpnu �[��� <?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; } }PK ! �o�6 Resolver.phpnu �[��� PK ! � ]c S Subject.phpnu �[��� PK ! �U-]� � �"