Decode the html-tags via "UTF8::html_entity_decode()" or the string via "UTF8::rawurldecode()".

@param string $str

@return string
187177
private function _decode_string(string $str): string
    {
        // init
        $regExForHtmlTags = '/<\p{L}+.*+/us';

        if (
            \strpos($str, '<') !== false
            &&
            \preg_match($regExForHtmlTags, $str, $matches) === 1
        ) {
            $str = (string) \preg_replace_callback(
                $regExForHtmlTags,
                function ($matches) {
                    return $this->_decode_entity($matches);
                },
                $str
            );
        } else {
            $str = UTF8::rawurldecode($str);
        }

        return $str;
    }
701798
private static function escapeString($str)
    {
        if (strlen($str) === 0) {
            return $str;
        }

        $str = str_replace(array(
            "\r",
            "\t",
            "\\",
            "\$",
            "\v",
            "\e",
            "\f",
            "\""
        ), array(
            '\r',
            '\t',
            '\\\\',
            '\$',
            '\v',
            '\e',
            '\f',
            '\"'
        ), $str);

        $str = str_replace("\n", "\\n\"\n\"", $str);

        $result = '';
        $str = str_split($str, 1);
        foreach ($str as $chr) {
            if (!ctype_print($chr) && $chr !== "\n") {
                $result .= '\\' . decoct(ord($chr));
            } else {
                $result .= $chr;
            }
        }
        if (substr($result, -5) === "\\n\"\n\"") {
            $result = substr($result, 0, -5) . "\\n";
        }
        return $result;
    }
1224398
public function loadHtml($str, $encoding = 'UTF-8')
    {
        $this->saveLocale();

        // FIXME: Determine character encoding, switch to UTF8, update meta tag. Need better http/file stream encoding detection, currently relies on text or meta tag.
        $known_encodings = mb_list_encodings();
        mb_detect_order('auto');
        if (($file_encoding = mb_detect_encoding($str, null, true)) === false) {
            $file_encoding = "auto";
        }
        if (in_array(strtoupper($file_encoding), array('UTF-8','UTF8')) === false) {
            $str = mb_convert_encoding($str, 'UTF-8', $file_encoding);
        }

        $metatags = array(
            '@<meta\s+http-equiv="Content-Type"\s+content="(?:[\w/]+)(?:;\s*?charset=([^\s"]+))?@i',
            '@<meta\s+content="(?:[\w/]+)(?:;\s*?charset=([^\s"]+))"?\s+http-equiv="Content-Type"@i',
            '@<meta [^>]*charset\s*=\s*["\']?\s*([^"\' ]+)@i',
        );
        foreach ($metatags as $metatag) {
            if (preg_match($metatag, $str, $matches)) {
                if (isset($matches[1]) && in_array($matches[1], $known_encodings)) {
                    $document_encoding = $matches[1];
                    break;
                }
            }
        }
        if (isset($document_encoding) && in_array(strtoupper($document_encoding), array('UTF-8','UTF8')) === false) {
            $str = preg_replace('/charset=([^\s"]+)/i', 'charset=UTF-8', $str);
        } elseif (isset($document_encoding) === false && strpos($str, '<head>') !== false) {
            $str = str_replace('<head>', '<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">', $str);
        } elseif (isset($document_encoding) === false) {
            $str = '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">' . $str;
        }
        //FIXME: since we're not using this just yet
        $encoding = 'UTF-8';

        // remove BOM mark from UTF-8, it's treated as document text by DOMDocument
        // FIXME: roll this into the encoding detection using UTF-8/16/32 BOM (http://us2.php.net/manual/en/function.mb-detect-encoding.php#91051)?
        if (substr($str, 0, 3) == chr(0xEF) . chr(0xBB) . chr(0xBF)) {
            $str = substr($str, 3);
        }

        // Store parsing warnings as messages
        set_error_handler(array("\\Dompdf\\Helpers", "record_warnings"));

        // @todo Take the quirksmode into account
        // http://hsivonen.iki.fi/doctype/
        // https://developer.mozilla.org/en/mozilla's_quirks_mode
        $quirksmode = false;

        if ($this->options->isHtml5ParserEnabled() && class_exists("HTML5_Tokenizer")) {
            $tokenizer = new HTML5_Tokenizer($str);
            $tokenizer->parse();
            $doc = $tokenizer->save();

            // Remove #text children nodes in nodes that shouldn't have
            $tag_names = array("html", "table", "tbody", "thead", "tfoot", "tr");
            foreach ($tag_names as $tag_name) {
                $nodes = $doc->getElementsByTagName($tag_name);

                foreach ($nodes as $node) {
                    self::removeTextNodes($node);
                }
            }

            $quirksmode = ($tokenizer->getTree()->getQuirksMode() > HTML5_TreeBuilder::NO_QUIRKS);
        } else {
            // loadHTML assumes ISO-8859-1 unless otherwise specified on the HTML document header.
            // http://devzone.zend.com/1538/php-dom-xml-extension-encoding-processing/ (see #4)
            // http://stackoverflow.com/a/11310258/264628
            $doc = new DOMDocument("1.0", $encoding);
            $doc->preserveWhiteSpace = true;
            $doc->loadHTML($str);
            $doc->encoding = $encoding;

            // Remove #text children nodes in nodes that shouldn't have
            $tag_names = array("html", "table", "tbody", "thead", "tfoot", "tr");
            foreach ($tag_names as $tag_name) {
                $nodes = $doc->getElementsByTagName($tag_name);

                foreach ($nodes as $node) {
                    self::removeTextNodes($node);
                }
            }

            // If some text is before the doctype, we are in quirksmode
            if (preg_match("/^(.+)<!doctype/i", ltrim($str), $matches)) {
                $quirksmode = true;
            } // If no doctype is provided, we are in quirksmode
            elseif (!preg_match("/^<!doctype/i", ltrim($str), $matches)) {
                $quirksmode = true;
            } else {
                // HTML5 <!DOCTYPE html>
                if (!$doc->doctype->publicId && !$doc->doctype->systemId) {
                    $quirksmode = false;
                }

                // not XHTML
                if (!preg_match("/xhtml/i", $doc->doctype->publicId)) {
                    $quirksmode = true;
                }
            }
        }

        $this->dom = $doc;
        $this->quirksmode = $quirksmode;

        $this->tree = new FrameTree($this->dom);

        restore_error_handler();

        $this->restoreLocale();
    }
