| | |
| | | $source = self::xss_entity_decode($source); |
| | | $stripped = preg_replace('/[^a-z\(:;]/i', '', $source); |
| | | $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : ''); |
| | | |
| | | if (preg_match("/$evilexpr/i", $stripped)) { |
| | | return '/* evil! */'; |
| | | } |
| | | |
| | | $strict_url_regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims'; |
| | | |
| | | // cut out all contents between { and } |
| | | while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) { |
| | | $styles = substr($source, $pos+1, $pos2-($pos+1)); |
| | | $length = $pos2 - $pos - 1; |
| | | $styles = substr($source, $pos+1, $length); |
| | | |
| | | // check every line of a style block... |
| | | if ($allow_remote) { |
| | | $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY); |
| | | |
| | | foreach ($a_styles as $line) { |
| | | $stripped = preg_replace('/[^a-z\(:;]/i', '', $line); |
| | | // ... and only allow strict url() values |
| | | $regexp = '!url\s*\([ "\'](https?:)//[a-z0-9/._+-]+["\' ]\)!Uims'; |
| | | if (stripos($stripped, 'url(') && !preg_match($regexp, $line)) { |
| | | if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) { |
| | | $a_styles = array('/* evil! */'); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | $styles = join(";\n", $a_styles); |
| | | } |
| | | |
| | | $key = $replacements->add($styles); |
| | | $source = substr($source, 0, $pos+1) |
| | | . $replacements->get_replacement($key) |
| | | . substr($source, $pos2, strlen($source)-$pos2); |
| | | $last_pos = $pos+2; |
| | | $key = $replacements->add($styles); |
| | | $repl = $replacements->get_replacement($key); |
| | | $source = substr_replace($source, $repl, $pos+1, $length); |
| | | $last_pos = $pos2 - ($length - strlen($repl)); |
| | | } |
| | | |
| | | // remove html comments and add #container to each tag selector. |
| | | // also replace body definition because we also stripped off the <body> tag |
| | | $styles = preg_replace( |
| | | $source = preg_replace( |
| | | array( |
| | | '/(^\s*<!--)|(-->\s*$)/', |
| | | '/(^\s*<\!--)|(-->\s*$)/m', |
| | | '/(^\s*|,\s*|\}\s*)([a-z0-9\._#\*][a-z0-9\.\-_]*)/im', |
| | | '/'.preg_quote($container_id, '/').'\s+body/i', |
| | | ), |
| | |
| | | $source); |
| | | |
| | | // put block contents back in |
| | | $styles = $replacements->resolve($styles); |
| | | $source = $replacements->resolve($source); |
| | | |
| | | return $styles; |
| | | return $source; |
| | | } |
| | | |
| | | |