![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/framework/Validator/HTML/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Magento\Framework\Validator\HTML; use Magento\Framework\Validation\ValidationException; /** * Validates user HTML based on configuration. */ class ConfigurableWYSIWYGValidator implements WYSIWYGValidatorInterface { /** * @var string[] */ private $allowedTags; /** * @var string[] */ private $allowedAttributes; /** * @var string[] */ private $attributesAllowedByTags; /** * @var AttributeValidatorInterface[][] */ private $attributeValidators; /** * @var TagValidatorInterface[][] */ private $tagValidators; /** * @param string[] $allowedTags * @param string[] $allowedAttributes * @param string[][] $attributesAllowedByTags * @param AttributeValidatorInterface[][] $attributeValidators * @param TagValidatorInterface[][] $tagValidators */ public function __construct( array $allowedTags, array $allowedAttributes = [], array $attributesAllowedByTags = [], array $attributeValidators = [], array $tagValidators = [] ) { if (empty(array_filter($allowedTags))) { throw new \InvalidArgumentException('List of allowed HTML tags cannot be empty'); } $this->allowedTags = array_unique($allowedTags); $this->allowedAttributes = array_unique($allowedAttributes); $this->attributesAllowedByTags = array_filter( $attributesAllowedByTags, function (string $tag) use ($allowedTags): bool { return in_array($tag, $allowedTags, true); }, ARRAY_FILTER_USE_KEY ); $this->attributeValidators = $attributeValidators; $this->tagValidators = $tagValidators; } /** * @inheritDoc */ public function validate(string $content): void { if (mb_strlen($content) === 0) { return; } $dom = $this->loadHtml($content); $xpath = new \DOMXPath($dom); $this->validateConfigured($xpath); $this->callAttributeValidators($xpath); $this->callTagValidators($xpath); } /** * Check declarative restrictions * * @param \DOMXPath $xpath * @return void * @throws ValidationException */ private function validateConfigured(\DOMXPath $xpath): void { //Validating tags $found = $xpath->query( '//*[' . implode( ' and ', array_map( function (string $tag): string { return "name() != '$tag'"; }, array_merge($this->allowedTags, ['body', 'html']) ) ) .']' ); if (count($found)) { throw new ValidationException( __('Allowed HTML tags are: %1', implode(', ', $this->allowedTags)) ); } //Validating attributes if ($this->attributesAllowedByTags) { foreach ($this->allowedTags as $tag) { $allowed = [$this->allowedAttributes]; if (!empty($this->attributesAllowedByTags[$tag])) { $allowed[] = $this->attributesAllowedByTags[$tag]; } // phpcs:ignore Magento2.Performance.ForeachArrayMerge $allowed = array_unique(array_merge(...$allowed)); $allowedQuery = ''; if ($allowed) { $allowedQuery = '[' . implode( ' and ', array_map( function (string $attribute): string { return "name() != '$attribute'"; }, $allowed ) ) .']'; } $found = $xpath->query("//$tag/@*$allowedQuery"); if (count($found)) { throw new ValidationException( __('Allowed HTML attributes for tag "%1" are: %2', $tag, implode(',', $allowed)) ); } } } else { $allowed = ''; if ($this->allowedAttributes) { $allowed = '[' . implode( ' and ', array_map( function (string $attribute): string { return "name() != '$attribute'"; }, $this->allowedAttributes ) ) .']'; } $found = $xpath->query("//@*$allowed"); if (count($found)) { throw new ValidationException( __('Allowed HTML attributes are: %1', implode(',', $this->allowedAttributes)) ); } } } /** * Validate allowed HTML attributes' content. * * @param \DOMXPath $xpath * @throws ValidationException * @return void */ private function callAttributeValidators(\DOMXPath $xpath): void { if ($this->attributeValidators) { foreach ($this->attributeValidators as $attr => $validators) { $found = $xpath->query("//@*[name() = '$attr']"); foreach ($found as $attribute) { foreach ($validators as $validator) { $validator->validate($attribute->parentNode->tagName, $attribute->name, $attribute->value); } } } } } /** * Validate allowed tags. * * @param \DOMXPath $xpath * @return void * @throws ValidationException */ private function callTagValidators(\DOMXPath $xpath): void { if ($this->tagValidators) { foreach ($this->tagValidators as $tag => $validators) { $found = $xpath->query("//*[name() = '$tag']"); /** @var \DOMElement $tagNode */ foreach ($found as $tagNode) { $attributes = []; if ($tagNode->hasAttributes()) { /** @var \DOMAttr $attributeNode */ foreach ($tagNode->attributes as $attributeNode) { $attributes[$attributeNode->name] = $attributeNode->value; } } foreach ($validators as $validator) { $validator->validate($tagNode->tagName, $attributes, $tagNode->textContent, $this); } } } } } /** * Load DOM. * * @param string $content * @return \DOMDocument * @throws ValidationException */ private function loadHtml(string $content): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); set_error_handler( function () use (&$loaded) { $loaded = false; } ); $loaded = $dom->loadHTML("<html><body>$content</body></html>"); restore_error_handler(); if (!$loaded) { throw new ValidationException(__('Invalid HTML content provided')); } return $dom; } }