26 public $name =
'ExtractStyleBlocks';
35 $this->_tidy =
new csstidy();
38 $this->_enum_attrdef =
new HTMLPurifier_AttrDef_Enum(array(
'first-child',
'link',
'visited',
'active',
'hover',
'focus'));
46 $this->_styleMatches[] = $matches[1];
54 $tidy =
$config->get(
'Filter.ExtractStyleBlocks.TidyImpl');
55 if ($tidy !== null) $this->_tidy = $tidy;
56 $html = preg_replace_callback(
'#<style(?:\s.*)?>(.+)</style>#isU', array($this,
'styleCallback'),
$html);
58 $this->_styleMatches = array();
59 $context->register(
'StyleBlocks', $style_blocks);
61 foreach ($style_blocks as &$style) {
78 $scope =
$config->get(
'Filter.ExtractStyleBlocks.Scope');
79 if ($scope !== null) {
80 $scopes = array_map(
'trim', explode(
',', $scope));
86 if (strncmp(
'<!--', $css, 4) === 0) {
87 $css = substr($css, 4);
89 if (strlen($css) > 3 && substr($css, -3) ==
'-->') {
90 $css = substr($css, 0, -3);
93 set_error_handler(
'htmlpurifier_filter_extractstyleblocks_muteerrorhandler');
94 $this->_tidy->parse($css);
95 restore_error_handler();
96 $css_definition =
$config->getDefinition(
'CSS');
97 $html_definition =
$config->getDefinition(
'HTML');
99 foreach ($this->_tidy->css as $k => $decls) {
101 $new_decls = array();
102 foreach ($decls as $selector => $style) {
103 $selector = trim($selector);
104 if ($selector ===
'')
continue;
167 $selectors = array_map(
'trim', explode(
',', $selector));
168 $new_selectors = array();
169 foreach ($selectors as
$sel) {
171 $basic_selectors = preg_split(
'/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE);
177 for (
$i = 0, $c = count($basic_selectors);
$i < $c;
$i++) {
178 $x = $basic_selectors[
$i];
184 $delim =
' ' . $x .
' ';
188 $components = preg_split(
'/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE);
191 for (
$j = 0, $cc = count($components);
$j < $cc;
$j ++) {
192 $y = $components[
$j];
194 if ($y ===
'*' || isset($html_definition->info[$y = strtolower($y)])) {
208 if ($sdelim ===
'#') {
210 } elseif ($sdelim ===
'.') {
212 } elseif ($sdelim ===
':') {
217 $r = $attrdef->validate($y,
$config, $context);
230 if ($nsel === null) {
233 $nsel .= $delim . $nx;
241 if ($nsel !== null) {
242 if (!empty($scopes)) {
243 foreach ($scopes as $s) {
244 $new_selectors[] =
"$s $nsel";
247 $new_selectors[] = $nsel;
251 if (empty($new_selectors))
continue;
252 $selector = implode(
', ', $new_selectors);
253 foreach ($style as
$name => $value) {
254 if (!isset($css_definition->info[
$name])) {
255 unset($style[
$name]);
258 $def = $css_definition->info[
$name];
260 if (
$ret ===
false) unset($style[
$name]);
263 $new_decls[$selector] = $style;
265 $new_css[$k] = $new_decls;
269 $this->_tidy->css = $new_css;
270 $this->_tidy->import = array();
271 $this->_tidy->charset = null;
272 $this->_tidy->namespace = null;
273 $css = $this->_tidy->print->plain();
276 if (
$config->get(
'Filter.ExtractStyleBlocks.Escaping')) {
278 array(
'<',
'>',
'&'),
279 array(
'\3C ',
'\3E ',
'\26 '),