PluginProbe
Autoptimize / 3.0.3
Autoptimize v3.0.3
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
← All changes | classes/autoptimizeStyles.php +58 -13 2.7.73.0.3 View file →
@@ -163,14 +163,13 @@
163 163 */
164 164 public function read( $options )
165 165 {
166 166 $noptimize_css = apply_filters( 'autoptimize_filter_css_noptimize', false, $this->content );
167 - if ( $noptimize_css ) {
167 + if ( $noptimize_css || false === autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_css_optimize' )) {
168 168 return false;
169 169 }
170 170
171 171 $allowlist_css = apply_filters( 'autoptimize_filter_css_allowlist', '', $this->content );
172 - $allowlist_css = apply_filters( 'autoptimize_filter_css_whitelist', $allowlist_css, $this->content ); // fixme: to be removed in next version.
173 172 if ( ! empty( $allowlist_css ) ) {
174 173 $this->allowlist = array_filter( array_map( 'trim', explode( ',', $allowlist_css ) ) );
175 174 }
176 175
@@ -198,8 +197,10 @@
198 197 // Returning true for "dontaggregate" turns off aggregation.
199 198 if ( $this->aggregate && apply_filters( 'autoptimize_filter_css_dontaggregate', false ) ) {
200 199 $this->aggregate = false;
201 200 }
201 + // and the filter that should have been there to begin with.
202 + $this->aggregate = apply_filters( 'autoptimize_filter_css_aggregate', $this->aggregate );
202 203
203 204 // include inline?
204 205 if ( apply_filters( 'autoptimize_css_include_inline', $options['include_inline'] ) ) {
205 206 $this->include_inline = true;
@@ -215,16 +216,24 @@
215 216
216 217 // forcefully exclude CSS with data-noptimize attrib.
217 218 $this->dontmove[] = 'data-noptimize';
218 219
220 + // forcefully exclude inline CSS with ".wp-container-" which due to the random-ish nature busts AO's cache continuously.
221 + $this->dontmove[] = '.wp-container-';
222 +
219 223 // Should we defer css?
220 224 // value: true / false.
221 225 $this->defer = $options['defer'];
222 226 $this->defer = apply_filters( 'autoptimize_filter_css_defer', $this->defer, $this->content );
223 227
228 + // If page/ post check post_meta to see if optimize is off.
229 + if ( $this->defer && false === autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_ccss' ) ) {
230 + $this->defer = false;
231 + }
232 +
224 233 // Should we inline while deferring?
225 234 // value: inlined CSS.
226 - $this->defer_inline = apply_filters( 'autoptimize_filter_css_defer_inline', $options['defer_inline'], $this->content );
235 + $this->defer_inline = apply_filters( 'autoptimize_filter_css_defer_inline', $this->sanitize_css( $options['defer_inline'] ), $this->content );
227 236
228 237 // Should we inline?
229 238 // value: true / false.
230 239 $this->inline = $options['inline'];
@@ -271,16 +280,20 @@
271 280 } elseif ( $this->ismovable( $tag ) ) {
272 281 // Get the media.
273 282 if ( false !== strpos( $tag, 'media=' ) ) {
274 283 preg_match( '#media=(?:"|\')([^>]*)(?:"|\')#Ui', $tag, $medias );
275 - $medias = explode( ',', $medias[1] );
276 - $media = array();
277 - foreach ( $medias as $elem ) {
278 - if ( empty( $elem ) ) {
279 - $elem = 'all';
284 + if ( !empty( $medias ) ) {
285 + $medias = explode( ',', $medias[1] );
286 + $media = array();
287 + foreach ( $medias as $elem ) {
288 + if ( empty( $elem ) ) {
289 + $elem = 'all';
290 + }
291 +
292 + $media[] = $elem;
280 293 }
281 -
282 - $media[] = $elem;
294 + } else {
295 + $media = array( 'all' );
283 296 }
284 297 } else {
285 298 // No media specified - applies to all.
286 299 $media = array( 'all' );
@@ -354,8 +367,13 @@
354 367
355 368 if ( '' !== $new_tag ) {
356 369 // Optionally defer (preload) non-aggregated CSS.
357 370 $new_tag = $this->optionally_defer_excluded( $new_tag, $url );
371 +
372 + // Check if we still need to CDN (esp. for already minified resources).
373 + if ( ! empty( $this->cdn_url ) || has_filter( 'autoptimize_filter_base_replace_cdn' ) ) {
374 + $new_tag = str_replace( $url, $this->url_replace_cdn( $url ), $new_tag );
375 + }
358 376 }
359 377
360 378 // And replace!
361 379 if ( ( '' !== $new_tag && $new_tag !== $tag ) || ( '' === $new_tag && apply_filters( 'autoptimize_filter_css_remove_empty_files', false ) ) ) {
@@ -472,9 +490,9 @@
472 490
473 491 private function check_datauri_exclude_list( $url )
474 492 {
475 493 static $exclude_list = null;
476 - $no_datauris = array();
494 + static $no_datauris = array();
477 495
478 496 // Again, skip doing certain stuff repeatedly when loop-called.
479 497 if ( null === $exclude_list ) {
480 498 $exclude_list = apply_filters( 'autoptimize_filter_css_datauri_exclude', '' );
@@ -854,9 +872,9 @@
854 872 $code = self::build_injectlater_marker( $path, md5( $code ) );
855 873 }
856 874
857 875 if ( ! empty( $code ) ) {
858 - $tmp_thiscss = preg_replace( '#(/\*FILESTART\*/.*)' . preg_quote( $import, '#' ) . '#Us', '/*FILESTART2*/' . $code . '$1', $thiscss );
876 + $tmp_thiscss = str_replace( $import, stripcslashes( $code ), $thiscss );
859 877 if ( ! empty( $tmp_thiscss ) ) {
860 878 $thiscss = $tmp_thiscss;
861 879 $import_ok = true;
862 880 unset( $tmp_thiscss );
@@ -1026,9 +1044,9 @@
1026 1044 // Add the stylesheet either deferred (import at bottom) or normal links in head.
1027 1045 if ( $this->defer && 'print' !== $media ) {
1028 1046 $preload_onload = autoptimizeConfig::get_ao_css_preload_onload( $media );
1029 1047
1030 - $preload_css_block .= '<link rel="stylesheet" media="print" href="' . $url . '" onload="' . $preload_onload . '" />';
1048 + $preload_css_block .= apply_filters( 'autoptimize_filter_css_single_deferred_link', '<link rel="stylesheet" media="print" href="' . $url . '" onload="' . $preload_onload . '" />' );
1031 1049 if ( apply_filters( 'autoptimize_fitler_css_preload_and_print', false ) ) {
1032 1050 $preload_css_block = '<link rel="preload" as="stylesheet" href="' . $url . '"/>' . $preload_css_block;
1033 1051 }
1034 1052 $noscript_css_block .= '<link ' . $type_css . 'media="' . $media . '" href="' . $url . '" rel="stylesheet" />';
@@ -1207,8 +1225,15 @@
1207 1225 {
1208 1226 $contents = $this->prepare_minify_single( $filepath );
1209 1227
1210 1228 if ( empty( $contents ) ) {
1229 + // if aggregate is off and CCSS is used but all files are minified already, then we
1230 + // must make sure the autoptimize_action_css_hash action still fires for CCSS's sake.
1231 + $ao_ccss_key = get_option( 'autoptimize_ccss_key', '' );
1232 + if ( false === $this->aggregate && isset( $ao_ccss_key ) && ! empty( $ao_ccss_key ) ) {
1233 + $hash = 'single_' . md5( file_get_contents( $filepath ) );
1234 + do_action( 'autoptimize_action_css_hash', $hash );
1235 + }
1211 1236 return false;
1212 1237 }
1213 1238
1214 1239 // Check cache.
@@ -1273,6 +1298,26 @@
1273 1298
1274 1299 public function getOption( $name )
1275 1300 {
1276 1301 return $this->options[ $name ];
1302 + }
1303 +
1304 + /**
1305 + * Sanitize user-provided CSS.
1306 + *
1307 + * For now just strip_tags (the WordPress way) and preg_replace to escape < in certain cases but might do full CSS escaping in the future, see:
1308 + * https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-4-css-encode-and-strictly-validate-before-inserting-untrusted-data-into-html-style-property-values
1309 + * https://github.com/twigphp/Twig/blob/3.x/src/Extension/EscaperExtension.php#L300-L319
1310 + * https://github.com/laminas/laminas-escaper/blob/2.8.x/src/Escaper.php#L205-L221
1311 + *
1312 + * @param string $css the to be sanitized CSS
1313 + * @return string sanitized CSS.
1314 + */
1315 + public static function sanitize_css( $css )
1316 + {
1317 + $css = wp_strip_all_tags( $css );
1318 + if ( strpos( $css, '<' ) !== false ) {
1319 + $css = preg_replace( '#<(\/?\w+)#', '\00003C$1', $css );
1320 + }
1321 + return $css;
1277 1322 }
1278 1323 }