• Resolved sebulka100

    (@sebulka100)


    Hello i have issue with new update, i have fatal error and site is down. How i can resolve this problem?

    Fatal error: Cannot declare class enshrined\svgSanitize\Sanitizer, because the name is already in use in /home/platne/serwer248429/public_html/nancybizuteria.pl/wp-content/plugins/header-footer-elementor/inc/lib/svg-sanitizer/src/Sanitizer.php on line 16
    <?php
    namespace enshrined\svgSanitize;
    
    use enshrined\svgSanitize\data\AllowedAttributes;
    use enshrined\svgSanitize\data\AllowedTags;
    use enshrined\svgSanitize\data\AttributeInterface;
    use enshrined\svgSanitize\data\TagInterface;
    use enshrined\svgSanitize\data\XPath;
    use enshrined\svgSanitize\ElementReference\Resolver;
    
    /**
     * Class Sanitizer
     *
     * @package enshrined\svgSanitize
     */
     class Sanitizer
    {
    
        /**
         * @var \DOMDocument
         */
        protected $xmlDocument;
    
        /**
         * @var array
         */
        protected $allowedTags;
    
        /**
         * @var array
         */
        protected $allowedAttrs;
    
        /**
         * @var
         */
        protected $xmlLoaderValue;
    
        /**
         * @var bool
         */
        protected $xmlErrorHandlerPreviousValue;
    
        /**
         * @var bool
         */
        protected $minifyXML = false;
    
        /**
         * @var bool
         */
        protected $removeRemoteReferences = false;
    
        /**
         * @var int
         */
        protected $useThreshold = 1000;
    
        /**
         * @var bool
         */
        protected $removeXMLTag = false;
    
        /**
         * @var int
         */
        protected $xmlOptions = LIBXML_NOEMPTYTAG;
    
        /**
         * @var array
         */
        protected $xmlIssues = array();
    
        /**
         * @var Resolver
         */
        protected $elementReferenceResolver;
    
        /**
         * @var int
         */
        protected $useNestingLimit = 15;
    
        /**
         * @var bool
         */
        protected $allowHugeFiles = false;
    
        /**
         *
         */
        function __construct()
        {
            // Load default tags/attributes
            $this->allowedAttrs = array_map('strtolower', AllowedAttributes::getAttributes());
            $this->allowedTags = array_map('strtolower', AllowedTags::getTags());
        }
    
        /**
         * Set up the DOMDocument
         */
        protected function resetInternal()
        {
            $this->xmlDocument = new \DOMDocument();
            $this->xmlDocument->preserveWhiteSpace = false;
            $this->xmlDocument->strictErrorChecking = false;
            $this->xmlDocument->formatOutput = !$this->minifyXML;
        }
    
        /**
         * Set XML options to use when saving XML
         * See: DOMDocument::saveXML
         *
         * @param int  $xmlOptions
         */
        public function setXMLOptions($xmlOptions)
        {
            $this->xmlOptions = $xmlOptions;
        }
    
        /**
         * Get XML options to use when saving XML
         * See: DOMDocument::saveXML
         *
         * @return int
         */
        public function getXMLOptions()
        {
            return $this->xmlOptions;
        }
    
        /**
         * Get the array of allowed tags
         *
         * @return array
         */
        public function getAllowedTags()
        {
            return $this->allowedTags;
        }
    
        /**
         * Set custom allowed tags
         *
         * @param TagInterface $allowedTags
         */
        public function setAllowedTags(TagInterface $allowedTags)
        {
            $this->allowedTags = array_map('strtolower', $allowedTags::getTags());
        }
    
        /**
         * Get the array of allowed attributes
         *
         * @return array
         */
        public function getAllowedAttrs()
        {
            return $this->allowedAttrs;
        }
    
        /**
         * Set custom allowed attributes
         *
         * @param AttributeInterface $allowedAttrs
         */
        public function setAllowedAttrs(AttributeInterface $allowedAttrs)
        {
            $this->allowedAttrs = array_map('strtolower', $allowedAttrs::getAttributes());
        }
    
        /**
         * Should we remove references to remote files?
         *
         * @param bool $removeRemoteRefs
         */
        public function removeRemoteReferences($removeRemoteRefs = false)
        {
            $this->removeRemoteReferences = $removeRemoteRefs;
        }
    
        /**
         * Get XML issues.
         *
         * @return array
         */
        public function getXmlIssues() {
            return $this->xmlIssues;
        }
    
        /**
         * Can we allow huge files?
         *
         * @return bool
         */
        public function getAllowHugeFiles() {
            return $this->allowHugeFiles;
        }
    
        /**
         * Set whether we can allow huge files.
         *
         * @param bool $allowHugeFiles
         */
        public function setAllowHugeFiles( $allowHugeFiles ) {
            $this->allowHugeFiles = $allowHugeFiles;
        }
    
    
        /**
         * Sanitize the passed string
         *
         * @param string $dirty
         * @return string|false
         */
        public function sanitize($dirty)
        {
            // Don't run on an empty string
            if (empty($dirty)) {
                return '';
            }
    
            // Strip php tags
            $dirty = preg_replace('/<\?(=|php)(.+?)\?>/i', '', $dirty);
    
            $this->resetInternal();
            $this->setUpBefore();
    
            $loaded = $this->xmlDocument->loadXML($dirty, $this->getAllowHugeFiles() ? LIBXML_PARSEHUGE : 0);
    
            // If we couldn't parse the XML then we go no further. Reset and return false
            if (!$loaded) {
                $this->resetAfter();
                return false;
            }
    
            // Pre-process all identified elements
            $xPath = new XPath($this->xmlDocument);
            $this->elementReferenceResolver = new Resolver($xPath, $this->useNestingLimit);
            $this->elementReferenceResolver->collect();
            $elementsToRemove = $this->elementReferenceResolver->getElementsToRemove();
    
            // Start the cleaning process
            $this->startClean($this->xmlDocument->childNodes, $elementsToRemove);
    
            // Save cleaned XML to a variable
            if ($this->removeXMLTag) {
                $clean = $this->xmlDocument->saveXML($this->xmlDocument->documentElement, $this->xmlOptions);
            } else {
                $clean = $this->xmlDocument->saveXML($this->xmlDocument, $this->xmlOptions);
            }
    
            $this->resetAfter();
    
            // Remove any extra whitespaces when minifying
            if ($this->minifyXML) {
                $clean = preg_replace('/\s+/', ' ', $clean);
            }
    
            // Return result
            return $clean;
        }
    
        /**
         * Set up libXML before we start
         */
        protected function setUpBefore()
        {
            // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
            // disabled by default, so this function is no longer needed to protect against XXE attacks.
            if (\LIBXML_VERSION < 20900) {
                // Turn off the entity loader
                $this->xmlLoaderValue = libxml_disable_entity_loader(true);
            }
    
            // Suppress the errors because we don't really have to worry about formation before cleansing.
            // See reset in resetAfter().
            $this->xmlErrorHandlerPreviousValue = libxml_use_internal_errors(true);
    
            // Reset array of altered XML
            $this->xmlIssues = array();
        }
    
        /**
         * Reset the class after use
         */
        protected function resetAfter()
        {
            // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
            // disabled by default, so this function is no longer needed to protect against XXE attacks.
            if (\LIBXML_VERSION < 20900) {
                // Reset the entity loader
                libxml_disable_entity_loader($this->xmlLoaderValue);
            }
    
            libxml_clear_errors();
            libxml_use_internal_errors($this->xmlErrorHandlerPreviousValue);
        }
    
        /**
         * Start the cleaning with tags, then we move onto attributes and hrefs later
         *
         * @param \DOMNodeList $elements
         * @param array        $elementsToRemove
         */
        protected function startClean(\DOMNodeList $elements, array $elementsToRemove)
        {
            // loop through all elements
            // we do this backwards so we don't skip anything if we delete a node
            // see comments at: http://php.net/manual/en/class.domnamednodemap.php
            for ($i = $elements->length - 1; $i >= 0; $i--) {
                /** @var \DOMElement $currentElement */
                $currentElement = $elements->item($i);
    
                /**
                 * If the element has exceeded the nesting limit, we should remove it.
                 *
                 * As it's only <use> elements that cause us issues with nesting DOS attacks
                 * we should check what the element is before removing it. For now we'll only
                 * remove <use> elements.
                 */
                if (in_array($currentElement, $elementsToRemove) && 'use' === $currentElement->nodeName) {
                    $currentElement->parentNode->removeChild($currentElement);
                    $this->xmlIssues[] = array(
                        'message' => 'Invalid \'' . $currentElement->tagName . '\'',
                        'line'    => $currentElement->getLineNo(),
                    );
                    continue;
                }
    
                if ($currentElement instanceof \DOMElement) {
                    // If the tag isn't in the whitelist, remove it and continue with next iteration
                    if (!in_array(strtolower($currentElement->tagName), $this->allowedTags)) {
                        $currentElement->parentNode->removeChild($currentElement);
                        $this->xmlIssues[] = array(
                            'message' => 'Suspicious tag \'' . $currentElement->tagName . '\'',
                            'line' => $currentElement->getLineNo(),
                        );
                        continue;
                    }
    
                    $this->cleanHrefs( $currentElement );
    
                    $this->cleanXlinkHrefs( $currentElement );
    
                    $this->cleanAttributesOnWhitelist($currentElement);
    
                    if (strtolower($currentElement->tagName) === 'use') {
                        if ($this->isUseTagDirty($currentElement)
                            || $this->isUseTagExceedingThreshold($currentElement)
                        ) {
                            $currentElement->parentNode->removeChild($currentElement);
                            $this->xmlIssues[] = array(
                                'message' => 'Suspicious \'' . $currentElement->tagName . '\'',
                                'line' => $currentElement->getLineNo(),
                            );
                            continue;
                        }
                    }
    
                    // Strip out font elements that will break out of foreign content.
                    if (strtolower($currentElement->tagName) === 'font') {
                        $breaksOutOfForeignContent = false;
                        for ($x = $currentElement->attributes->length - 1; $x >= 0; $x--) {
                            // get attribute name
                            $attrName = $currentElement->attributes->item( $x )->name;
    
                            if (in_array(strtolower($attrName), ['face', 'color', 'size'])) {
                                $breaksOutOfForeignContent = true;
                            }
                        }
    
                        if ($breaksOutOfForeignContent) {
                            $currentElement->parentNode->removeChild($currentElement);
                            $this->xmlIssues[] = array(
                                'message' => 'Suspicious tag \'' . $currentElement->tagName . '\'',
                                'line' => $currentElement->getLineNo(),
                            );
                            continue;
                        }
                    }
                }
    
                $this->cleanUnsafeNodes($currentElement);
    
                if ($currentElement->hasChildNodes()) {
                    $this->startClean($currentElement->childNodes, $elementsToRemove);
                }
            }
        }
    
        /**
         * Only allow attributes that are on the whitelist
         *
         * @param \DOMElement $element
         */
        protected function cleanAttributesOnWhitelist(\DOMElement $element)
        {
            for ($x = $element->attributes->length - 1; $x >= 0; $x--) {
                // get attribute name
                $attrName = $element->attributes->item($x)->name;
    
                // Remove attribute if not in whitelist
                if (!in_array(strtolower($attrName), $this->allowedAttrs) && !$this->isAriaAttribute(strtolower($attrName)) && !$this->isDataAttribute(strtolower($attrName))) {
    
                    $element->removeAttribute($attrName);
                    $this->xmlIssues[] = array(
                        'message' => 'Suspicious attribute \'' . $attrName . '\'',
                        'line' => $element->getLineNo(),
                    );
                }
    
                /**
                 * This is used for when a namespace isn't imported properly.
                 * Such as xlink:href when the xlink namespace isn't imported.
                 * We have to do this as the link is still ran in this case.
                 */
                if (false !== strpos($attrName, 'href')) {
                    $href = $element->getAttribute($attrName);
                    if (false === $this->isHrefSafeValue($href)) {
                        $element->removeAttribute($attrName);
                        $this->xmlIssues[] = array(
                            'message' => 'Suspicious attribute \'href\'',
                            'line'    => $element->getLineNo(),
                        );
                    }
                }
    
                // Do we want to strip remote references?
                if($this->removeRemoteReferences) {
                    // Remove attribute if it has a remote reference
                    if (isset($element->attributes->item($x)->value) && $this->hasRemoteReference($element->attributes->item($x)->value)) {
                        $element->removeAttribute($attrName);
                        $this->xmlIssues[] = array(
                            'message' => 'Suspicious attribute \'' . $attrName . '\'',
                            'line' => $element->getLineNo(),
                        );
                    }
                }
            }
        }
    
        /**
         * Clean the xlink:hrefs of script and data embeds
         *
         * @param \DOMElement $element
         */
        protected function cleanXlinkHrefs(\DOMElement $element)
        {
            $xlinks = $element->getAttributeNS('http://www.w3.org/1999/xlink', 'href');
            if (false === $this->isHrefSafeValue($xlinks)) {
                $element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' );
                $this->xmlIssues[] = array(
                    'message' => 'Suspicious attribute \'href\'',
                    'line' => $element->getLineNo(),
                );
            }
        }
    
        /**
         * Clean the hrefs of script and data embeds
         *
         * @param \DOMElement $element
         */
        protected function cleanHrefs(\DOMElement $element)
        {
            $href = $element->getAttribute('href');
            if (false === $this->isHrefSafeValue($href)) {
                $element->removeAttribute('href');
                $this->xmlIssues[] = array(
                    'message' => 'Suspicious attribute \'href\'',
                    'line' => $element->getLineNo(),
                );
            }
        }
    
        /**
         * Only allow whitelisted starts to be within the href.
         *
         * This will stop scripts etc from being passed through, with or without attempting to hide bypasses.
         * This stops the need for us to use a complicated script regex.
         *
         * @param $value
         * @return bool
         */
        protected function isHrefSafeValue($value) {
    
            // Allow empty values
            if (empty($value)) {
                return true;
            }
    
            // Allow fragment identifiers.
            if ('#' === substr($value, 0, 1)) {
                return true;
            }
    
            // Allow relative URIs.
            if ('/' === substr($value, 0, 1)) {
                return true;
            }
    
            // Allow HTTPS domains.
            if ('https://' === substr($value, 0, 8)) {
                return true;
            }
    
            // Allow HTTP domains.
            if ('http://' === substr($value, 0, 7)) {
                return true;
            }
    
            // Allow known data URIs.
            if (in_array(substr($value, 0, 14), array(
                'data:image/png', // PNG
                'data:image/gif', // GIF
                'data:image/jpg', // JPG
                'data:image/jpe', // JPEG
                'data:image/pjp', // PJPEG
            ))) {
                return true;
            }
    
            // Allow known short data URIs.
            if (in_array(substr($value, 0, 12), array(
                'data:img/png', // PNG
                'data:img/gif', // GIF
                'data:img/jpg', // JPG
                'data:img/jpe', // JPEG
                'data:img/pjp', // PJPEG
            ))) {
                return true;
            }
    
            return false;
        }
    
        /**
         * Removes non-printable ASCII characters from string & trims it
         *
         * @param string $value
         * @return bool
         */
        protected function removeNonPrintableCharacters($value)
        {
            return trim(preg_replace('/[^ -~]/xu','',$value));
        }
    
        /**
         * Does this attribute value have a remote reference?
         *
         * @param $value
         * @return bool
         */
        protected function hasRemoteReference($value)
        {
            $value = $this->removeNonPrintableCharacters($value);
    
            $wrapped_in_url = preg_match('~^url\(\s*[\'"]\s*(.*)\s*[\'"]\s*\)$~xi', $value, $match);
            if (!$wrapped_in_url){
                return false;
            }
    
            $value = trim($match[1], '\'"');
    
            return preg_match('~^((https?|ftp|file):)?//~xi', $value);
        }
    
        /**
         * Should we minify the output?
         *
         * @param bool $shouldMinify
         */
        public function minify($shouldMinify = false)
        {
            $this->minifyXML = (bool) $shouldMinify;
        }
    
        /**
         * Should we remove the XML tag in the header?
         *
         * @param bool $removeXMLTag
         */
        public function removeXMLTag($removeXMLTag = false)
        {
            $this->removeXMLTag = (bool) $removeXMLTag;
        }
    
        /**
         * Whether <use ... xlink:href="#identifier"> elements shall be
         * removed in case expansion would exceed this threshold.
         *
         * @param int $useThreshold
         */
        public function useThreshold($useThreshold = 1000)
        {
            $this->useThreshold = (int)$useThreshold;
        }
    
        /**
         * Check to see if an attribute is an aria attribute or not
         *
         * @param $attributeName
         *
         * @return bool
         */
        protected function isAriaAttribute($attributeName)
        {
            return strpos($attributeName, 'aria-') === 0;
        }
    
        /**
         * Check to see if an attribute is an data attribute or not
         *
         * @param $attributeName
         *
         * @return bool
         */
        protected function isDataAttribute($attributeName)
        {
            return strpos($attributeName, 'data-') === 0;
        }
    
        /**
         * Make sure our use tag is only referencing internal resources
         *
         * @param \DOMElement $element
         * @return bool
         */
        protected function isUseTagDirty(\DOMElement $element)
        {
            $href = Helper::getElementHref($element);
            return $href && strpos($href, '#') !== 0;
        }
    
        /**
         * Determines whether <use ... xlink:href="#identifier"> is expanded
         * recursively in order to create DoS scenarios. The amount of a actually
         * used element needs to be below $this->useThreshold.
         *
         * @param \DOMElement $element
         * @return bool
         */
        protected function isUseTagExceedingThreshold(\DOMElement $element)
        {
            if ($this->useThreshold <= 0) {
                return false;
            }
            $useId = Helper::extractIdReferenceFromHref(
                Helper::getElementHref($element)
            );
            if ($useId === null) {
                return false;
            }
            foreach ($this->elementReferenceResolver->findByElementId($useId) as $subject) {
                if ($subject->countUse() >= $this->useThreshold) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * Set the nesting limit for <use> tags.
         *
         * @param $limit
         */
        public function setUseNestingLimit($limit)
        {
            $this->useNestingLimit = (int) $limit;
        }
    
        /**
         * Remove nodes that are either invalid or malformed.
         *
         * @param \DOMNode $currentElement The current element.
         */
        protected function cleanUnsafeNodes(\DOMNode $currentElement) {
            // Replace CDATA node with encoded text node
            if ($currentElement instanceof \DOMCdataSection) {
                $textNode = $currentElement->ownerDocument->createTextNode($currentElement->nodeValue);
                $currentElement->parentNode->replaceChild($textNode, $currentElement);
            // If the element doesn't have a tagname, remove it and continue with next iteration
            } elseif (!$currentElement instanceof \DOMElement && !$currentElement instanceof \DOMText) {
                $currentElement->parentNode->removeChild($currentElement);
                $this->xmlIssues[] = array(
                    'message' => 'Suspicious node \'' . $currentElement->nodeName . '\'',
                    'line' => $currentElement->getLineNo(),
                );
                return;
            }
    
            if ( $currentElement->childNodes && $currentElement->childNodes->length > 0 ) {
                for ($j = $currentElement->childNodes->length - 1; $j >= 0; $j--) {
                    /** @var \DOMElement $childElement */
                    $childElement = $currentElement->childNodes->item($j);
                    $this->cleanUnsafeNodes($childElement);
                }
            }
        }
    }
    
Viewing 4 replies - 1 through 4 (of 4 total)
  • Michael

    (@migaweb)

    please follow the github issue: https://github.com/brainstormforce/header-footer-elementor/issues/810 it has a test version and an explanation why this happens (you have another module for SVG files)

    Plugin Support Herman Asrori (BSF)

    (@bsfherman)

    Hi @sebulka100,

    We’re sorry for the inconvenience. We have fixed the issue. Please install the latest update, v1.6.31, to resolve this problem.

    If your site login page is not accessible, you will need to disable the plugin using FTP. Here is an article that explains how to disable a plugin using FTP.

    As mentioned in the article, you need to rename the plugin folder. As mentioned in the last comment above, the one you need to rename is the header-footer-elementor folder. Once you rename the folder, you can log in to your site and reinstall the plugin.

    Please let us know how you go.

    Kind regards,
    Herman 😊

    HI Herman,

    I have the same error on kraniosakralterapibolgen.dk and I don’t know how to solve it with this FTP. I am not technical at all πŸ™

    Is there any way you can help?

    Best regards Terapi

    Plugin Support Herman Asrori (BSF)

    (@bsfherman)

    Hi @kstterapi1,

    If the article I shared above doesn’t help, please ask your hosting support. I believe the will help. You can just tell them that this plugin causes the issue, and you need to deactivate it. Or you can also share this thread to them. They will understand.

    Or if you like, you can also reach out to us using the form available on this page.

    Kind regards,
    Herman 😊

Viewing 4 replies - 1 through 4 (of 4 total)

The topic ‘New update fatal error’ is closed to new replies.