function SourceEditingPreventSelfXssConstraintValidator::validate

Same name in other branches
  1. 10 core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php \Drupal\ckeditor5\Plugin\Validation\Constraint\SourceEditingPreventSelfXssConstraintValidator::validate()
  2. 11.x core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php \Drupal\ckeditor5\Plugin\Validation\Constraint\SourceEditingPreventSelfXssConstraintValidator::validate()

Throws

\Symfony\Component\Validator\Exception\UnexpectedTypeException Thrown when the given constraint is not supported by this validator.

File

core/modules/ckeditor5/src/Plugin/Validation/Constraint/SourceEditingPreventSelfXssConstraintValidator.php, line 27

Class

SourceEditingPreventSelfXssConstraintValidator
Ensures Source Editing cannot be configured to allow self-XSS.

Namespace

Drupal\ckeditor5\Plugin\Validation\Constraint

Code

public function validate($value, Constraint $constraint) {
    if (!$constraint instanceof SourceEditingPreventSelfXssConstraint) {
        throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\\SourceEditingPreventSelfXssConstraint');
    }
    if (empty($value)) {
        return;
    }
    $restrictions = HTMLRestrictions::fromString($value);
    // @todo Remove this early return in
    //   https://www.drupal.org/project/drupal/issues/2820364. It is only
    //   necessary because CKEditor5ElementConstraintValidator does not run
    //   before this, which means that this validator cannot assume it receives
    //   valid values.
    if ($restrictions->allowsNothing() || count($restrictions->getAllowedElements()) > 1) {
        return;
    }
    // This validation constraint only validates attributes, not tags; so if all
    // attributes are allowed (TRUE) or no attributes are allowed (FALSE),
    // return early. Only proceed when some attributes are allowed (an array).
    $allowed_elements = $restrictions->getAllowedElements(FALSE);
    assert(count($allowed_elements) === 1);
    $tag = array_key_first($allowed_elements);
    $attribute_restrictions = $allowed_elements[$tag];
    if (!is_array($attribute_restrictions)) {
        return;
    }
    $text_editor = $this->createTextEditorObjectFromContext();
    $text_format_allowed_elements = HTMLRestrictions::fromTextFormat($text_editor->getFilterFormat())
        ->getAllowedElements();
    // Any XSS-prevention related measures imposed by filter plugins are relayed
    // through their ::getHtmlRestrictions() return value. The global attribute
    // `*` HTML tag allows attributes to be forbidden.
    // @see https://html.spec.whatwg.org/multipage/dom.html#global-attributes
    // @see \Drupal\ckeditor5\HTMLRestrictions::validateAllowedRestrictionsPhase4()
    // @see \Drupal\filter\Plugin\Filter\FilterHtml::getHTMLRestrictions()
    $forbidden_attributes = [];
    if (array_key_exists('*', $text_format_allowed_elements)) {
        $forbidden_attributes = array_keys(array_filter($text_format_allowed_elements['*'], function ($attribute_value_restriction, string $attribute_name) {
            return $attribute_value_restriction === FALSE;
        }, ARRAY_FILTER_USE_BOTH));
    }
    foreach ($forbidden_attributes as $forbidden_attribute_name) {
        // Forbidden attributes not containing wildcards, such as `style`.
        if (!self::isWildcardAttributeName($forbidden_attribute_name)) {
            if (array_key_exists($forbidden_attribute_name, $attribute_restrictions)) {
                $this->context
                    ->buildViolation($constraint->message)
                    ->setParameter('%dangerous_tag', $value)
                    ->addViolation();
            }
        }
        else {
            $regex = self::getRegExForWildCardAttributeName($forbidden_attribute_name);
            if (!empty(preg_grep($regex, array_keys($attribute_restrictions)))) {
                $this->context
                    ->buildViolation($constraint->message)
                    ->setParameter('%dangerous_tag', $value)
                    ->addViolation();
            }
        }
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.