<?php
$redefs = '(?(DEFINE)
(?<tagname> [a-z][^\s>/]*+ )
(?<attname> [^\s>/][^\s=>/]*+ ) # first char can be pretty much anything, including =
(?<attval> (?>
"[^"]*+" |
\'[^\']*+\' |
[^\s>]*+ # unquoted values can contain quotes, = and /
)
)
(?<attrib> (?&attname)
(?: \s*+
= \s*+
(?&attval)
)?+
)
(?<crap> [^\s>] ) # most crap inside tag is ignored, will eat the last / in self closing tags
(?<tag> <(?&tagname)
(?: \s*+ # spaces between attributes not required: <b/foo=">"style=color:red>bold red text</b>
(?>
(?&attrib) | # order matters
(?&crap) # if not an attribute, eat the crap
)
)*+
\s*+ /?+
\s*+ >
)
)';
// removes onanything attributes from all matched HTML tags
function remove_event_attributes($html){
global $redefs;
$re = '(?&tag)' . $redefs;
return preg_replace("~$re~xie", 'remove_event_attributes_from_tag("$0")', $html); }
// removes onanything attributes from a single opening tag
function remove_event_attributes_from_tag($tag){
global $redefs;
$re = '( ^ <(?&tagname) ) | \G \s*+ (?> ((?&attrib)) | ((?&crap)) )' . $redefs;
return preg_replace("~$re~xie", '"$1$3"? "$0": (preg_match("/^on/i", "$2")? " ": "$0")', $tag); }
// test
$str = '
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz />
';
echo $str . "\n----------------------\n";
echo remove_event_attributes($str);
?>
PD9waHAKCiRyZWRlZnMgPSAnKD8oREVGSU5FKQogICAgKD88dGFnbmFtZT4gW2Etel1bXlxzPi9dKisgICAgKQogICAgKD88YXR0bmFtZT4gW15ccz4vXVteXHM9Pi9dKisgICAgKSAgIyBmaXJzdCBjaGFyIGNhbiBiZSBwcmV0dHkgbXVjaCBhbnl0aGluZywgaW5jbHVkaW5nID0KICAgICg/PGF0dHZhbD4gICg/PgogICAgICAgICAgICAgICAgICAgICJbXiJdKisiIHwKICAgICAgICAgICAgICAgICAgICBcJ1teXCddKitcJyB8CiAgICAgICAgICAgICAgICAgICAgW15ccz5dKisgICAgICAgICAgICAjIHVucXVvdGVkIHZhbHVlcyBjYW4gY29udGFpbiBxdW90ZXMsID0gYW5kIC8KICAgICAgICAgICAgICAgICkKICAgICkgCiAgICAoPzxhdHRyaWI+ICAoPyZhdHRuYW1lKQogICAgICAgICAgICAgICAgKD86IFxzKisKICAgICAgICAgICAgICAgICAgICA9IFxzKisKICAgICAgICAgICAgICAgICAgICAoPyZhdHR2YWwpCiAgICAgICAgICAgICAgICApPysKICAgICkKICAgICg/PGNyYXA+ICAgIFteXHM+XSAgICApICAgICAgICAgICAgICMgbW9zdCBjcmFwIGluc2lkZSB0YWcgaXMgaWdub3JlZCwgd2lsbCBlYXQgdGhlIGxhc3QgLyBpbiBzZWxmIGNsb3NpbmcgdGFncwogICAgKD88dGFnPiAgICAgPCg/JnRhZ25hbWUpCiAgICAgICAgICAgICAgICAoPzogXHMqKyAgICAgICAgICAgICAgICAjIHNwYWNlcyBiZXR3ZWVuIGF0dHJpYnV0ZXMgbm90IHJlcXVpcmVkOiA8Yi9mb289Ij4ic3R5bGU9Y29sb3I6cmVkPmJvbGQgcmVkIHRleHQ8L2I+CiAgICAgICAgICAgICAgICAgICAgKD8+CiAgICAgICAgICAgICAgICAgICAgICAgICg/JmF0dHJpYikgfCAgICAjIG9yZGVyIG1hdHRlcnMKICAgICAgICAgICAgICAgICAgICAgICAgKD8mY3JhcCkgICAgICAgICMgaWYgbm90IGFuIGF0dHJpYnV0ZSwgZWF0IHRoZSBjcmFwCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSorCiAgICAgICAgICAgICAgICBccyorIC8/KwogICAgICAgICAgICAgICAgXHMqKyA+CiAgICApCiknOwoKCi8vIHJlbW92ZXMgb25hbnl0aGluZyBhdHRyaWJ1dGVzIGZyb20gYWxsIG1hdGNoZWQgSFRNTCB0YWdzCmZ1bmN0aW9uIHJlbW92ZV9ldmVudF9hdHRyaWJ1dGVzKCRodG1sKXsKCWdsb2JhbCAkcmVkZWZzOwoJJHJlID0gJyg/JnRhZyknIC4gJHJlZGVmczsKCXJldHVybiBwcmVnX3JlcGxhY2UoIn4kcmV+eGllIiwgJ3JlbW92ZV9ldmVudF9hdHRyaWJ1dGVzX2Zyb21fdGFnKCIkMCIpJywgJGh0bWwpOwp9CgovLyByZW1vdmVzIG9uYW55dGhpbmcgYXR0cmlidXRlcyBmcm9tIGEgc2luZ2xlIG9wZW5pbmcgdGFnCmZ1bmN0aW9uIHJlbW92ZV9ldmVudF9hdHRyaWJ1dGVzX2Zyb21fdGFnKCR0YWcpewoJZ2xvYmFsICRyZWRlZnM7CgkkcmUgPSAnKCBeIDwoPyZ0YWduYW1lKSApIHwgXEcgXHMqKyAoPz4gKCg/JmF0dHJpYikpIHwgKCg/JmNyYXApKSApJyAuICRyZWRlZnM7CglyZXR1cm4gcHJlZ19yZXBsYWNlKCJ+JHJlfnhpZSIsICciJDEkMyI/ICIkMCI6IChwcmVnX21hdGNoKCIvXm9uL2kiLCAiJDIiKT8gIiAiOiAiJDAiKScsICR0YWcpOwp9CgoKLy8gdGVzdAokc3RyID0gJwo8YnV0dG9uIG9uY2xpY2s9Ii4uamF2YXNjcmlwdCBpbnN0cnVjdGlvbi4uIj4KPGJ1dHRvbiBvbmNsaWNrPSIuLmphdmFzY3JpcHQgaW5zdHJ1Y3Rpb24uLiIgdmFsdWU9Ii4uIj4KPGJ1dHRvbiBvbmNsaWNrPS4uamF2YXNjcmlwdF9pbnN0cnVjdGlvbi4uPgo8YnV0dG9uIG9uY2xpY2s9Li5qYXZhc2NyaXB0X2luc3RydWN0aW9uLi4gdmFsdWU+CjxoZWxsbyB3b3JkICIiIG9udGVzdCA9ICJoYWkieD0ieSJvbmZvbz1iYXIvYmF6ICAvPgonOwoKZWNobyAkc3RyIC4gIlxuLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIjsKCmVjaG8gcmVtb3ZlX2V2ZW50X2F0dHJpYnV0ZXMoJHN0cik7Cgo/Pg==