540099
protected function _validate_entities($str) {
		/*
		 * Protect GET variables in URLs
		 */
		
		// 901119URL5918AMP18930PROTECT8198
		
		$str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash() . "\\1=\\2", $str);
		
		/*
		 * Validate standard character entities Add a semicolon if missing. We
		 * do this to enable the conversion of entities to ASCII later.
		 */
		$str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str);
		
		/*
		 * Validate UTF16 two byte encoding (x00) Just as above, adds a
		 * semicolon if missing.
		 */
		$str = preg_replace('#(&\#x?)([0-9A-F]+);?#i', "\\1\\2;", $str);
		
		/*
		 * Un-Protect GET variables in URLs
		 */
		$str = str_replace($this->xss_hash(), '&', $str);
		
		return $str;
	}
332267
private function unescapeLatinCharacters($str)
    {
        if ($this->latinCharacters) {
            $str = vsprintf($str, $this->latinCharacters);
            $this->latinCharacters = array();
        }

        return $str;
    }
1139605
function UTF8toSubset($str)
	{
		$ret = '<';
		// $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str );	// mPDF 6 deleted
		// $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str );	// mPDF 6 deleted
		$unicode = $this->UTF8StringToArray($str);
		$orig_fid = $this->CurrentFont['subsetfontids'][0];
		$last_fid = $this->CurrentFont['subsetfontids'][0];
		foreach ($unicode as $c) {
			/* 	// mPDF 6 deleted
			  if ($c == 7 || $c == 8) {
			  if ($orig_fid != $last_fid) {
			  $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
			  $last_fid = $orig_fid;
			  }
			  if ($c == 7) { $ret .= $this->aliasNbPgHex; }
			  else { $ret .= $this->aliasNbPgGpHex; }
			  continue;
			  }
			 */
			if (!$this->_charDefined($this->CurrentFont['cw'], $c)) {
				$c = 0;
			} // mPDF 6
			for ($i = 0; $i < 99; $i++) {
				// return c as decimal char
				$init = array_search($c, $this->CurrentFont['subsets'][$i]);
				if ($init !== false) {
					if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
						$ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
						$last_fid = $this->CurrentFont['subsetfontids'][$i];
					}
					$ret .= sprintf("%02s", strtoupper(dechex($init)));
					break;
				} // TrueType embedded SUBSETS
				elseif (count($this->CurrentFont['subsets'][$i]) < 255) {
					$n = count($this->CurrentFont['subsets'][$i]);
					$this->CurrentFont['subsets'][$i][$n] = $c;
					if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
						$ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
						$last_fid = $this->CurrentFont['subsetfontids'][$i];
					}
					$ret .= sprintf("%02s", strtoupper(dechex($n)));
					break;
				} elseif (!isset($this->CurrentFont['subsets'][($i + 1)])) {
					// TrueType embedded SUBSETS
					$this->CurrentFont['subsets'][($i + 1)] = [0 => 0];
					$new_fid = count($this->fonts) + $this->extraFontSubsets + 1;
					$this->CurrentFont['subsetfontids'][($i + 1)] = $new_fid;
					$this->extraFontSubsets++;
				}
			}
		}
		$ret .= '>';
		if ($last_fid != $orig_fid) {
			$ret .= ' Tj /F' . $orig_fid . ' ' . $this->FontSizePt . ' Tf <> ';
		}
		return $ret;
	}
