30 public $name =
'ExtractStyleBlocks';
59 $this->_tidy =
new csstidy();
60 $this->_tidy->set_cfg(
'lowercase_s',
false);
81 $this->_styleMatches[] = $matches[1];
94 $tidy = $config->get(
'Filter.ExtractStyleBlocks.TidyImpl');
98 $html = preg_replace_callback(
'#<style(?:\s.*)?>(.+)</style>#isU', array($this,
'styleCallback'), $html);
100 $this->_styleMatches = array();
101 $context->register(
'StyleBlocks', $style_blocks);
103 foreach ($style_blocks as &$style) {
104 $style = $this->
cleanCSS($style, $config, $context);
122 $scope = $config->get(
'Filter.ExtractStyleBlocks.Scope');
123 if ($scope !== null) {
124 $scopes = array_map(
'trim', explode(
',', $scope));
130 if (strncmp(
'<!--', $css, 4) === 0) {
131 $css = substr($css, 4);
133 if (strlen($css) > 3 && substr($css, -3) ==
'-->') {
134 $css = substr($css, 0, -3);
137 set_error_handler(
'htmlpurifier_filter_extractstyleblocks_muteerrorhandler');
138 $this->_tidy->parse($css);
139 restore_error_handler();
140 $css_definition = $config->getDefinition(
'CSS');
141 $html_definition = $config->getDefinition(
'HTML');
143 foreach ($this->_tidy->css as $k => $decls) {
145 $new_decls = array();
146 foreach ($decls as $selector => $style) {
147 $selector = trim($selector);
148 if ($selector ===
'') {
213 $selectors = array_map(
'trim', explode(
',', $selector));
214 $new_selectors = array();
215 foreach ($selectors as $sel) {
217 $basic_selectors = preg_split(
'/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE);
223 for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) {
224 $x = $basic_selectors[$i];
230 $delim =
' ' . $x .
' ';
234 $components = preg_split(
'/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE);
237 for ($j = 0, $cc = count($components); $j < $cc; $j++) {
238 $y = $components[$j];
240 if ($y ===
'*' || isset($html_definition->info[$y = strtolower($y)])) {
254 if ($sdelim ===
'#') {
256 } elseif ($sdelim ===
'.') {
258 } elseif ($sdelim ===
':') {
263 $r = $attrdef->validate($y, $config, $context);
276 if ($nsel === null) {
279 $nsel .= $delim . $nx;
287 if ($nsel !== null) {
288 if (!empty($scopes)) {
289 foreach ($scopes as $s) {
290 $new_selectors[] =
"$s $nsel";
293 $new_selectors[] = $nsel;
297 if (empty($new_selectors)) {
300 $selector = implode(
', ', $new_selectors);
301 foreach ($style as
$name => $value) {
302 if (!isset($css_definition->info[
$name])) {
303 unset($style[
$name]);
306 $def = $css_definition->info[
$name];
307 $ret = $def->validate($value, $config, $context);
308 if (
$ret ===
false) {
309 unset($style[
$name]);
314 $new_decls[$selector] = $style;
316 $new_css[$k] = $new_decls;
320 $this->_tidy->css = $new_css;
321 $this->_tidy->import = array();
322 $this->_tidy->charset = null;
323 $this->_tidy->namespace = null;
324 $css = $this->_tidy->print->plain();
327 if ($config->get(
'Filter.ExtractStyleBlocks.Escaping')) {
329 array(
'<',
'>',
'&'),
330 array(
'\3C ',
'\3E ',
'\26 '),