Seditio Source
Root |
./othercms/phpBB3/vendor/s9e/text-formatter/src/Configurator/TemplateChecks/DisallowXPathFunction.php
<?php

/**
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2021 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Configurator\TemplateChecks;

use
DOMElement;
use
DOMXPath;
use
s9e\TextFormatter\Configurator\Exceptions\UnsafeTemplateException;
use
s9e\TextFormatter\Configurator\Helpers\AVTHelper;
use
s9e\TextFormatter\Configurator\Items\Tag;
use
s9e\TextFormatter\Configurator\TemplateCheck;

class
DisallowXPathFunction extends TemplateCheck
{
   
/**
    * @var string Name of the disallowed function
    */
   
public $funcName;

   
/**
    * Constructor
    *
    * @param  string $funcName Name of the disallowed function
    */
   
public function __construct($funcName)
    {
       
$this->funcName = $funcName;
    }

   
/**
    * Test for the presence of given XPath function
    *
    * @param  DOMElement $template <xsl:template/> node
    * @param  Tag        $tag      Tag this template belongs to
    * @return void
    */
   
public function check(DOMElement $template, Tag $tag)
    {
       
// Regexp that matches the function call
       
$regexp = '#(?!<\\pL)' . preg_quote($this->funcName, '#') . '\\s*\\(#iu';

       
// Allow whitespace around colons (NOTE: colons are unnecessarily escaped by preg_quote())
       
$regexp = str_replace('\\:', '\\s*:\\s*', $regexp);

        foreach (
$this->getExpressions($template) as $expr => $node)
        {
           
// Remove string literals from the expression
           
$expr = preg_replace('#([\'"]).*?\\1#s', '', $expr);

           
// Test whether the expression contains a document() call
           
if (preg_match($regexp, $expr))
            {
                throw new
UnsafeTemplateException('An XPath expression uses the ' . $this->funcName . '() function', $node);
            }
        }
    }

   
/**
    * Get all the potential XPath expressions used in given template
    *
    * @param  DOMElement $template <xsl:template/> node
    * @return array                XPath expression as key, reference node as value
    */
   
protected function getExpressions(DOMElement $template)
    {
       
$xpath = new DOMXPath($template->ownerDocument);
       
$exprs = [];

        foreach (
$xpath->query('//@*') as $attribute)
        {
            if (
$attribute->parentNode->namespaceURI === self::XMLNS_XSL)
            {
               
// Attribute of an XSL element. May or may not use XPath, but it shouldn't produce
                // false-positives
               
$expr = $attribute->value;
               
$exprs[$expr] = $attribute;
            }
            else
            {
               
// Attribute of an HTML (or otherwise) element -- Look for inline expressions
               
foreach (AVTHelper::parse($attribute->value) as $token)
                {
                    if (
$token[0] === 'expression')
                    {
                       
$exprs[$token[1]] = $attribute;
                    }
                }
            }
        }

        return
$exprs;
    }
}