720295
public function decode($value)
    {
        if (is_array($value)) {
            $newValue = array();
            foreach ($value as $key => $val) {
                $newValue[$key] = html_entity_decode($val, ENT_QUOTES, 'UTF-8');
            }

            return $newValue;
        }

        return html_entity_decode($value, ENT_QUOTES, 'UTF-8');
    }
915957
private function _do($str)
    {
        $str = (string) $str;
        $strInt = (int) $str;
        $strFloat = (float) $str;
        if (
            !$str
            ||
            (string) $strInt === $str
            ||
            (string) $strFloat === $str
        ) {

            // no xss found
            if ($this->_xss_found !== true) {
                $this->_xss_found = false;
            }

            return $str;
        }

        // remove the BOM from UTF-8 / UTF-16 / UTF-32 strings
        $str = UTF8::remove_bom($str);

        // replace the diamond question mark (�) and invalid-UTF8 chars
        $str = UTF8::replace_diamond_question_mark($str, '');

        // replace invisible characters with one single space
        $str = UTF8::remove_invisible_characters($str, true, ' ');

        // normalize the whitespace
        $str = UTF8::normalize_whitespace($str);

        // decode UTF-7 characters
        $str = $this->_repack_utf7($str);

        // decode the string
        $str = $this->_decode_string($str);

        // remove all >= 4-Byte chars if needed
        if ($this->_stripe_4byte_chars) {
            $str = (string) \preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str);
        }

        // backup the string (for later comparision)
        $str_backup = $str;

        // remove strings that are never allowed
        $str = $this->_do_never_allowed($str);

        // corrects words before the browser will do it
        $str = $this->_compact_exploded_javascript($str);

        // remove disallowed javascript calls in links, images etc.
        $str = $this->_remove_disallowed_javascript($str);

        // remove evil attributes such as style, onclick and xmlns
        $str = $this->_remove_evil_attributes($str);

        // sanitize naughty JavaScript elements
        $str = $this->_sanitize_naughty_javascript($str);

        // sanitize naughty HTML elements
        $str = $this->_sanitize_naughty_html($str);

        // final clean up
        //
        // -> This adds a bit of extra precaution in case something got through the above filters.
        $str = $this->_do_never_allowed_afterwards($str);

        // check for xss
        if ($this->_xss_found !== true) {
            $this->_xss_found = !($str_backup === $str);
        }

        return $str;
    }
273290
public function convertToUtf8($str) {
        if (mb_detect_encoding($str, "UTF-8, ISO-8859-1, GBK")!="UTF-8") {
            $str = utf8_encode($str);
        }
        $str = iconv('UTF-8', 'UTF-8//IGNORE', $str);
        return $str;
    }
