PluginProbe
Autoptimize / trunk
Autoptimize vtrunk
3.1.16 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 All 108 releases
← All changes | classes/autoptimizeCriticalCSSSettingsAjax.php +284 -51 2.7.7 → trunk View file →
@@ -7,16 +7,17 @@
7 7 exit;
8 8 }
9 9
10 10 class autoptimizeCriticalCSSSettingsAjax {
11 - public function __construct()
12 - {
13 - // fetch all options at once and populate them individually explicitely as globals.
14 - $all_options = autoptimizeCriticalCSSBase::fetch_options();
15 - foreach ( $all_options as $_option => $_value ) {
16 - global ${$_option};
17 - ${$_option} = $_value;
18 - }
11 + /**
12 + * Critical CSS object.
13 + *
14 + * @var object
15 + */
16 + protected $criticalcss;
17 +
18 + public function __construct() {
19 + $this->criticalcss = autoptimize()->criticalcss();
19 20 $this->run();
20 21 }
21 22
22 23 public function run() {
@@ -26,8 +27,10 @@
26 27 add_action( 'wp_ajax_rm_critcss', array( $this, 'critcss_rm_callback' ) );
27 28 add_action( 'wp_ajax_rm_critcss_all', array( $this, 'critcss_rm_all_callback' ) );
28 29 add_action( 'wp_ajax_ao_ccss_export', array( $this, 'ao_ccss_export_callback' ) );
29 30 add_action( 'wp_ajax_ao_ccss_import', array( $this, 'ao_ccss_import_callback' ) );
31 + add_action( 'wp_ajax_ao_ccss_queuerunner', array( $this, 'ao_ccss_queuerunner_callback' ) );
32 + add_action( 'wp_ajax_ao_ccss_saverules', array( $this, 'ao_ccss_saverules_callback' ) );
30 33 }
31 34
32 35 public function critcss_fetch_callback() {
33 36 // Ajax handler to obtain a critical CSS file from the filesystem.
@@ -43,9 +46,9 @@
43 46 $error = false;
44 47 } elseif ( current_user_can( 'manage_options' ) && $this->critcss_check_filename( $_POST['critcssfile'] ) ) {
45 48 // Or check user permissios and filename.
46 49 // Set file path and obtain its content.
47 - $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
50 + $critcssfile = AO_CCSS_DIR . $_POST['critcssfile'];
48 51 if ( file_exists( $critcssfile ) ) {
49 52 $content = file_get_contents( $critcssfile );
50 53 $error = false;
51 54 }
@@ -85,19 +88,21 @@
85 88 // Set critical CSS content.
86 89 $critcsscontents = stripslashes( $_POST['critcsscontents'] );
87 90
88 91 // If there is content and it's valid, write the file.
89 - if ( $critcsscontents && autoptimizeCriticalCSSCore::ao_ccss_check_contents( $critcsscontents ) ) {
92 + if ( $critcsscontents && $this->criticalcss->check_contents( $critcsscontents ) ) {
90 93 // Set file path and status.
91 - $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
94 + $critcssfile = AO_CCSS_DIR . $_POST['critcssfile'];
92 95 $status = file_put_contents( $critcssfile, $critcsscontents, LOCK_EX );
93 96 // Or set as error.
94 97 } else {
95 - $error = true;
98 + $error = true;
99 + $critcssfile = 'CCSS content not acceptable.';
96 100 }
97 101 // Or just set an error.
98 102 } else {
99 - $error = true;
103 + $error = true;
104 + $critcssfile = 'Not allowed or problem with CCSS filename.';
100 105 }
101 106
102 107 // Prepare response.
103 108 if ( ! $status || $error ) {
@@ -106,10 +111,17 @@
106 111 } else {
107 112 $response['code'] = '200';
108 113 if ( $critcssfile ) {
109 114 $response['string'] = 'File ' . $critcssfile . ' saved.';
115 +
116 + if ( true === apply_filters( 'autoptimize_filter_ccss_ajax_do_actions', true ) ) {
117 + $rule_identifiers = $this->fetch_rule_from_ccssfile( $critcssfile );
118 + if ( ! empty( $rule_identifiers ) && is_array( $rule_identifiers ) ) {
119 + do_action( 'autoptimize_action_ccss_ajax_css_changed', $rule_identifiers[0], $critcssfile, $rule_identifiers[1] );
120 + }
121 + }
110 122 } else {
111 - $response['string'] = 'Empty content do not need to be saved.';
123 + $response['string'] = 'Empty content does not need to be saved.';
112 124 }
113 125 }
114 126
115 127 // Dispatch respose.
@@ -118,9 +130,8 @@
118 130 // Close ajax request.
119 131 wp_die();
120 132 }
121 133
122 -
123 134 public function critcss_rm_callback() {
124 135 // Ajax handler to delete a critical CSS from the filesystem
125 136 // Check referer.
126 137 check_ajax_referer( 'rm_critcss_nonce', 'critcss_rm_nonce' );
@@ -134,9 +145,9 @@
134 145 $error = false;
135 146 } elseif ( current_user_can( 'manage_options' ) && $this->critcss_check_filename( $_POST['critcssfile'] ) ) {
136 147 // Or check user permissios and filename
137 148 // Set file path and delete it.
138 - $critcssfile = AO_CCSS_DIR . strip_tags( $_POST['critcssfile'] );
149 + $critcssfile = AO_CCSS_DIR . $_POST['critcssfile'];
139 150 if ( file_exists( $critcssfile ) ) {
140 151 $status = unlink( $critcssfile );
141 152 $error = false;
142 153 }
@@ -149,8 +160,15 @@
149 160 } else {
150 161 $response['code'] = '200';
151 162 if ( $status ) {
152 163 $response['string'] = 'File ' . $critcssfile . ' removed.';
164 +
165 + if ( true === apply_filters( 'autoptimize_filter_ccss_ajax_do_actions', true ) ) {
166 + $rule_identifiers = $this->fetch_rule_from_ccssfile( $critcssfile );
167 + if ( ! empty( $rule_identifiers ) && is_array( $rule_identifiers ) ) {
168 + do_action( 'autoptimize_action_ccss_ajax_css_removed', $rule_identifiers[0], $critcssfile, $rule_identifiers[1] );
169 + }
170 + }
153 171 } else {
154 172 $response['string'] = 'No file to be removed.';
155 173 }
156 174 }
@@ -176,8 +194,12 @@
176 194 if ( file_exists( AO_CCSS_DIR ) && is_dir( AO_CCSS_DIR ) ) {
177 195 array_map( 'unlink', glob( AO_CCSS_DIR . 'ccss_*.css', GLOB_BRACE ) );
178 196 $error = false;
179 197 $status = true;
198 +
199 + if ( true === apply_filters( 'autoptimize_filter_ccss_ajax_do_actions', true ) ) {
200 + do_action( 'autoptimize_action_ccss_ajax_all_css_removed' );
201 + }
180 202 }
181 203 }
182 204
183 205 // Prepare response.
@@ -212,18 +234,67 @@
212 234 wp_die();
213 235 }
214 236
215 237 // Init array, get options and prepare the raw object.
216 - $settings = array();
217 - $settings['rules'] = get_option( 'autoptimize_ccss_rules' );
218 - $settings['additional'] = get_option( 'autoptimize_ccss_additional' );
219 - $settings['viewport'] = get_option( 'autoptimize_ccss_viewport' );
220 - $settings['finclude'] = get_option( 'autoptimize_ccss_finclude' );
221 - $settings['rlimit'] = get_option( 'autoptimize_ccss_rlimit' );
222 - $settings['noptimize'] = get_option( 'autoptimize_ccss_noptimize' );
223 - $settings['debug'] = get_option( 'autoptimize_ccss_debug' );
224 - $settings['key'] = get_option( 'autoptimize_ccss_key' );
238 + $settings = array();
225 239
240 + // CCSS settings.
241 + $settings['ccss']['rules'] = get_option( 'autoptimize_ccss_rules' );
242 + $settings['ccss']['additional'] = get_option( 'autoptimize_ccss_additional' );
243 + $settings['ccss']['viewport'] = get_option( 'autoptimize_ccss_viewport' );
244 + $settings['ccss']['finclude'] = get_option( 'autoptimize_ccss_finclude' );
245 + $settings['ccss']['rtimelimit'] = get_option( 'autoptimize_ccss_rtimelimit' );
246 + $settings['ccss']['noptimize'] = get_option( 'autoptimize_ccss_noptimize' );
247 + $settings['ccss']['debug'] = get_option( 'autoptimize_ccss_debug' );
248 + $settings['ccss']['key'] = get_option( 'autoptimize_ccss_key' );
249 + $settings['ccss']['deferjquery'] = get_option( 'autoptimize_ccss_deferjquery' );
250 + $settings['ccss']['domain'] = get_option( 'autoptimize_ccss_domain' );
251 + $settings['ccss']['forcepath'] = get_option( 'autoptimize_ccss_forcepath' );
252 + $settings['ccss']['loggedin'] = get_option( 'autoptimize_ccss_loggedin' );
253 + $settings['ccss']['rlimit'] = get_option( 'autoptimize_ccss_rlimit' );
254 + $settings['ccss']['unloadccss'] = get_option( 'autoptimize_ccss_unloadccss' );
255 +
256 + // JS settings.
257 + $settings['js']['root'] = get_option( 'autoptimize_js' );
258 + $settings['js']['aggregate'] = get_option( 'autoptimize_js_aggregate' );
259 + $settings['js']['defer_not_aggregate'] = get_option( 'autoptimize_js_defer_not_aggregate' );
260 + $settings['js']['defer_inline'] = get_option( 'autoptimize_js_defer_inline' );
261 + $settings['js']['exclude'] = get_option( 'autoptimize_js_exclude' );
262 + $settings['js']['forcehead'] = get_option( 'autoptimize_js_forcehead' );
263 + $settings['js']['justhead'] = get_option( 'autoptimize_js_justhead' );
264 + $settings['js']['trycatch'] = get_option( 'autoptimize_js_trycatch' );
265 + $settings['js']['include_inline'] = get_option( 'autoptimize_js_include_inline' );
266 +
267 + // CSS settings.
268 + $settings['css']['root'] = get_option( 'autoptimize_css' );
269 + $settings['css']['aggregate'] = get_option( 'autoptimize_css_aggregate' );
270 + $settings['css']['datauris'] = get_option( 'autoptimize_css_datauris' );
271 + $settings['css']['justhead'] = get_option( 'autoptimize_css_justhead' );
272 + $settings['css']['defer'] = get_option( 'autoptimize_css_defer' );
273 + $settings['css']['defer_inline'] = get_option( 'autoptimize_css_defer_inline' );
274 + $settings['css']['inline'] = get_option( 'autoptimize_css_inline' );
275 + $settings['css']['exclude'] = get_option( 'autoptimize_css_exclude' );
276 + $settings['css']['include_inline'] = get_option( 'autoptimize_css_include_inline' );
277 +
278 + // Others.
279 + $settings['other']['autoptimize_imgopt_settings'] = get_option( 'autoptimize_imgopt_settings' );
280 + $settings['other']['autoptimize_extra_settings'] = get_option( 'autoptimize_extra_settings' );
281 + $settings['other']['autoptimize_cache_fallback'] = get_option( 'autoptimize_cache_fallback' );
282 + $settings['other']['autoptimize_cache_nogzip'] = get_option( 'autoptimize_cache_nogzip' );
283 + $settings['other']['autoptimize_cdn_url'] = get_option( 'autoptimize_cdn_url' );
284 + $settings['other']['autoptimize_enable_meta_ao_settings'] = get_option( 'autoptimize_enable_meta_ao_settings' );
285 + $settings['other']['autoptimize_enable_site_config'] = get_option( 'autoptimize_enable_site_config' );
286 + $settings['other']['autoptimize_html'] = get_option( 'autoptimize_html' );
287 + $settings['other']['autoptimize_html_keepcomments'] = get_option( 'autoptimize_html_keepcomments' );
288 + $settings['other']['autoptimize_minify_excluded'] = get_option( 'autoptimize_minify_excluded' );
289 + $settings['other']['autoptimize_optimize_checkout'] = get_option( 'autoptimize_optimize_checkout' );
290 + $settings['other']['autoptimize_optimize_logged'] = get_option( 'autoptimize_optimize_logged' );
291 +
292 + if ( defined( 'AO_PRO_VERSION' ) ) {
293 + $settings['pro']['boosters'] = get_option( 'autoptimize_pro_boosters' );
294 + $settings['pro']['pagecache'] = get_option( 'autoptimize_pro_pagecache' );
295 + }
296 +
226 297 // Initialize error flag.
227 298 $error = true;
228 299
229 300 // Check user permissions.
@@ -235,9 +306,9 @@
235 306 $error = false;
236 307 }
237 308
238 309 // Prepare archive.
239 - $zipfile = AO_CCSS_DIR . date( 'Ymd-H\hi' ) . '_ao_ccss_settings.zip';
310 + $zipfile = AO_CCSS_DIR . str_replace( array( '.', '/' ), '_', parse_url( AUTOPTIMIZE_WP_SITE_URL, PHP_URL_HOST ) ) . '_' . date( 'Ymd-H\hi' ) . '_ao_ccss_settings.zip'; // @codingStandardsIgnoreLine
240 311 $file = pathinfo( $zipfile, PATHINFO_BASENAME );
241 312 $zip = new ZipArchive();
242 313 $ret = $zip->open( $zipfile, ZipArchive::CREATE );
243 314 if ( true !== $ret ) {
@@ -254,8 +325,13 @@
254 325 $zip->addGlob( AO_CCSS_DIR . '*.css', 0, $options );
255 326 $zip->close();
256 327 }
257 328
329 + // settings.json has been added to zipfile, so can be removed now.
330 + if ( file_exists( $exportfile ) ) {
331 + unlink( $exportfile );
332 + }
333 +
258 334 // Prepare response.
259 335 if ( ! $status || $error ) {
260 336 $response['code'] = '500';
261 337 $response['msg'] = 'Error saving file ' . $file . ', code: ' . $ret;
@@ -280,34 +356,38 @@
280 356 // Initialize error flag.
281 357 $error = false;
282 358
283 359 // Process an uploaded file with no errors.
284 - if ( current_user_can( 'manage_options' ) && ! $_FILES['file']['error'] && strpos( $_FILES['file']['name'], '.zip' ) === strlen( $_FILES['file']['name'] ) - 4 ) {
285 - // Save file to the cache directory.
286 - $zipfile = AO_CCSS_DIR . $_FILES['file']['name'];
360 + if ( current_user_can( 'manage_options' ) && ! $_FILES['file']['error'] && $_FILES['file']['size'] < 500001 && strpos( $_FILES['file']['name'], '.zip' ) === strlen( $_FILES['file']['name'] ) - 4 ) {
361 + // create tmp dir with hard guess name in AO_CCSS_DIR.
362 + $_secret_dir = wp_hash( uniqid( md5( AUTOPTIMIZE_CACHE_URL ), true ) );
363 + $_import_tmp_dir = trailingslashit( AO_CCSS_DIR . $_secret_dir );
364 + mkdir( $_import_tmp_dir, 0774, true );
365 +
366 + // Save file to that tmp directory but give it our own name to prevent directory traversal risks when using original name.
367 + $zipfile = $_import_tmp_dir . uniqid( 'import_settings-', true ) . '.zip';
287 368 move_uploaded_file( $_FILES['file']['tmp_name'], $zipfile );
288 369
289 - // Extract archive.
370 + // Extract archive in the tmp directory.
290 371 $zip = new ZipArchive;
291 372 if ( $zip->open( $zipfile ) === true ) {
292 - $zip->extractTo( AO_CCSS_DIR );
373 + // loop through all files in the zipfile.
374 + for ( $i = 0; $i < $zip->numFiles; $i++ ) { // @codingStandardsIgnoreLine
375 + // but only extract known good files.
376 + if ( preg_match( '/^settings\.json$|^\.\/ccss_[a-z0-9]{32}\.css$/', $zip->getNameIndex( $i ) ) > 0 ) {
377 + $zip->extractTo( AO_CCSS_DIR, $zip->getNameIndex( $i ) );
378 + }
379 + }
293 380 $zip->close();
294 381 } else {
295 382 $error = 'could not extract';
296 383 }
297 384
385 + // and remove temp. dir with all contents (the import-zipfile).
386 + $this->rrmdir( $_import_tmp_dir );
387 +
298 388 if ( ! $error ) {
299 - // only known files allowed, all others are deleted.
300 - $_dir_contents_ccss = glob( AO_CCSS_DIR . 'ccss_*.css' );
301 - $_dir_known_ok = array( AO_CCSS_DIR . 'queue.lock', AO_CCSS_DIR . 'queuelog.html', AO_CCSS_DIR . 'index.html', AO_CCSS_DIR . 'settings.json' );
302 - $_dir_contents_ok = array_merge( $_dir_contents_ccss, $_dir_known_ok );
303 - $_dir_contents_all = glob( AO_CCSS_DIR . '*' );
304 - $_dir_to_be_deleted = array_diff( $_dir_contents_all, $_dir_contents_ok );
305 - foreach ( $_dir_to_be_deleted as $_file_to_be_deleted ) {
306 - unlink( $_file_to_be_deleted );
307 - }
308 -
309 - // Archive extraction ok, continue settings importing
389 + // Archive extraction ok, continue importing settings from AO_CCSS_DIR.
310 390 // Settings file.
311 391 $importfile = AO_CCSS_DIR . 'settings.json';
312 392
313 393 if ( file_exists( $importfile ) ) {
@@ -313,17 +393,59 @@
313 393 if ( file_exists( $importfile ) ) {
314 394 // Get settings and turn them into an object.
315 395 $settings = json_decode( file_get_contents( $importfile ), true );
316 396
317 - // Update options.
318 - update_option( 'autoptimize_ccss_rules', $settings['rules'] );
319 - update_option( 'autoptimize_ccss_additional', $settings['additional'] );
320 - update_option( 'autoptimize_ccss_viewport', $settings['viewport'] );
321 - update_option( 'autoptimize_ccss_finclude', $settings['finclude'] );
322 - update_option( 'autoptimize_ccss_rlimit', $settings['rlimit'] );
323 - update_option( 'autoptimize_ccss_noptimize', $settings['noptimize'] );
324 - update_option( 'autoptimize_ccss_debug', $settings['debug'] );
325 - update_option( 'autoptimize_ccss_key', $settings['key'] );
397 + // Update options from settings, but only for known options.
398 + // CCSS.
399 + foreach ( array( 'rules', 'additional', 'viewport', 'finclude', 'rtimelimit', 'noptimize', 'debug', 'key', 'deferjquery', 'domain', 'forcepath', 'loggedin', 'rlimit', 'unloadccss' ) as $ccss_setting ) {
400 + if ( false === array_key_exists( 'ccss', $settings ) || false === array_key_exists( $ccss_setting, $settings['ccss'] ) ) {
401 + continue;
402 + } else {
403 + update_option( 'autoptimize_ccss_' . $ccss_setting, autoptimizeUtils::strip_tags_array( $settings['ccss'][ $ccss_setting ] ) );
404 + }
405 + }
406 +
407 + // JS.
408 + foreach ( array( 'root', 'aggregate', 'defer_not_aggregate', 'defer_inline', 'exclude', 'forcehead', 'trycatch', 'include_inline' ) as $js_setting ) {
409 + if ( false === array_key_exists( 'js', $settings ) || false === array_key_exists( $js_setting, $settings['js'] ) ) {
410 + continue;
411 + } else if ( 'root' === $js_setting ) {
412 + update_option( 'autoptimize_js', $settings['js']['root'] );
413 + } else {
414 + update_option( 'autoptimize_js_' . $js_setting, $settings['js'][ $js_setting ] );
415 + }
416 + }
417 +
418 + // CSS.
419 + foreach ( array( 'root', 'aggregate', 'datauris', 'justhead', 'defer', 'defer_inline', 'inline', 'exclude', 'include_inline' ) as $css_setting ) {
420 + if ( false === array_key_exists( 'css', $settings ) || false === array_key_exists( $css_setting, $settings['css'] ) ) {
421 + continue;
422 + } else if ( 'root' === $css_setting ) {
423 + update_option( 'autoptimize_css', $settings['css']['root'] );
424 + } else {
425 + update_option( 'autoptimize_css_' . $css_setting, $settings['css'][ $css_setting ] );
426 + }
427 + }
428 +
429 + // Other.
430 + foreach ( array( 'autoptimize_imgopt_settings', 'autoptimize_extra_settings', 'autoptimize_cache_fallback', 'autoptimize_cache_nogzip', 'autoptimize_cdn_url', 'autoptimize_enable_meta_ao_settings', 'autoptimize_enable_site_config', 'autoptimize_html', 'autoptimize_html_keepcomments', 'autoptimize_minify_excluded', 'autoptimize_optimize_checkout', 'autoptimize_optimize_logged' ) as $other_setting ) {
431 + if ( false === array_key_exists( 'other', $settings ) || false === array_key_exists( $other_setting, $settings['other'] ) ) {
432 + continue;
433 + } else {
434 + update_option( $other_setting, $settings['other'][ $other_setting ] );
435 + }
436 + }
437 +
438 + // AO Pro.
439 + if ( defined( 'AO_PRO_VERSION' ) && array_key_exists( 'pro', $settings ) ) {
440 + update_option( 'autoptimize_pro_boosters', $settings['pro']['boosters'] );
441 + update_option( 'autoptimize_pro_pagecache', $settings['pro']['pagecache'] );
442 + }
443 +
444 + // settings.json has been imported, so can be removed now.
445 + if ( file_exists( $importfile ) ) {
446 + unlink( $importfile );
447 + }
326 448 } else {
327 449 // Settings file doesn't exist, update error flag.
328 450 $error = 'settings file does not exist';
329 451 }
@@ -347,8 +469,84 @@
347 469 // Close ajax request.
348 470 wp_die();
349 471 }
350 472
473 + public function ao_ccss_queuerunner_callback() {
474 + check_ajax_referer( 'ao_ccss_queuerunner_nonce', 'ao_ccss_queuerunner_nonce' );
475 +
476 + // Process an uploaded file with no errors.
477 + if ( current_user_can( 'manage_options' ) ) {
478 + if ( ! file_exists( AO_CCSS_LOCK ) ) {
479 + $ccss_cron = new autoptimizeCriticalCSSCron();
480 + $ccss_cron->ao_ccss_queue_control();
481 + $response['code'] = '200';
482 + $response['msg'] = 'Queue processing done';
483 + } else {
484 + $response['code'] = '302';
485 + $response['msg'] = 'Lock file found';
486 + }
487 + } else {
488 + $response['code'] = '500';
489 + $response['msg'] = 'Not allowed';
490 + }
491 +
492 + // Dispatch respose.
493 + echo json_encode( $response );
494 +
495 + // Close ajax request.
496 + wp_die();
497 + }
498 +
499 + public function ao_ccss_saverules_callback() {
500 + check_ajax_referer( 'ao_ccss_saverules_nonce', 'ao_ccss_saverules_nonce' );
501 +
502 + // save rules over AJAX, too many users forget to press "save changes".
503 + if ( current_user_can( 'manage_options' ) ) {
504 + if ( array_key_exists( 'critcssrules', $_POST ) ) {
505 + $rules = stripslashes( $_POST['critcssrules'] ); // ugly, but seems correct as per https://developer.wordpress.org/reference/functions/stripslashes_deep/#comment-1045 .
506 + if ( ! empty( $rules ) ) {
507 + $_unsafe_rules_array = json_decode( wp_strip_all_tags( $rules ), true );
508 + if ( ! empty( $_unsafe_rules_array ) && is_array( $_unsafe_rules_array ) ) {
509 + $_safe_rules_array = array();
510 + if ( array_key_exists( 'paths', $_unsafe_rules_array ) ) {
511 + $_safe_rules_array['paths'] = $_unsafe_rules_array['paths'];
512 + }
513 + if ( array_key_exists( 'types', $_unsafe_rules_array ) ) {
514 + $_safe_rules_array['types'] = $_unsafe_rules_array['types'];
515 + }
516 + $_safe_rules = json_encode( $_safe_rules_array, JSON_FORCE_OBJECT );
517 + if ( ! empty( $_safe_rules ) ) {
518 + update_option( 'autoptimize_ccss_rules', $_safe_rules );
519 + $response['code'] = '200';
520 + $response['msg'] = 'Rules saved';
521 + } else {
522 + $_error = 'Could not auto-save rules (safe rules empty)';
523 + }
524 + } else {
525 + $_error = 'Could not auto-save rules (rules could not be json_decoded)';
526 + }
527 + } else {
528 + $_error = 'Could not auto-save rules (rules empty)';
529 + }
530 + } else {
531 + $_error = 'Could not auto-save rules (rules not in $_POST)';
532 + }
533 + } else {
534 + $_error = 'Not allowed';
535 + }
536 +
537 + if ( ! isset( $response ) && $_error ) {
538 + $response['code'] = '500';
539 + $response['msg'] = $_error;
540 + }
541 +
542 + // Dispatch respose.
543 + echo json_encode( $response );
544 +
545 + // Close ajax request.
546 + wp_die();
547 + }
548 +
351 549 public function critcss_check_filename( $filename ) {
352 550 // Try to avoid directory traversal when reading/writing/deleting critical CSS files.
353 551 if ( strpos( $filename, 'ccss_' ) !== 0 ) {
354 552 return false;
@@ -359,6 +557,41 @@
359 557 return false;
360 558 } else {
361 559 return true;
362 560 }
561 + }
562 +
563 + public function rrmdir( $path ) {
564 + // recursively remove a directory as found on
565 + // https://andy-carter.com/blog/recursively-remove-a-directory-in-php.
566 + $files = glob( $path . '/*' );
567 + foreach ( $files as $file ) {
568 + is_dir( $file ) ? $this->rrmdir( $file ) : unlink( $file );
569 + }
570 + rmdir( $path );
571 +
572 + return;
573 + }
574 +
575 + public function fetch_rule_from_ccssfile( $ccss_file = '' ) {
576 + if ( empty( $ccss_file ) ) {
577 + return false;
578 + }
579 +
580 + $ccss_file = str_replace( AO_CCSS_DIR, '', $ccss_file );
581 +
582 + static $rules = null;
583 + if ( null === $rules ) {
584 + $rules = $this->criticalcss->get_option( 'rules' );
585 + }
586 +
587 + foreach ( $rules as $ruletype => $rulechilds ) {
588 + foreach ( $rulechilds as $identifier => $properties ) {
589 + if ( $properties['file'] === $ccss_file ) {
590 + return array( $ruletype, $identifier );
591 + }
592 + }
593 + }
594 +
595 + return false;
363 596 }
364 597 }