diff --git a/htmLawed.php b/htmLawed.php index e9fe93f..b6a9f39 100755 --- a/htmLawed.php +++ b/htmLawed.php @@ -1,7 +1,7 @@ 1, 'abbr' => 1, 'acronym' => 1, 'address' => 1, 'applet' => 1, 'area' => 1, 'article' => 1, 'aside' => 1, 'audio' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'blockquote' => 1, 'br' => 1, 'button' => 1, 'canvas' => 1, 'caption' => 1, 'center' => 1, 'cite' => 1, 'code' => 1, 'col' => 1, 'colgroup' => 1, 'command' => 1, 'data' => 1, 'datalist' => 1, 'dd' => 1, 'del' => 1, 'details' => 1, 'dfn' => 1, 'dir' => 1, 'div' => 1, 'dl' => 1, 'dt' => 1, 'em' => 1, 'embed' => 1, 'fieldset' => 1, 'figcaption' => 1, 'figure' => 1, 'font' => 1, 'footer' => 1, 'form' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'header' => 1, 'hgroup' => 1, 'hr' => 1, 'i' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'ins' => 1, 'isindex' => 1, 'kbd' => 1, 'keygen' => 1, 'label' => 1, 'legend' => 1, 'li' => 1, 'link' => 1, 'main' => 1, 'map' => 1, 'mark' => 1, 'menu' => 1, 'meta' => 1, 'meter' => 1, 'nav' => 1, 'noscript' => 1, 'object' => 1, 'ol' => 1, 'optgroup' => 1, 'option' => 1, 'output' => 1, 'p' => 1, 'param' => 1, 'pre' => 1, 'progress' => 1, 'q' => 1, 'rb' => 1, 'rbc' => 1, 'rp' => 1, 'rt' => 1, 'rtc' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'script' => 1, 'section' => 1, 'select' => 1, 'small' => 1, 'source' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'style' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'table' => 1, 'tbody' => 1, 'td' => 1, 'textarea' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'time' => 1, 'tr' => 1, 'track' => 1, 'tt' => 1, 'u' => 1, 'ul' => 1, 'var' => 1, 'video' => 1, 'wbr' => 1]; // 118 incl. deprecated & some Ruby + $e = ['a' => 1, 'abbr' => 1, 'acronym' => 1, 'address' => 1, 'applet' => 1, 'area' => 1, 'article' => 1, 'aside' => 1, 'audio' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'blockquote' => 1, 'br' => 1, 'button' => 1, 'canvas' => 1, 'caption' => 1, 'center' => 1, 'cite' => 1, 'code' => 1, 'col' => 1, 'colgroup' => 1, 'command' => 1, 'data' => 1, 'datalist' => 1, 'dd' => 1, 'del' => 1, 'details' => 1, 'dialog' => 1, 'dfn' => 1, 'dir' => 1, 'div' => 1, 'dl' => 1, 'dt' => 1, 'em' => 1, 'embed' => 1, 'fieldset' => 1, 'figcaption' => 1, 'figure' => 1, 'font' => 1, 'footer' => 1, 'form' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'header' => 1, 'hgroup' => 1, 'hr' => 1, 'i' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'ins' => 1, 'isindex' => 1, 'kbd' => 1, 'keygen' => 1, 'label' => 1, 'legend' => 1, 'li' => 1, 'link' => 1, 'main' => 1, 'map' => 1, 'mark' => 1, 'menu' => 1, 'meta' => 1, 'meter' => 1, 'nav' => 1, 'noscript' => 1, 'object' => 1, 'ol' => 1, 'optgroup' => 1, 'option' => 1, 'output' => 1, 'p' => 1, 'param' => 1, 'picture' => 1, 'pre' => 1, 'progress' => 1, 'q' => 1, 'rb' => 1, 'rbc' => 1, 'rp' => 1, 'rt' => 1, 'rtc' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'script' => 1, 'section' => 1, 'select' => 1, 'slot' => 1, 'small' => 1, 'source' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'style' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'table' => 1, 'tbody' => 1, 'td' => 1, 'template' => 1, 'textarea' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'time' => 1, 'tr' => 1, 'track' => 1, 'tt' => 1, 'u' => 1, 'ul' => 1, 'var' => 1, 'video' => 1, 'wbr' => 1]; // 122 incl. deprecated & some Ruby if (!empty($C['safe'])) { - unset($e['applet'], $e['audio'], $e['canvas'], $e['embed'], $e['iframe'], $e['object'], $e['script'], $e['video']); + unset($e['applet'], $e['audio'], $e['canvas'], $e['dialog'], $e['embed'], $e['iframe'], $e['object'], $e['script'], $e['video']); } - $x = !empty($C['elements']) ? str_replace(["\n", "\r", "\t", ' '], '', $C['elements']) : '*'; + $x = !empty($C['elements']) ? str_replace(["\n", "\r", "\t", ' '], '', strtolower($C['elements'])) : '*'; if ('-*' === $x) { $e = []; } elseif (false === strpos($x, '*')) { $e = array_flip(explode(',', $x)); } else { if (isset($x[1])) { + if (strpos($x, '(')) { + $x = preg_replace_callback('`\([^()]+\)`', function ($m) {return str_replace(['(', ')', '-'], ['', '', 'A'], $m[0]); }, $x); + } + preg_match_all('`(?:^|-|\+)[^\-+]+?(?=-|\+|$)`', $x, $m, \PREG_SET_ORDER); for ($i = count($m); --$i >= 0;) { $m[$i] = $m[$i][0]; } foreach ($m as $v) { + $v = str_replace('A', '-', $v); if ('+' === $v[0]) { $e[substr($v, 1)] = 1; - } - if ('-' === $v[0] && isset($e[($v = substr($v, 1))]) && !in_array('+' . $v, $m, true)) { - unset($e[$v]); + } elseif ('-' === $v[0]) { + if (strpos($v, '-', 1)) { + $e[$v] = 1; + } elseif (isset($e[($v = substr($v, 1))]) && !in_array('+' . $v, $m, true)) { + unset($e[$v]); + } } } } @@ -76,6 +84,7 @@ function htmLawed($t, $C = 1, $S = []) $C['and_mark'] = empty($C['and_mark']) ? 0 : 1; $C['anti_link_spam'] = (isset($C['anti_link_spam']) && is_array($C['anti_link_spam']) && 2 === count($C['anti_link_spam']) && (empty($C['anti_link_spam'][0]) || hl_regex($C['anti_link_spam'][0])) && (empty($C['anti_link_spam'][1]) || hl_regex($C['anti_link_spam'][1]))) ? $C['anti_link_spam'] : 0; $C['anti_mail_spam'] = isset($C['anti_mail_spam']) ? $C['anti_mail_spam'] : 0; + $C['any_custom_element'] = (!isset($C['any_custom_element']) || !empty($C['any_custom_element'])) ? 1 : 0; $C['balance'] = isset($C['balance']) ? (bool) $C['balance'] : 1; $C['cdata'] = isset($C['cdata']) ? $C['cdata'] : (empty($C['safe']) ? 3 : 0); $C['clean_ms_char'] = empty($C['clean_ms_char']) ? 0 : $C['clean_ms_char']; @@ -233,8 +242,8 @@ function hl_bal($t, $do = 1, $in = 'div') // by content $cB = ['blockquote' => 1, 'form' => 1, 'map' => 1, 'noscript' => 1]; // Block $cE = ['area' => 1, 'br' => 1, 'col' => 1, 'command' => 1, 'embed' => 1, 'hr' => 1, 'img' => 1, 'input' => 1, 'isindex' => 1, 'keygen' => 1, 'link' => 1, 'meta' => 1, 'param' => 1, 'source' => 1, 'track' => 1, 'wbr' => 1]; // Empty - $cF = ['a' => 1, 'article' => 1, 'aside' => 1, 'audio' => 1, 'button' => 1, 'canvas' => 1, 'del' => 1, 'details' => 1, 'div' => 1, 'dd' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'header' => 1, 'iframe' => 1, 'ins' => 1, 'li' => 1, 'main' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'object' => 1, 'section' => 1, 'style' => 1, 'td' => 1, 'th' => 1, 'video' => 1]; // Flow; later context-wise dynamic move of ins & del to $cI - $cI = ['abbr' => 1, 'acronym' => 1, 'address' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'caption' => 1, 'cite' => 1, 'code' => 1, 'data' => 1, 'datalist' => 1, 'dfn' => 1, 'dt' => 1, 'em' => 1, 'figcaption' => 1, 'font' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'hgroup' => 1, 'i' => 1, 'kbd' => 1, 'label' => 1, 'legend' => 1, 'mark' => 1, 'meter' => 1, 'output' => 1, 'p' => 1, 'pre' => 1, 'progress' => 1, 'q' => 1, 'rb' => 1, 'rt' => 1, 's' => 1, 'samp' => 1, 'small' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'time' => 1, 'tt' => 1, 'u' => 1, 'var' => 1]; // Inline + $cF = ['a' => 1, 'article' => 1, 'aside' => 1, 'audio' => 1, 'button' => 1, 'canvas' => 1, 'del' => 1, 'details' => 1, 'dialog' => 1, 'div' => 1, 'dd' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'header' => 1, 'iframe' => 1, 'ins' => 1, 'li' => 1, 'main' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'object' => 1, 'section' => 1, 'slot' => 1, 'style' => 1, 'td' => 1, 'template' => 1, 'th' => 1, 'video' => 1]; // Flow; later context-wise dynamic move of ins & del to $cI + $cI = ['abbr' => 1, 'acronym' => 1, 'address' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'caption' => 1, 'cite' => 1, 'code' => 1, 'data' => 1, 'datalist' => 1, 'dfn' => 1, 'dt' => 1, 'em' => 1, 'figcaption' => 1, 'font' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'hgroup' => 1, 'i' => 1, 'kbd' => 1, 'label' => 1, 'legend' => 1, 'mark' => 1, 'meter' => 1, 'output' => 1, 'p' => 1, 'picture' => 1, 'pre' => 1, 'progress' => 1, 'q' => 1, 'rb' => 1, 'rt' => 1, 's' => 1, 'samp' => 1, 'small' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'time' => 1, 'tt' => 1, 'u' => 1, 'var' => 1]; // Inline $cN = ['a' => ['a' => 1, 'address' => 1, 'button' => 1, 'details' => 1, 'embed' => 1, 'keygen' => 1, 'label' => 1, 'select' => 1, 'textarea' => 1], 'address' => ['address' => 1, 'article' => 1, 'aside' => 1, 'header' => 1, 'keygen' => 1, 'footer' => 1, 'nav' => 1, 'section' => 1], 'button' => ['a' => 1, 'address' => 1, 'button' => 1, 'details' => 1, 'embed' => 1, 'fieldset' => 1, 'form' => 1, 'iframe' => 1, 'input' => 1, 'keygen' => 1, 'label' => 1, 'select' => 1, 'textarea' => 1], 'fieldset' => ['fieldset' => 1], 'footer' => ['header' => 1, 'footer' => 1], 'form' => ['form' => 1], 'header' => ['header' => 1, 'footer' => 1], 'label' => ['label' => 1], 'main' => ['main' => 1], 'meter' => ['meter' => 1], 'noscript' => ['script' => 1], 'pre' => ['big' => 1, 'font' => 1, 'img' => 1, 'object' => 1, 'script' => 1, 'small' => 1, 'sub' => 1, 'sup' => 1], 'progress' => ['progress' => 1], 'rb' => ['ruby' => 1], 'rt' => ['ruby' => 1], 'time' => ['time' => 1]]; // Illegal $cN2 = array_keys($cN); $cS = ['colgroup' => ['col' => 1], 'datalist' => ['option' => 1], 'dir' => ['li' => 1], 'dl' => ['dd' => 1, 'dt' => 1], 'hgroup' => ['h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1], 'menu' => ['li' => 1], 'ol' => ['li' => 1], 'optgroup' => ['option' => 1], 'option' => ['#pcdata' => 1], 'rbc' => ['rb' => 1], 'rp' => ['#pcdata' => 1], 'rtc' => ['rt' => 1], 'ruby' => ['rb' => 1, 'rbc' => 1, 'rp' => 1, 'rt' => 1, 'rtc' => 1, '#pcdata' => 1], 'select' => ['optgroup' => 1, 'option' => 1], 'script' => ['#pcdata' => 1], 'table' => ['caption' => 1, 'col' => 1, 'colgroup' => 1, 'tfoot' => 1, 'tbody' => 1, 'tr' => 1, 'thead' => 1], 'tbody' => ['tr' => 1], 'tfoot' => ['tr' => 1], 'textarea' => ['#pcdata' => 1], 'thead' => ['tr' => 1], 'tr' => ['td' => 1, 'th' => 1], 'ul' => ['li' => 1]]; // Specific - immediate parent-child @@ -244,8 +253,8 @@ function hl_bal($t, $do = 1, $in = 'div') $cO = ['address' => ['p' => 1], 'applet' => ['param' => 1], 'audio' => ['source' => 1, 'track' => 1], 'blockquote' => ['script' => 1], 'details' => ['summary' => 1], 'fieldset' => ['legend' => 1, '#pcdata' => 1], 'figure' => ['figcaption' => 1], 'form' => ['script' => 1], 'map' => ['area' => 1], 'object' => ['param' => 1, 'embed' => 1], 'video' => ['source' => 1, 'track' => 1]]; // Other $cT = ['colgroup' => 1, 'dd' => 1, 'dt' => 1, 'li' => 1, 'option' => 1, 'p' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1]; // Omitable closing // block/inline type; a/ins/del both type; #pcdata: text - $eB = ['a' => 1, 'address' => 1, 'article' => 1, 'aside' => 1, 'blockquote' => 1, 'center' => 1, 'del' => 1, 'details' => 1, 'dir' => 1, 'dl' => 1, 'div' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'form' => 1, 'ins' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'header' => 1, 'hr' => 1, 'isindex' => 1, 'main' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'ol' => 1, 'p' => 1, 'pre' => 1, 'section' => 1, 'style' => 1, 'table' => 1, 'ul' => 1]; - $eI = ['#pcdata' => 1, 'a' => 1, 'abbr' => 1, 'acronym' => 1, 'applet' => 1, 'audio' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'br' => 1, 'button' => 1, 'canvas' => 1, 'cite' => 1, 'code' => 1, 'command' => 1, 'data' => 1, 'datalist' => 1, 'del' => 1, 'dfn' => 1, 'em' => 1, 'embed' => 1, 'figcaption' => 1, 'font' => 1, 'i' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'ins' => 1, 'kbd' => 1, 'label' => 1, 'link' => 1, 'map' => 1, 'mark' => 1, 'meta' => 1, 'meter' => 1, 'object' => 1, 'output' => 1, 'progress' => 1, 'q' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'select' => 1, 'script' => 1, 'small' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'textarea' => 1, 'time' => 1, 'tt' => 1, 'u' => 1, 'var' => 1, 'video' => 1, 'wbr' => 1]; + $eB = ['a' => 1, 'address' => 1, 'article' => 1, 'aside' => 1, 'blockquote' => 1, 'center' => 1, 'del' => 1, 'details' => 1, 'dialog' => 1, 'dir' => 1, 'dl' => 1, 'div' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'form' => 1, 'ins' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'header' => 1, 'hr' => 1, 'isindex' => 1, 'main' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'ol' => 1, 'p' => 1, 'pre' => 1, 'section' => 1, 'slot' => 1, 'style' => 1, 'table' => 1, 'template' => 1, 'ul' => 1]; + $eI = ['#pcdata' => 1, 'a' => 1, 'abbr' => 1, 'acronym' => 1, 'applet' => 1, 'audio' => 1, 'b' => 1, 'bdi' => 1, 'bdo' => 1, 'big' => 1, 'br' => 1, 'button' => 1, 'canvas' => 1, 'cite' => 1, 'code' => 1, 'command' => 1, 'data' => 1, 'datalist' => 1, 'del' => 1, 'dfn' => 1, 'em' => 1, 'embed' => 1, 'figcaption' => 1, 'font' => 1, 'i' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'ins' => 1, 'kbd' => 1, 'label' => 1, 'link' => 1, 'map' => 1, 'mark' => 1, 'meta' => 1, 'meter' => 1, 'object' => 1, 'output' => 1, 'picture' => 1, 'progress' => 1, 'q' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'select' => 1, 'script' => 1, 'small' => 1, 'span' => 1, 'strike' => 1, 'strong' => 1, 'sub' => 1, 'summary' => 1, 'sup' => 1, 'textarea' => 1, 'time' => 1, 'tt' => 1, 'u' => 1, 'var' => 1, 'video' => 1, 'wbr' => 1]; $eN = ['a' => 1, 'address' => 1, 'article' => 1, 'aside' => 1, 'big' => 1, 'button' => 1, 'details' => 1, 'embed' => 1, 'fieldset' => 1, 'font' => 1, 'footer' => 1, 'form' => 1, 'header' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'keygen' => 1, 'label' => 1, 'meter' => 1, 'nav' => 1, 'object' => 1, 'progress' => 1, 'ruby' => 1, 'script' => 1, 'select' => 1, 'small' => 1, 'sub' => 1, 'sup' => 1, 'textarea' => 1, 'time' => 1]; // Exclude from specific ele; $cN values $eO = ['area' => 1, 'caption' => 1, 'col' => 1, 'colgroup' => 1, 'command' => 1, 'dd' => 1, 'dt' => 1, 'hgroup' => 1, 'keygen' => 1, 'legend' => 1, 'li' => 1, 'optgroup' => 1, 'option' => 1, 'param' => 1, 'rb' => 1, 'rbc' => 1, 'rp' => 1, 'rt' => 1, 'rtc' => 1, 'script' => 1, 'source' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'thead' => 1, 'th' => 1, 'tr' => 1, 'track' => 1]; // Missing in $eB & $eI $eF = $eB + $eI; @@ -274,6 +283,9 @@ function hl_bal($t, $do = 1, $in = 'div') if (isset($cN[$in])) { $inOk = array_diff_assoc($inOk, $cN[$in]); } + if (strpos($in, '-')) { + $inOk = ['*' => 1, '#pcdata' => 1]; + } // custom ele $t = explode('<', $t); $ok = $q = []; // $q seq list of open non-empty ele @@ -303,6 +315,9 @@ function hl_bal($t, $do = 1, $in = 'div') if (isset($cN[$p])) { $ok = array_diff_assoc($ok, $cN[$p]); } + if (strpos($p, '-')) { + $ok = ['*' => 1, '#pcdata' => 1]; + } } else { $ok = $inOk; unset($cI['del'], $cI['ins']); @@ -325,7 +340,7 @@ function hl_bal($t, $do = 1, $in = 'div') } } // get markup - if (!preg_match('`^(/?)([a-z1-6]+)([^>]*)>(.*)`sm', $t[$i], $r)) { + if (!preg_match('`^(/?)([a-z][^ >]*)([^>]*)>(.*)`sm', $t[$i], $r)) { $x = $t[$i]; continue; } @@ -366,7 +381,10 @@ function hl_bal($t, $do = 1, $in = 'div') --$i; continue; } - if ((($ql && isset($cB[$p])) || (isset($cB[$in]) && !$ql)) && !isset($eB[$e]) && !isset($ok[$e])) { + if (strpos($e, '-')) { + $ok[$e] = 1; + } + if ((($ql && isset($cB[$p])) || (isset($cB[$in]) && !$ql)) && !isset($eB[$e]) && !isset($ok[$e]) && !isset($ok['*'])) { array_splice($t, $i, 0, 'div>'); unset($e, $x); ++$ci; @@ -375,7 +393,7 @@ function hl_bal($t, $do = 1, $in = 'div') } // if no open ele, $in = parent; mostly immediate parent-child relation should hold if (!$ql || !isset($eN[$e]) || !array_intersect($q, $cN2)) { - if (!isset($ok[$e])) { + if (!isset($ok[$e]) && !isset($ok['*'])) { if ($ql && isset($cT[$p])) { echo ''; unset($e, $x); @@ -416,8 +434,8 @@ function hl_bal($t, $do = 1, $in = 'div') if (isset($cN[$d])) { $ok2 = array_diff_assoc($ok2, $cN[$d]); } - if (!isset($ok2[$e])) { - if (!$k && !isset($inOk[$e])) { + if (!isset($ok2[$e]) && !strpos($e, '-')) { + if (!$k && !isset($inOk[$e]) && !isset($inOk['*'])) { continue 2; } $add = ""; @@ -460,6 +478,9 @@ function hl_bal($t, $do = 1, $in = 'div') if (isset($cN[$p])) { $ok = array_diff_assoc($ok, $cN[$p]); } + if (strpos($p, '-')) { + $ok = ['*' => 1, '#pcdata' => 1]; + } } else { $ok = $inOk; unset($cI['del'], $cI['ins']); @@ -698,9 +719,12 @@ function hl_tag($t) if ('>' === $t) { return '>'; } - if (!preg_match('`^<(/?)([a-zA-Z][a-zA-Z1-6]*)([^>]*?)\s?>$`m', $t, $m)) { + if (!preg_match('`^<(/?)([a-zA-Z][^\s>]*)([^>]*?)\s?>$`m', $t, $m)) { return str_replace(['<', '>'], ['<', '>'], $t); - } elseif (!isset($C['elements'][($e = strtolower($m[2]))])) { + } + $e = strtolower($m[2]); + static $eIC = ['annotation-xml' => 1, 'color-profile' => 1, 'font-face' => 1, 'font-face-src' => 1, 'font-face-uri' => 1, 'font-face-format' => 1, 'font-face-name' => 1, 'missing-glyph' => 1]; // Illegal cust ele + if ((!strpos($e, '-') && !isset($C['elements'][$e])) || (strpos($e, '-') && (isset($C['elements']['-' . $e]) || (!$C['any_custom_element'] && !isset($C['elements'][$e])) || isset($eIC[$e]) || preg_match('`[^-._0-9a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\x{2ff}\x{370}-\x{37d}\x{37f}-\x{1fff}\x{200c}-\x{200d}\x{2070}-\x{218f}\x{2c00}-\x{2fef}\x{3001}-\x{d7ff}\x{f900}-\x{fdcf}\x{fdf0}-\x{fffd}\x{10000}-\x{effff}]`u', $e)))) { return ($C['keep_bad'] % 2) ? str_replace(['<', '>'], ['<', '>'], $t) : ''; } // attr string @@ -720,12 +744,12 @@ function hl_tag($t) } // open tag & attr - static $aN = ['abbr' => ['td' => 1, 'th' => 1], 'accept' => ['form' => 1, 'input' => 1], 'accept-charset' => ['form' => 1], 'action' => ['form' => 1], 'align' => ['applet' => 1, 'caption' => 1, 'col' => 1, 'colgroup' => 1, 'div' => 1, 'embed' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'hr' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'legend' => 1, 'object' => 1, 'p' => 1, 'table' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'allowfullscreen' => ['iframe' => 1], 'alt' => ['applet' => 1, 'area' => 1, 'img' => 1, 'input' => 1], 'archive' => ['applet' => 1, 'object' => 1], 'async' => ['script' => 1], 'autocomplete' => ['form' => 1, 'input' => 1], 'autofocus' => ['button' => 1, 'input' => 1, 'keygen' => 1, 'select' => 1, 'textarea' => 1], 'autoplay' => ['audio' => 1, 'video' => 1], 'axis' => ['td' => 1, 'th' => 1], 'bgcolor' => ['embed' => 1, 'table' => 1, 'td' => 1, 'th' => 1, 'tr' => 1], 'border' => ['img' => 1, 'object' => 1, 'table' => 1], 'bordercolor' => ['table' => 1, 'td' => 1, 'tr' => 1], 'cellpadding' => ['table' => 1], 'cellspacing' => ['table' => 1], 'challenge' => ['keygen' => 1], 'char' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'charoff' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'charset' => ['a' => 1, 'script' => 1], 'checked' => ['command' => 1, 'input' => 1], 'cite' => ['blockquote' => 1, 'del' => 1, 'ins' => 1, 'q' => 1], 'classid' => ['object' => 1], 'clear' => ['br' => 1], 'code' => ['applet' => 1], 'codebase' => ['applet' => 1, 'object' => 1], 'codetype' => ['object' => 1], 'color' => ['font' => 1], 'cols' => ['textarea' => 1], 'colspan' => ['td' => 1, 'th' => 1], 'compact' => ['dir' => 1, 'dl' => 1, 'menu' => 1, 'ol' => 1, 'ul' => 1], 'content' => ['meta' => 1], 'controls' => ['audio' => 1, 'video' => 1], 'coords' => ['a' => 1, 'area' => 1], 'crossorigin' => ['img' => 1], 'data' => ['object' => 1], 'datetime' => ['del' => 1, 'ins' => 1, 'time' => 1], 'declare' => ['object' => 1], 'default' => ['track' => 1], 'defer' => ['script' => 1], 'dirname' => ['input' => 1, 'textarea' => 1], 'disabled' => ['button' => 1, 'command' => 1, 'fieldset' => 1, 'input' => 1, 'keygen' => 1, 'optgroup' => 1, 'option' => 1, 'select' => 1, 'textarea' => 1], 'download' => ['a' => 1], 'enctype' => ['form' => 1], 'face' => ['font' => 1], 'flashvars' => ['embed' => 1], 'for' => ['label' => 1, 'output' => 1], 'form' => ['button' => 1, 'fieldset' => 1, 'input' => 1, 'keygen' => 1, 'label' => 1, 'object' => 1, 'output' => 1, 'select' => 1, 'textarea' => 1], 'formaction' => ['button' => 1, 'input' => 1], 'formenctype' => ['button' => 1, 'input' => 1], 'formmethod' => ['button' => 1, 'input' => 1], 'formnovalidate' => ['button' => 1, 'input' => 1], 'formtarget' => ['button' => 1, 'input' => 1], 'frame' => ['table' => 1], 'frameborder' => ['iframe' => 1], 'headers' => ['td' => 1, 'th' => 1], 'height' => ['applet' => 1, 'canvas' => 1, 'embed' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'object' => 1, 'td' => 1, 'th' => 1, 'video' => 1], 'high' => ['meter' => 1], 'href' => ['a' => 1, 'area' => 1, 'link' => 1], 'hreflang' => ['a' => 1, 'area' => 1, 'link' => 1], 'hspace' => ['applet' => 1, 'embed' => 1, 'img' => 1, 'object' => 1], 'icon' => ['command' => 1], 'ismap' => ['img' => 1, 'input' => 1], 'keyparams' => ['keygen' => 1], 'keytype' => ['keygen' => 1], 'kind' => ['track' => 1], 'label' => ['command' => 1, 'menu' => 1, 'option' => 1, 'optgroup' => 1, 'track' => 1], 'language' => ['script' => 1], 'list' => ['input' => 1], 'longdesc' => ['img' => 1, 'iframe' => 1], 'loop' => ['audio' => 1, 'video' => 1], 'low' => ['meter' => 1], 'marginheight' => ['iframe' => 1], 'marginwidth' => ['iframe' => 1], 'max' => ['input' => 1, 'meter' => 1, 'progress' => 1], 'maxlength' => ['input' => 1, 'textarea' => 1], 'media' => ['a' => 1, 'area' => 1, 'link' => 1, 'source' => 1, 'style' => 1], 'mediagroup' => ['audio' => 1, 'video' => 1], 'method' => ['form' => 1], 'min' => ['input' => 1, 'meter' => 1], 'model' => ['embed' => 1], 'multiple' => ['input' => 1, 'select' => 1], 'muted' => ['audio' => 1, 'video' => 1], 'name' => ['a' => 1, 'applet' => 1, 'button' => 1, 'embed' => 1, 'fieldset' => 1, 'form' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'keygen' => 1, 'map' => 1, 'object' => 1, 'output' => 1, 'param' => 1, 'select' => 1, 'textarea' => 1], 'nohref' => ['area' => 1], 'noshade' => ['hr' => 1], 'novalidate' => ['form' => 1], 'nowrap' => ['td' => 1, 'th' => 1], 'object' => ['applet' => 1], 'open' => ['details' => 1], 'optimum' => ['meter' => 1], 'pattern' => ['input' => 1], 'ping' => ['a' => 1, 'area' => 1], 'placeholder' => ['input' => 1, 'textarea' => 1], 'pluginspage' => ['embed' => 1], 'pluginurl' => ['embed' => 1], 'poster' => ['video' => 1], 'pqg' => ['keygen' => 1], 'preload' => ['audio' => 1, 'video' => 1], 'prompt' => ['isindex' => 1], 'pubdate' => ['time' => 1], 'radiogroup' => ['command' => 1], 'readonly' => ['input' => 1, 'textarea' => 1], 'referrerpolicy' => ['a' => 1, 'area' => 1, 'img' => 1, 'iframe' => 1, 'link' => 1], 'rel' => ['a' => 1, 'area' => 1, 'link' => 1], 'required' => ['input' => 1, 'select' => 1, 'textarea' => 1], 'rev' => ['a' => 1], 'reversed' => ['ol' => 1], 'rows' => ['textarea' => 1], 'rowspan' => ['td' => 1, 'th' => 1], 'rules' => ['table' => 1], 'sandbox' => ['iframe' => 1], 'scope' => ['td' => 1, 'th' => 1], 'scoped' => ['style' => 1], 'scrolling' => ['iframe' => 1], 'seamless' => ['iframe' => 1], 'selected' => ['option' => 1], 'shape' => ['a' => 1, 'area' => 1], 'size' => ['font' => 1, 'hr' => 1, 'input' => 1, 'select' => 1], 'sizes' => ['link' => 1], 'span' => ['col' => 1, 'colgroup' => 1], 'src' => ['audio' => 1, 'embed' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'script' => 1, 'source' => 1, 'track' => 1, 'video' => 1], 'srcdoc' => ['iframe' => 1], 'srclang' => ['track' => 1], 'srcset' => ['img' => 1], 'standby' => ['object' => 1], 'start' => ['ol' => 1], 'step' => ['input' => 1], 'summary' => ['table' => 1], 'target' => ['a' => 1, 'area' => 1, 'form' => 1], 'type' => ['a' => 1, 'area' => 1, 'button' => 1, 'command' => 1, 'embed' => 1, 'input' => 1, 'li' => 1, 'link' => 1, 'menu' => 1, 'object' => 1, 'ol' => 1, 'param' => 1, 'script' => 1, 'source' => 1, 'style' => 1, 'ul' => 1], 'typemustmatch' => ['object' => 1], 'usemap' => ['img' => 1, 'input' => 1, 'object' => 1], 'valign' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'value' => ['button' => 1, 'data' => 1, 'input' => 1, 'li' => 1, 'meter' => 1, 'option' => 1, 'param' => 1, 'progress' => 1], 'valuetype' => ['param' => 1], 'vspace' => ['applet' => 1, 'embed' => 1, 'img' => 1, 'object' => 1], 'width' => ['applet' => 1, 'canvas' => 1, 'col' => 1, 'colgroup' => 1, 'embed' => 1, 'hr' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'object' => 1, 'pre' => 1, 'table' => 1, 'td' => 1, 'th' => 1, 'video' => 1], 'wmode' => ['embed' => 1], 'wrap' => ['textarea' => 1]]; // Ele-specific - static $aNA = ['aria-activedescendant' => 1, 'aria-atomic' => 1, 'aria-autocomplete' => 1, 'aria-busy' => 1, 'aria-checked' => 1, 'aria-controls' => 1, 'aria-describedby' => 1, 'aria-disabled' => 1, 'aria-dropeffect' => 1, 'aria-expanded' => 1, 'aria-flowto' => 1, 'aria-grabbed' => 1, 'aria-haspopup' => 1, 'aria-hidden' => 1, 'aria-invalid' => 1, 'aria-label' => 1, 'aria-labelledby' => 1, 'aria-level' => 1, 'aria-live' => 1, 'aria-multiline' => 1, 'aria-multiselectable' => 1, 'aria-orientation' => 1, 'aria-owns' => 1, 'aria-posinset' => 1, 'aria-pressed' => 1, 'aria-readonly' => 1, 'aria-relevant' => 1, 'aria-required' => 1, 'aria-selected' => 1, 'aria-setsize' => 1, 'aria-sort' => 1, 'aria-valuemax' => 1, 'aria-valuemin' => 1, 'aria-valuenow' => 1, 'aria-valuetext' => 1]; // ARIA + static $aN = ['abbr' => ['td' => 1, 'th' => 1], 'accept' => ['form' => 1, 'input' => 1], 'accept-charset' => ['form' => 1], 'action' => ['form' => 1], 'align' => ['applet' => 1, 'caption' => 1, 'col' => 1, 'colgroup' => 1, 'div' => 1, 'embed' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'hr' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'legend' => 1, 'object' => 1, 'p' => 1, 'table' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'allowfullscreen' => ['iframe' => 1], 'alt' => ['applet' => 1, 'area' => 1, 'img' => 1, 'input' => 1], 'archive' => ['applet' => 1, 'object' => 1], 'async' => ['script' => 1], 'autocomplete' => ['form' => 1, 'input' => 1], 'autofocus' => ['button' => 1, 'input' => 1, 'keygen' => 1, 'select' => 1, 'textarea' => 1], 'autoplay' => ['audio' => 1, 'video' => 1], 'axis' => ['td' => 1, 'th' => 1], 'bgcolor' => ['embed' => 1, 'table' => 1, 'td' => 1, 'th' => 1, 'tr' => 1], 'border' => ['img' => 1, 'object' => 1, 'table' => 1], 'bordercolor' => ['table' => 1, 'td' => 1, 'tr' => 1], 'cellpadding' => ['table' => 1], 'cellspacing' => ['table' => 1], 'challenge' => ['keygen' => 1], 'char' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'charoff' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'charset' => ['a' => 1, 'script' => 1], 'checked' => ['command' => 1, 'input' => 1], 'cite' => ['blockquote' => 1, 'del' => 1, 'ins' => 1, 'q' => 1], 'classid' => ['object' => 1], 'clear' => ['br' => 1], 'code' => ['applet' => 1], 'codebase' => ['applet' => 1, 'object' => 1], 'codetype' => ['object' => 1], 'color' => ['font' => 1], 'cols' => ['textarea' => 1], 'colspan' => ['td' => 1, 'th' => 1], 'compact' => ['dir' => 1, 'dl' => 1, 'menu' => 1, 'ol' => 1, 'ul' => 1], 'content' => ['meta' => 1], 'controls' => ['audio' => 1, 'video' => 1], 'coords' => ['a' => 1, 'area' => 1], 'crossorigin' => ['img' => 1], 'data' => ['object' => 1], 'datetime' => ['del' => 1, 'ins' => 1, 'time' => 1], 'declare' => ['object' => 1], 'default' => ['track' => 1], 'defer' => ['script' => 1], 'dirname' => ['input' => 1, 'textarea' => 1], 'disabled' => ['button' => 1, 'command' => 1, 'fieldset' => 1, 'input' => 1, 'keygen' => 1, 'optgroup' => 1, 'option' => 1, 'select' => 1, 'textarea' => 1], 'download' => ['a' => 1], 'enctype' => ['form' => 1], 'face' => ['font' => 1], 'flashvars' => ['embed' => 1], 'for' => ['label' => 1, 'output' => 1], 'form' => ['button' => 1, 'fieldset' => 1, 'input' => 1, 'keygen' => 1, 'label' => 1, 'object' => 1, 'output' => 1, 'select' => 1, 'textarea' => 1], 'formaction' => ['button' => 1, 'input' => 1], 'formenctype' => ['button' => 1, 'input' => 1], 'formmethod' => ['button' => 1, 'input' => 1], 'formnovalidate' => ['button' => 1, 'input' => 1], 'formtarget' => ['button' => 1, 'input' => 1], 'frame' => ['table' => 1], 'frameborder' => ['iframe' => 1], 'headers' => ['td' => 1, 'th' => 1], 'height' => ['applet' => 1, 'canvas' => 1, 'embed' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'object' => 1, 'td' => 1, 'th' => 1, 'video' => 1], 'high' => ['meter' => 1], 'href' => ['a' => 1, 'area' => 1, 'link' => 1], 'hreflang' => ['a' => 1, 'area' => 1, 'link' => 1], 'hspace' => ['applet' => 1, 'embed' => 1, 'img' => 1, 'object' => 1], 'icon' => ['command' => 1], 'ismap' => ['img' => 1, 'input' => 1], 'keyparams' => ['keygen' => 1], 'keytype' => ['keygen' => 1], 'kind' => ['track' => 1], 'label' => ['command' => 1, 'menu' => 1, 'option' => 1, 'optgroup' => 1, 'track' => 1], 'language' => ['script' => 1], 'list' => ['input' => 1], 'longdesc' => ['img' => 1, 'iframe' => 1], 'loop' => ['audio' => 1, 'video' => 1], 'low' => ['meter' => 1], 'marginheight' => ['iframe' => 1], 'marginwidth' => ['iframe' => 1], 'max' => ['input' => 1, 'meter' => 1, 'progress' => 1], 'maxlength' => ['input' => 1, 'textarea' => 1], 'media' => ['a' => 1, 'area' => 1, 'link' => 1, 'source' => 1, 'style' => 1], 'mediagroup' => ['audio' => 1, 'video' => 1], 'method' => ['form' => 1], 'min' => ['input' => 1, 'meter' => 1], 'model' => ['embed' => 1], 'multiple' => ['input' => 1, 'select' => 1], 'muted' => ['audio' => 1, 'video' => 1], 'name' => ['a' => 1, 'applet' => 1, 'button' => 1, 'embed' => 1, 'fieldset' => 1, 'form' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'keygen' => 1, 'map' => 1, 'object' => 1, 'output' => 1, 'param' => 1, 'select' => 1, 'slot' => 1, 'textarea' => 1], 'nohref' => ['area' => 1], 'noshade' => ['hr' => 1], 'novalidate' => ['form' => 1], 'nowrap' => ['td' => 1, 'th' => 1], 'object' => ['applet' => 1], 'open' => ['details' => 1, 'dialog' => 1], 'optimum' => ['meter' => 1], 'pattern' => ['input' => 1], 'ping' => ['a' => 1, 'area' => 1], 'placeholder' => ['input' => 1, 'textarea' => 1], 'pluginspage' => ['embed' => 1], 'pluginurl' => ['embed' => 1], 'poster' => ['video' => 1], 'pqg' => ['keygen' => 1], 'preload' => ['audio' => 1, 'video' => 1], 'prompt' => ['isindex' => 1], 'pubdate' => ['time' => 1], 'radiogroup' => ['command' => 1], 'readonly' => ['input' => 1, 'textarea' => 1], 'referrerpolicy' => ['a' => 1, 'area' => 1, 'img' => 1, 'iframe' => 1, 'link' => 1], 'rel' => ['a' => 1, 'area' => 1, 'link' => 1], 'required' => ['input' => 1, 'select' => 1, 'textarea' => 1], 'rev' => ['a' => 1], 'reversed' => ['ol' => 1], 'rows' => ['textarea' => 1], 'rowspan' => ['td' => 1, 'th' => 1], 'rules' => ['table' => 1], 'sandbox' => ['iframe' => 1], 'scope' => ['td' => 1, 'th' => 1], 'scoped' => ['style' => 1], 'scrolling' => ['iframe' => 1], 'seamless' => ['iframe' => 1], 'selected' => ['option' => 1], 'shape' => ['a' => 1, 'area' => 1], 'size' => ['font' => 1, 'hr' => 1, 'input' => 1, 'select' => 1], 'sizes' => ['link' => 1], 'span' => ['col' => 1, 'colgroup' => 1], 'src' => ['audio' => 1, 'embed' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'script' => 1, 'source' => 1, 'track' => 1, 'video' => 1], 'srcdoc' => ['iframe' => 1], 'srclang' => ['track' => 1], 'srcset' => ['img' => 1], 'standby' => ['object' => 1], 'start' => ['ol' => 1], 'step' => ['input' => 1], 'summary' => ['table' => 1], 'target' => ['a' => 1, 'area' => 1, 'form' => 1], 'type' => ['a' => 1, 'area' => 1, 'button' => 1, 'command' => 1, 'embed' => 1, 'input' => 1, 'li' => 1, 'link' => 1, 'menu' => 1, 'object' => 1, 'ol' => 1, 'param' => 1, 'script' => 1, 'source' => 1, 'style' => 1, 'ul' => 1], 'typemustmatch' => ['object' => 1], 'usemap' => ['img' => 1, 'input' => 1, 'object' => 1], 'valign' => ['col' => 1, 'colgroup' => 1, 'tbody' => 1, 'td' => 1, 'tfoot' => 1, 'th' => 1, 'thead' => 1, 'tr' => 1], 'value' => ['button' => 1, 'data' => 1, 'input' => 1, 'li' => 1, 'meter' => 1, 'option' => 1, 'param' => 1, 'progress' => 1], 'valuetype' => ['param' => 1], 'vspace' => ['applet' => 1, 'embed' => 1, 'img' => 1, 'object' => 1], 'width' => ['applet' => 1, 'canvas' => 1, 'col' => 1, 'colgroup' => 1, 'embed' => 1, 'hr' => 1, 'iframe' => 1, 'img' => 1, 'input' => 1, 'object' => 1, 'pre' => 1, 'table' => 1, 'td' => 1, 'th' => 1, 'video' => 1], 'wmode' => ['embed' => 1], 'wrap' => ['textarea' => 1]]; // Ele-specific + static $aNA = ['aria-activedescendant' => 1, 'aria-atomic' => 1, 'aria-autocomplete' => 1, 'aria-braillelabel' => 1, 'aria-brailleroledescription' => 1, 'aria-busy' => 1, 'aria-checked' => 1, 'aria-colcount' => 1, 'aria-colindex' => 1, 'aria-colindextext' => 1, 'aria-colspan' => 1, 'aria-controls' => 1, 'aria-current' => 1, 'aria-describedby' => 1, 'aria-description' => 1, 'aria-details' => 1, 'aria-disabled' => 1, 'aria-dropeffect' => 1, 'aria-errormessage' => 1, 'aria-expanded' => 1, 'aria-flowto' => 1, 'aria-grabbed' => 1, 'aria-haspopup' => 1, 'aria-hidden' => 1, 'aria-invalid' => 1, 'aria-keyshortcuts' => 1, 'aria-label' => 1, 'aria-labelledby' => 1, 'aria-level' => 1, 'aria-live' => 1, 'aria-multiline' => 1, 'aria-multiselectable' => 1, 'aria-orientation' => 1, 'aria-owns' => 1, 'aria-placeholder' => 1, 'aria-posinset' => 1, 'aria-pressed' => 1, 'aria-readonly' => 1, 'aria-relevant' => 1, 'aria-required' => 1, 'aria-roledescription' => 1, 'aria-rowcount' => 1, 'aria-rowindex' => 1, 'aria-rowindextext' => 1, 'aria-rowspan' => 1, 'aria-selected' => 1, 'aria-setsize' => 1, 'aria-sort' => 1, 'aria-valuemax' => 1, 'aria-valuemin' => 1, 'aria-valuenow' => 1, 'aria-valuetext' => 1]; // ARIA static $aNE = ['allowfullscreen' => 1, 'checkbox' => 1, 'checked' => 1, 'command' => 1, 'compact' => 1, 'declare' => 1, 'defer' => 1, 'default' => 1, 'disabled' => 1, 'hidden' => 1, 'inert' => 1, 'ismap' => 1, 'itemscope' => 1, 'multiple' => 1, 'nohref' => 1, 'noresize' => 1, 'noshade' => 1, 'nowrap' => 1, 'open' => 1, 'radio' => 1, 'readonly' => 1, 'required' => 1, 'reversed' => 1, 'selected' => 1]; // Empty - static $aNO = ['onabort' => 1, 'onblur' => 1, 'oncanplay' => 1, 'oncanplaythrough' => 1, 'onchange' => 1, 'onclick' => 1, 'oncontextmenu' => 1, 'oncopy' => 1, 'oncuechange' => 1, 'oncut' => 1, 'ondblclick' => 1, 'ondrag' => 1, 'ondragend' => 1, 'ondragenter' => 1, 'ondragleave' => 1, 'ondragover' => 1, 'ondragstart' => 1, 'ondrop' => 1, 'ondurationchange' => 1, 'onemptied' => 1, 'onended' => 1, 'onerror' => 1, 'onfocus' => 1, 'onformchange' => 1, 'onforminput' => 1, 'oninput' => 1, 'oninvalid' => 1, 'onkeydown' => 1, 'onkeypress' => 1, 'onkeyup' => 1, 'onload' => 1, 'onloadeddata' => 1, 'onloadedmetadata' => 1, 'onloadstart' => 1, 'onlostpointercapture' => 1, 'onmousedown' => 1, 'onmousemove' => 1, 'onmouseout' => 1, 'onmouseover' => 1, 'onmouseup' => 1, 'onmousewheel' => 1, 'onpaste' => 1, 'onpause' => 1, 'onplay' => 1, 'onplaying' => 1, 'onpointercancel' => 1, 'ongotpointercapture' => 1, 'onpointerdown' => 1, 'onpointerenter' => 1, 'onpointerleave' => 1, 'onpointermove' => 1, 'onpointerout' => 1, 'onpointerover' => 1, 'onpointerup' => 1, 'onprogress' => 1, 'onratechange' => 1, 'onreadystatechange' => 1, 'onreset' => 1, 'onsearch' => 1, 'onscroll' => 1, 'onseeked' => 1, 'onseeking' => 1, 'onselect' => 1, 'onshow' => 1, 'onstalled' => 1, 'onsubmit' => 1, 'onsuspend' => 1, 'ontimeupdate' => 1, 'ontoggle' => 1, 'ontouchcancel' => 1, 'ontouchend' => 1, 'ontouchmove' => 1, 'ontouchstart' => 1, 'onvolumechange' => 1, 'onwaiting' => 1, 'onwheel' => 1]; // Event + static $aNO = ['onabort' => 1, 'onblur' => 1, 'oncanplay' => 1, 'oncanplaythrough' => 1, 'onchange' => 1, 'onclick' => 1, 'oncontextmenu' => 1, 'oncopy' => 1, 'oncuechange' => 1, 'oncut' => 1, 'ondblclick' => 1, 'ondrag' => 1, 'ondragend' => 1, 'ondragenter' => 1, 'ondragleave' => 1, 'ondragover' => 1, 'ondragstart' => 1, 'ondrop' => 1, 'ondurationchange' => 1, 'onemptied' => 1, 'onended' => 1, 'onerror' => 1, 'onfocus' => 1, 'onformchange' => 1, 'onforminput' => 1, 'oninput' => 1, 'oninvalid' => 1, 'onkeydown' => 1, 'onkeypress' => 1, 'onkeyup' => 1, 'onload' => 1, 'onloadeddata' => 1, 'onloadedmetadata' => 1, 'onloadstart' => 1, 'onlostpointercapture' => 1, 'onmousedown' => 1, 'onmousemove' => 1, 'onmouseout' => 1, 'onmouseover' => 1, 'onmouseup' => 1, 'onmousewheel' => 1, 'onpaste' => 1, 'onpause' => 1, 'onplay' => 1, 'onplaying' => 1, 'onpointercancel' => 1, 'ongotpointercapture' => 1, 'onpointerdown' => 1, 'onpointerenter' => 1, 'onpointerleave' => 1, 'onpointermove' => 1, 'onpointerout' => 1, 'onpointerover' => 1, 'onpointerup' => 1, 'onprogress' => 1, 'onratechange' => 1, 'onreadystatechange' => 1, 'onreset' => 1, 'onsearch' => 1, 'onscroll' => 1, 'onseeked' => 1, 'onseeking' => 1, 'onselect' => 1, 'onshow' => 1, 'onstalled' => 1, 'onsubmit' => 1, 'onsuspend' => 1, 'ontimeupdate' => 1, 'ontoggle' => 1, 'ontouchcancel' => 1, 'ontouchend' => 1, 'ontouchmove' => 1, 'ontouchstart' => 1, 'onvolumechange' => 1, 'onwaiting' => 1, 'onwheel' => 1, 'onauxclick' => 1, 'oncancel' => 1, 'onclose' => 1, 'oncontextlost' => 1, 'oncontextrestored' => 1, 'onformdata' => 1, 'onmouseenter' => 1, 'onmouseleave' => 1, 'onresize' => 1, 'onsecuritypolicyviolation' => 1, 'onslotchange' => 1]; // Event static $aNP = ['action' => 1, 'cite' => 1, 'classid' => 1, 'codebase' => 1, 'data' => 1, 'href' => 1, 'itemtype' => 1, 'longdesc' => 1, 'model' => 1, 'pluginspage' => 1, 'pluginurl' => 1, 'src' => 1, 'srcset' => 1, 'usemap' => 1]; // Need scheme check; excludes style, on* - static $aNU = ['accesskey' => 1, 'class' => 1, 'contenteditable' => 1, 'contextmenu' => 1, 'dir' => 1, 'draggable' => 1, 'dropzone' => 1, 'hidden' => 1, 'id' => 1, 'inert' => 1, 'itemid' => 1, 'itemprop' => 1, 'itemref' => 1, 'itemscope' => 1, 'itemtype' => 1, 'lang' => 1, 'role' => 1, 'spellcheck' => 1, 'style' => 1, 'tabindex' => 1, 'title' => 1, 'translate' => 1, 'xmlns' => 1, 'xml:base' => 1, 'xml:lang' => 1, 'xml:space' => 1]; // Univ; excludes on*, aria* + static $aNU = ['accesskey' => 1, 'autocapitalize' => 1, 'autofocus' => 1, 'class' => 1, 'contenteditable' => 1, 'contextmenu' => 1, 'dir' => 1, 'draggable' => 1, 'dropzone' => 1, 'enterkeyhint' => 1, 'hidden' => 1, 'id' => 1, 'inert' => 1, 'inputmode' => 1, 'is' => 1, 'itemid' => 1, 'itemprop' => 1, 'itemref' => 1, 'itemscope' => 1, 'itemtype' => 1, 'lang' => 1, 'nonce' => 1, 'role' => 1, 'slot' => 1, 'spellcheck' => 1, 'style' => 1, 'tabindex' => 1, 'title' => 1, 'translate' => 1, 'xmlns' => 1, 'xml:base' => 1, 'xml:lang' => 1, 'xml:space' => 1]; // Univ; excludes on*, aria* if ($C['lc_std_val']) { // predef attr vals for $eAL & $aNE ele @@ -753,7 +777,7 @@ function hl_tag($t) $w = 0; switch ($mode) { case 0: // Name - if (preg_match('`^[a-zA-Z][^\s=/]+`', $a, $m)) { + if (preg_match('`^[^=\s/\x7f-\x9f]+`', $a, $m)) { $nm = strtolower($m[0]); $w = $mode = 1; $a = ltrim(substr_replace($a, '', 0, strlen($m[0]))); @@ -797,7 +821,7 @@ function hl_tag($t) $nfr = 0; $d = $C['deny_attribute']; foreach ($aA as $k => $v) { - if (((isset($d['*']) ? isset($d[$k]) : !isset($d[$k])) && (isset($aN[$k][$e]) || isset($aNU[$k]) || (isset($aNO[$k]) && !isset($d['on*'])) || (isset($aNA[$k]) && !isset($d['aria*'])) || (!isset($d['data*']) && preg_match('`data-((?!xml)[^:]+$)`', $k))) && !isset($rl['n'][$k]) && !isset($rl['n']['*'])) || isset($rl[$k])) { + if (((isset($d['*']) ? isset($d[$k]) : !isset($d[$k])) && (isset($aN[$k][$e]) || isset($aNU[$k]) || (isset($aNO[$k]) && !isset($d['on*'])) || (isset($aNA[$k]) && !isset($d['aria*'])) || (!isset($d['data*']) && preg_match('`data-((?!xml)[^:]+$)`', $k)) || strpos($e, '-')) && !isset($rl['n'][$k]) && !isset($rl['n']['*'])) || isset($rl[$k])) { if (isset($aNE[$k])) { $v = $k; } elseif (!empty($lcase) && (('button' !== $e || 'input' !== $e) || 'type' === $k)) { // Rather loose but ?not cause issues @@ -920,7 +944,7 @@ function hl_tag($t) $c[] = 'font-size: 85%'; } elseif ('height' === $k || 'width' === $k) { unset($a[$k]); - $c[] = $k . ': ' . ('*' !== $v[0] ? $v . (ctype_digit($v) ? 'px' : '') : 'auto'); + $c[] = $k . ': ' . (isset($v[0]) && '*' !== $v[0] ? $v . (ctype_digit($v) ? 'px' : '') : 'auto'); } elseif ('hspace' === $k) { unset($a['hspace']); $c[] = "margin-left: {$v}px; margin-right: {$v}px"; @@ -1067,7 +1091,7 @@ function hl_aux2($m) $a = ['br' => 1]; $b = ['button' => 1, 'command' => 1, 'input' => 1, 'option' => 1, 'param' => 1, 'track' => 1]; $c = ['audio' => 1, 'canvas' => 1, 'caption' => 1, 'dd' => 1, 'dt' => 1, 'figcaption' => 1, 'h1' => 1, 'h2' => 1, 'h3' => 1, 'h4' => 1, 'h5' => 1, 'h6' => 1, 'isindex' => 1, 'label' => 1, 'legend' => 1, 'li' => 1, 'object' => 1, 'p' => 1, 'pre' => 1, 'style' => 1, 'summary' => 1, 'td' => 1, 'textarea' => 1, 'th' => 1, 'video' => 1]; - $d = ['address' => 1, 'article' => 1, 'aside' => 1, 'blockquote' => 1, 'center' => 1, 'colgroup' => 1, 'datalist' => 1, 'details' => 1, 'dir' => 1, 'div' => 1, 'dl' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'form' => 1, 'header' => 1, 'hgroup' => 1, 'hr' => 1, 'iframe' => 1, 'main' => 1, 'map' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'ol' => 1, 'optgroup' => 1, 'rbc' => 1, 'rtc' => 1, 'ruby' => 1, 'script' => 1, 'section' => 1, 'select' => 1, 'table' => 1, 'tbody' => 1, 'tfoot' => 1, 'thead' => 1, 'tr' => 1, 'ul' => 1]; + $d = ['address' => 1, 'article' => 1, 'aside' => 1, 'blockquote' => 1, 'center' => 1, 'colgroup' => 1, 'datalist' => 1, 'details' => 1, 'dialog' => 1, 'dir' => 1, 'div' => 1, 'dl' => 1, 'fieldset' => 1, 'figure' => 1, 'footer' => 1, 'form' => 1, 'header' => 1, 'hgroup' => 1, 'hr' => 1, 'iframe' => 1, 'main' => 1, 'map' => 1, 'menu' => 1, 'nav' => 1, 'noscript' => 1, 'ol' => 1, 'optgroup' => 1, 'picture' => 1, 'rbc' => 1, 'rtc' => 1, 'ruby' => 1, 'script' => 1, 'section' => 1, 'select' => 1, 'table' => 1, 'tbody' => 1, 'template' => 1, 'tfoot' => 1, 'thead' => 1, 'tr' => 1, 'ul' => 1]; $T = explode('<', $t); $X = 1; while ($X) { @@ -1130,5 +1154,5 @@ function hl_aux2($m) function hl_version() { // version - return '1.2.6'; + return '1.2.7'; }