916235
protected function extractContentIdFromBBCode($str)
    {
        $references = array();
        /** @var \OpenOrchestra\BBcodeBundle\Parser\BBcodeParserInterface $parserBBcode */
        $parsedBBcode = $this->bbcodeParser->parse($str);
        $nodeTags = $parsedBBcode->getElementByTagName(InternalLinkDefinition::TAG_NAME);
        /** @var \OpenOrchestra\BBcodeBundle\ElementNode\BBcodeElementNodeInterface $mediaTag */
        foreach ($nodeTags as $nodeTag) {
            $linkAttribute = json_decode(html_entity_decode($nodeTag->getAttribute()['link']), true);
            if (!empty($linkAttribute['contentSearch_contentId'])) {
                $references[] = $linkAttribute['contentSearch_contentId'];
            }
        }

        return $references;
    }
152420
public static function parse_attrib_string($str)
    {
        $attrib = array();
        $html   = '<html>'
            . '<head><meta http-equiv="Content-Type" content="text/html; charset=' . RCUBE_CHARSET . '" /></head>'
            . '<body><div ' . rtrim($str, '/ ') . ' /></body>'
            . '</html>';

        $document = new DOMDocument('1.0', RCUBE_CHARSET);
        @$document->loadHTML($html);

        if ($node = $document->getElementsByTagName('div')->item(0)) {
            foreach ($node->attributes as $name => $attr) {
                $attrib[strtolower($name)] = $attr->nodeValue;
            }
        }

        return $attrib;
    }
676340
public function convertToUtf8($str, $charset = 'ISO-8859-1')
    {
        if ($charset == 'default') {
            $charset = 'utf-8';
        }

        $str = iconv($charset, 'UTF-8//IGNORE', $str);

        return $str;
    }
1360541
private function _toupper($str)
    {
        // string can containing HTML tags
        $chunks = preg_split('/(<[^>]*>)/', $str, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

        // convert toupper only the text between HTML tags
        foreach ($chunks as $idx => $chunk) {
            if ($chunk[0] != '<') {
                $chunks[$idx] = $this->_strtoupper($chunk);
            }
        }

        return implode($chunks);
    }
950411
public static final String decode(String str)
    {
        Matcher m = ENT.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (m.find())
        {
            String entity = m.group(1);
            Matcher m2 = HENT.matcher(entity);
            Integer codePoint = null;
            if (m2.matches())
            {
                codePoint = Integer.parseInt(m2.group(1));
            }
            else
            {
                codePoint = codePointMap.get(entity);
            }
            if (codePoint == null)
            {
                m.appendReplacement(sb, m.group());
            }
            else
            {
                String s = new String(new int[] {codePoint.intValue()}, 0, 1);
                m.appendReplacement(sb, s);
            }
        }
        m.appendTail(sb);
        return sb.toString();
    }
1270569
static function DecodeFromHTML($string, $charset = null)
	{
		// this only gets named characters
		// return html_entity_decode($string);

		// this is a complex method that appears to be the reverse of UTF8ToHTML
		// taken from http://www.php.net/manual/en/function.html-entity-decode.php#68491
//		$string = self::ReplaceNonNumericEntities($string);
//		$string = preg_replace_callback('~&(#(x?))?([^;]+);~', 'self::html_entity_replace', $string);
//        return $string;

		// this way at least somebody could specify a character set.  UTF-8 will work most of the time
		if ($charset == null) $charset = VerySimpleStringUtil::$DEFAULT_CHARACTER_SET;
		return mb_convert_encoding($string, $charset, 'HTML-ENTITIES');
	}
973121
protected static function decodeToUtf8($str)
    {
        $str = preg_replace_callback("/\\\\x([0-9ABCDEF]{1,2})/", function ($matches) {
            return chr(hexdec($matches[1]));
        }, $str);

        $encoding = mb_detect_encoding($str, 'ASCII, UCS2, UTF8');
        if ($encoding == 'ASCII') {
            $result = mb_convert_encoding($str, 'UTF-8', 'ASCII');
        } else {
            if (substr_count($str, chr(0)) > 0) {
                $result = mb_convert_encoding($str, 'UTF-8', 'UCS2');
            } else {
                $result = $str;
            }
        }

        return $result;
    }
1008919
public static function safe($str)
    {
        if(is_array($str)){
            foreach($str as $key=>$val){
                $str[$key] = self::safe($val);
            }
            return $str;
        }
        return htmlspecialchars($str, ENT_QUOTES);
    }