Вход Регистрация
Файл: vendor/symfony/html-sanitizer/HtmlSanitizer.php
Строк: 252
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentHtmlSanitizer;

use 
SymfonyComponentHtmlSanitizerParserMastermindsParser;
use 
SymfonyComponentHtmlSanitizerParserNativeParser;
use 
SymfonyComponentHtmlSanitizerParserParserInterface;
use 
SymfonyComponentHtmlSanitizerReferenceW3CReference;
use 
SymfonyComponentHtmlSanitizerTextSanitizerStringSanitizer;
use 
SymfonyComponentHtmlSanitizerVisitorDomVisitor;

/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
final class HtmlSanitizer implements HtmlSanitizerInterface
{
    private 
ParserInterface $parser;

    
/**
     * @var array<string, DomVisitor>
     */
    
private array $domVisitors = [];

    public function 
__construct(
        private 
HtmlSanitizerConfig $config,
        ?
ParserInterface $parser null,
    ) {
        
$this->parser $parser ?? (PHP_VERSION_ID 80400 ? new MastermindsParser() : new NativeParser());
    }

    public function 
sanitize(string $input): string
    
{
        return 
$this->sanitizeFor(W3CReference::CONTEXT_BODY$input);
    }

    public function 
sanitizeFor(string $elementstring $input): string
    
{
        
$element StringSanitizer::htmlLower($element);
        
$context W3CReference::CONTEXTS_MAP[$element] ?? W3CReference::CONTEXT_BODY;
        
$element = isset(W3CReference::BODY_ELEMENTS[$element]) ? $element $context;

        
// Prevent DOS attack induced by extremely long HTML strings
        
if (-!== $this->config->getMaxInputLength() && strlen($input) > $this->config->getMaxInputLength()) {
            
$input substr($input0$this->config->getMaxInputLength());
        }

        
// Text context: early return with HTML encoding
        
if (W3CReference::CONTEXT_TEXT === $context) {
            return 
StringSanitizer::encodeHtmlEntities($input);
        }

        
// Other context: build a DOM visitor
        
$this->domVisitors[$context] ??= $this->createDomVisitorForContext($context);

        
// Only operate on valid UTF-8 strings. This is necessary to prevent cross
        // site scripting issues on Internet Explorer 6. Idea from Drupal (filter_xss).
        
if (!$this->isValidUtf8($input)) {
            return 
'';
        }

        
// Remove NULL character and HTML entities for null byte
        
$input str_replace([chr(0), '&#0;''&#x00;''&#X00;''&#000;'], '�'$input);

        
// Parse as HTML
        
if ('' === trim($input) || !$parsed $this->parser->parse($input$element)) {
            return 
'';
        }

        
// Visit the DOM tree and render the sanitized nodes
        
return $this->domVisitors[$context]->visit($parsed)?->render() ?? '';
    }

    private function 
isValidUtf8(string $html): bool
    
{
        
// preg_match() fails silently on strings containing invalid UTF-8.
        
return '' === $html || preg_match('//u'$html);
    }

    private function 
createDomVisitorForContext(string $context): DomVisitor
    
{
        
$elementsConfig = [];

        
// Head: only a few elements are allowed
        
if (W3CReference::CONTEXT_HEAD === $context) {
            foreach (
$this->config->getAllowedElements() as $allowedElement => $allowedAttributes) {
                if (
array_key_exists($allowedElementW3CReference::HEAD_ELEMENTS)) {
                    
$elementsConfig[$allowedElement] = $allowedAttributes;
                }
            }

            foreach (
$this->config->getBlockedElements() as $blockedElement => $v) {
                if (
array_key_exists($blockedElementW3CReference::HEAD_ELEMENTS)) {
                    
$elementsConfig[$blockedElement] = HtmlSanitizerAction::Block;
                }
            }

            foreach (
$this->config->getDroppedElements() as $droppedElement => $v) {
                if (
array_key_exists($droppedElementW3CReference::HEAD_ELEMENTS)) {
                    
$elementsConfig[$droppedElement] = HtmlSanitizerAction::Drop;
                }
            }

            return new 
DomVisitor($this->config$elementsConfig);
        }

        
// Body: allow any configured element that isn't in <head>
        
foreach ($this->config->getAllowedElements() as $allowedElement => $allowedAttributes) {
            if (!
array_key_exists($allowedElementW3CReference::HEAD_ELEMENTS)) {
                
$elementsConfig[$allowedElement] = $allowedAttributes;
            }
        }

        foreach (
$this->config->getBlockedElements() as $blockedElement => $v) {
            if (!
array_key_exists($blockedElementW3CReference::HEAD_ELEMENTS)) {
                
$elementsConfig[$blockedElement] = HtmlSanitizerAction::Block;
            }
        }

        foreach (
$this->config->getDroppedElements() as $droppedElement => $v) {
            if (!
array_key_exists($droppedElementW3CReference::HEAD_ELEMENTS)) {
                
$elementsConfig[$droppedElement] = HtmlSanitizerAction::Drop;
            }
        }

        return new 
DomVisitor($this->config$elementsConfig);
    }
}
Онлайн: 2
Реклама