futtta /
autoptimize
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Critical CSS job enqueue logic. |
||
| 4 | */ |
||
| 5 | |||
| 6 | if ( ! defined( 'ABSPATH' ) ) { |
||
| 7 | exit; |
||
| 8 | } |
||
| 9 | |||
| 10 | class autoptimizeCriticalCSSEnqueue { |
||
| 11 | public function __construct() |
||
| 12 | { |
||
| 13 | // fetch all options at once and populate them individually explicitely as globals. |
||
| 14 | $all_options = autoptimizeCriticalCSSBase::fetch_options(); |
||
|
0 ignored issues
–
show
|
|||
| 15 | foreach ( $all_options as $_option => $_value ) { |
||
| 16 | global ${$_option}; |
||
| 17 | ${$_option} = $_value; |
||
| 18 | } |
||
| 19 | } |
||
| 20 | |||
| 21 | public static function ao_ccss_enqueue( $hash ) { |
||
| 22 | $self = new self(); |
||
| 23 | // Get key status. |
||
| 24 | $key = autoptimizeCriticalCSSCore::ao_ccss_key_status( false ); |
||
| 25 | |||
| 26 | // Queue is available to anyone... |
||
| 27 | $enqueue = true; |
||
| 28 | |||
| 29 | // ... which are not the ones below. |
||
| 30 | if ( is_user_logged_in() || is_feed() || is_404() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || $self->ao_ccss_ua() || 'nokey' == $key['status'] || 'invalid' == $key['status'] || false === apply_filters( 'autoptimize_filter_ccss_enqueue_should_enqueue', true ) ) { |
||
| 31 | $enqueue = false; |
||
| 32 | autoptimizeCriticalCSSCore::ao_ccss_log( "Job queuing is not available for WordPress's logged in users, feeds, error pages, ajax calls, to criticalcss.com itself or when a valid API key is not found", 3 ); |
||
| 33 | } |
||
| 34 | |||
| 35 | if ( $enqueue ) { |
||
| 36 | // Continue if queue is available |
||
| 37 | // Attach required arrays/ vars. |
||
| 38 | global $ao_ccss_rules; |
||
| 39 | global $ao_ccss_queue_raw; |
||
| 40 | global $ao_ccss_queue; |
||
| 41 | global $ao_ccss_forcepath; |
||
| 42 | |||
| 43 | // Get request path and page type, and initialize the queue update flag. |
||
| 44 | $req_orig = $_SERVER['REQUEST_URI']; |
||
| 45 | $req_path = strtok( $req_orig, '?' ); |
||
| 46 | |||
| 47 | // Check if we have a lang param. we need to keep as WPML can switch languages based on that |
||
| 48 | // and that includes RTL -> LTR so diff. structure, so rules would be RTL vs LTR |
||
| 49 | // but this needs changes in the structur of the rule object so off by default for now |
||
| 50 | // as now this will simply result in conditional rules being overwritten. |
||
| 51 | if ( apply_filters( 'autoptimize_filter_ccss_coreenqueue_honor_lang', false ) && strpos( $req_orig, 'lang=' ) !== false ) { |
||
| 52 | $req_params = strtok( '?' ); |
||
| 53 | parse_str( $req_params, $req_params_arr ); |
||
| 54 | if ( array_key_exists( 'lang', $req_params_arr ) && !empty( $req_params_arr['lang'] ) ) { |
||
| 55 | $req_path .= '?lang=' . $req_params_arr['lang']; |
||
| 56 | } |
||
| 57 | } |
||
| 58 | |||
| 59 | $req_type = $self->ao_ccss_get_type(); |
||
| 60 | $job_qualify = false; |
||
| 61 | $target_rule = false; |
||
| 62 | $rule_properties = false; |
||
| 63 | $queue_update = false; |
||
| 64 | |||
| 65 | // Match for paths in rules. |
||
| 66 | foreach ( $ao_ccss_rules['paths'] as $path => $props ) { |
||
| 67 | |||
| 68 | // Prepare rule target and log. |
||
| 69 | $target_rule = 'paths|' . $path; |
||
| 70 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Qualifying path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 ); |
||
| 71 | |||
| 72 | // Path match |
||
| 73 | // -> exact match needed for AUTO rules |
||
| 74 | // -> partial match OK for MANUAL rules (which have empty hash and a file with CCSS). |
||
| 75 | if ( $path === $req_path || ( false == $props['hash'] && false != $props['file'] && preg_match( '|' . $path . '|', $req_path ) ) ) { |
||
| 76 | |||
| 77 | // There's a path match in the rule, so job QUALIFIES with a path rule match. |
||
| 78 | $job_qualify = true; |
||
| 79 | $rule_properties = $props; |
||
| 80 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 ); |
||
| 81 | |||
| 82 | // Stop processing other path rules. |
||
| 83 | break; |
||
| 84 | } |
||
| 85 | } |
||
| 86 | |||
| 87 | // Match for types in rules if no path rule matches and if we're not enforcing paths. |
||
| 88 | if ( ! $job_qualify && ( ! $ao_ccss_forcepath || ! in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) || ! apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) ) ) { |
||
| 89 | foreach ( $ao_ccss_rules['types'] as $type => $props ) { |
||
| 90 | |||
| 91 | // Prepare rule target and log. |
||
| 92 | $target_rule = 'types|' . $type; |
||
| 93 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Qualifying page type <' . $req_type . '> on path <' . $req_path . '> for job submission by rule <' . $target_rule . '>', 3 ); |
||
| 94 | |||
| 95 | if ( $req_type == $type ) { |
||
| 96 | // Type match. |
||
| 97 | // There's a type match in the rule, so job QUALIFIES with a type rule match. |
||
| 98 | $job_qualify = true; |
||
| 99 | $rule_properties = $props; |
||
| 100 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Page type <' . $req_type . '> on path <' . $req_path . '> QUALIFIED for job submission by rule <' . $target_rule . '>', 3 ); |
||
| 101 | |||
| 102 | // Stop processing other type rules. |
||
| 103 | break; |
||
| 104 | } |
||
| 105 | } |
||
| 106 | } |
||
| 107 | |||
| 108 | if ( $job_qualify && ( ( false == $rule_properties['hash'] && false != $rule_properties['file'] ) || strpos( $req_type, 'template_' ) !== false ) ) { |
||
| 109 | // If job qualifies but rule hash is false and file isn't false (MANUAL rule) or if template, job does not qualify despite what previous evaluations says. |
||
| 110 | $job_qualify = false; |
||
| 111 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission DISQUALIFIED by MANUAL rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 ); |
||
| 112 | } elseif ( ! $job_qualify && empty( $rule_properties ) ) { |
||
| 113 | // But if job does not qualify and rule properties are set, job qualifies as there is no matching rule for it yet |
||
| 114 | // Fill-in the new target rule. |
||
| 115 | $job_qualify = true; |
||
| 116 | |||
| 117 | // Should we switch to path-base AUTO-rules? Conditions: |
||
| 118 | // 1. forcepath option has to be enabled (off by default) |
||
| 119 | // 2. request type should be (by default, but filterable) one of is_page (removed for now: woo_is_product or woo_is_product_category). |
||
| 120 | if ( ( $ao_ccss_forcepath && in_array( $req_type, apply_filters( 'autoptimize_filter_ccss_coreenqueue_forcepathfortype', array( 'is_page' ) ) ) ) || apply_filters( 'autoptimize_filter_ccss_coreenqueue_ignorealltypes', false ) ) { |
||
| 121 | if ( '/' !== $req_path ) { |
||
| 122 | $target_rule = 'paths|' . $req_path; |
||
| 123 | } else { |
||
| 124 | // Exception; we don't want a path-based rule for "/" as that messes things up, hard-switch this to a type-based is_front_page rule. |
||
| 125 | $target_rule = 'types|' . 'is_front_page'; |
||
| 126 | } |
||
| 127 | } else { |
||
| 128 | $target_rule = 'types|' . $req_type; |
||
| 129 | } |
||
| 130 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by MISSING rule for page type <' . $req_type . '> on path <' . $req_path . '>, new rule target is <' . $target_rule . '>', 3 ); |
||
| 131 | } else { |
||
| 132 | // Or just log a job qualified by a matching rule. |
||
| 133 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Job submission QUALIFIED by AUTO rule <' . $target_rule . '> with hash <' . $rule_properties['hash'] . '> and file <' . $rule_properties['file'] . '>', 3 ); |
||
| 134 | } |
||
| 135 | |||
| 136 | // Submit job. |
||
| 137 | if ( $job_qualify ) { |
||
| 138 | if ( ! array_key_exists( $req_path, $ao_ccss_queue ) ) { |
||
| 139 | // This is a NEW job |
||
| 140 | // Merge job into the queue. |
||
| 141 | $ao_ccss_queue[ $req_path ] = $self->ao_ccss_define_job( |
||
| 142 | $req_path, |
||
| 143 | $target_rule, |
||
| 144 | $req_type, |
||
| 145 | $hash, |
||
| 146 | null, |
||
| 147 | null, |
||
| 148 | null, |
||
| 149 | null, |
||
| 150 | true |
||
| 151 | ); |
||
| 152 | // Set update flag. |
||
| 153 | $queue_update = true; |
||
| 154 | } else { |
||
| 155 | // This is an existing job |
||
| 156 | // The job is still NEW, most likely this is extra CSS file for the same page that needs a hash. |
||
| 157 | if ( 'NEW' == $ao_ccss_queue[ $req_path ]['jqstat'] ) { |
||
| 158 | // Add hash if it's not already in the job. |
||
| 159 | if ( ! in_array( $hash, $ao_ccss_queue[ $req_path ]['hashes'] ) ) { |
||
| 160 | // Push new hash to its array and update flag. |
||
| 161 | $queue_update = array_push( $ao_ccss_queue[ $req_path ]['hashes'], $hash ); |
||
| 162 | |||
| 163 | // Log job update. |
||
| 164 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Hashes UPDATED on local job id <' . $ao_ccss_queue[ $req_path ]['ljid'] . '>, job status NEW, target rule <' . $ao_ccss_queue[ $req_path ]['rtarget'] . '>, hash added: ' . $hash, 3 ); |
||
| 165 | |||
| 166 | // Return from here as the hash array is already updated. |
||
| 167 | return true; |
||
| 168 | } |
||
| 169 | } elseif ( 'NEW' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_QUEUED' != $ao_ccss_queue[ $req_path ]['jqstat'] && 'JOB_ONGOING' != $ao_ccss_queue[ $req_path ]['jqstat'] ) { |
||
| 170 | // Allow requeuing jobs that are not NEW, JOB_QUEUED or JOB_ONGOING |
||
| 171 | // Merge new job keeping some previous job values. |
||
| 172 | $ao_ccss_queue[ $req_path ] = $self->ao_ccss_define_job( |
||
| 173 | $req_path, |
||
| 174 | $target_rule, |
||
| 175 | $req_type, |
||
| 176 | $hash, |
||
| 177 | $ao_ccss_queue[ $req_path ]['file'], |
||
| 178 | $ao_ccss_queue[ $req_path ]['jid'], |
||
| 179 | $ao_ccss_queue[ $req_path ]['jrstat'], |
||
| 180 | $ao_ccss_queue[ $req_path ]['jvstat'], |
||
| 181 | false |
||
| 182 | ); |
||
| 183 | // Set update flag. |
||
| 184 | $queue_update = true; |
||
| 185 | } |
||
| 186 | } |
||
| 187 | |||
| 188 | if ( $queue_update ) { |
||
| 189 | // Persist the job to the queue and return. |
||
| 190 | $ao_ccss_queue_raw = json_encode( $ao_ccss_queue ); |
||
| 191 | update_option( 'autoptimize_ccss_queue', $ao_ccss_queue_raw, false ); |
||
| 192 | return true; |
||
| 193 | } else { |
||
| 194 | // Or just return false if no job was added. |
||
| 195 | autoptimizeCriticalCSSCore::ao_ccss_log( 'A job for path <' . $req_path . '> already exist with NEW or PENDING status, skipping job creation', 3 ); |
||
| 196 | return false; |
||
| 197 | } |
||
| 198 | } |
||
| 199 | } |
||
| 200 | } |
||
| 201 | |||
| 202 | public function ao_ccss_get_type() { |
||
| 203 | // Get the type of a page |
||
| 204 | // Attach the conditional tags array. |
||
| 205 | global $ao_ccss_types; |
||
| 206 | global $ao_ccss_forcepath; |
||
| 207 | |||
| 208 | // By default, a page type is false. |
||
| 209 | $page_type = false; |
||
| 210 | |||
| 211 | // Iterates over the array to match a type. |
||
| 212 | foreach ( $ao_ccss_types as $type ) { |
||
| 213 | if ( is_404() ) { |
||
| 214 | $page_type = 'is_404'; |
||
| 215 | break; |
||
| 216 | } elseif ( is_front_page() ) { |
||
| 217 | // identify frontpage immediately to avoid it also matching a CPT or template. |
||
| 218 | $page_type = 'is_front_page'; |
||
| 219 | break; |
||
| 220 | } elseif ( strpos( $type, 'custom_post_' ) !== false && ( ! $ao_ccss_forcepath || ! is_page() ) ) { |
||
| 221 | // Match custom post types and not page or page not forced to path-based. |
||
| 222 | if ( get_post_type( get_the_ID() ) === substr( $type, 12 ) ) { |
||
| 223 | $page_type = $type; |
||
| 224 | break; |
||
| 225 | } |
||
| 226 | } elseif ( strpos( $type, 'template_' ) !== false && ( ! $ao_ccss_forcepath || ! is_page() ) ) { |
||
| 227 | // Match templates if not page or if page is not forced to path-based. |
||
| 228 | if ( is_page_template( substr( $type, 9 ) ) ) { |
||
| 229 | $page_type = $type; |
||
| 230 | break; |
||
| 231 | } |
||
| 232 | } else { |
||
| 233 | // Match all other existing types |
||
| 234 | // but remove prefix to be able to check if the function exists & returns true. |
||
| 235 | $_type = str_replace( array( 'woo_', 'bp_', 'bbp_', 'edd_' ), '', $type ); |
||
| 236 | if ( function_exists( $_type ) && call_user_func( $_type ) ) { |
||
| 237 | // Make sure we only return for one page, not for the "paged pages" (/page/2 ..). |
||
| 238 | if ( ! is_page() || ! is_paged() ) { |
||
| 239 | $page_type = $type; |
||
| 240 | break; |
||
| 241 | } |
||
| 242 | } |
||
| 243 | } |
||
| 244 | } |
||
| 245 | |||
| 246 | // Return the page type. |
||
| 247 | return $page_type; |
||
| 248 | } |
||
| 249 | |||
| 250 | public function ao_ccss_define_job( $path, $target, $type, $hash, $file, $jid, $jrstat, $jvstat, $create ) { |
||
|
0 ignored issues
–
show
|
|||
| 251 | // Define a job entry to be created or updated |
||
| 252 | // Define commom job properties. |
||
| 253 | $path = array(); |
||
| 254 | $path['ljid'] = $this->ao_ccss_job_id(); |
||
| 255 | $path['rtarget'] = $target; |
||
| 256 | $path['ptype'] = $type; |
||
| 257 | $path['hashes'] = array( $hash ); |
||
| 258 | $path['hash'] = $hash; |
||
| 259 | $path['file'] = $file; |
||
| 260 | $path['jid'] = $jid; |
||
| 261 | $path['jqstat'] = 'NEW'; |
||
| 262 | $path['jrstat'] = $jrstat; |
||
| 263 | $path['jvstat'] = $jvstat; |
||
| 264 | $path['jctime'] = microtime( true ); |
||
| 265 | $path['jftime'] = null; |
||
| 266 | |||
| 267 | // Set operation requested. |
||
| 268 | if ( $create ) { |
||
| 269 | $operation = 'CREATED'; |
||
| 270 | } else { |
||
| 271 | $operation = 'UPDATED'; |
||
| 272 | } |
||
| 273 | |||
| 274 | // Log job creation. |
||
| 275 | autoptimizeCriticalCSSCore::ao_ccss_log( 'Job ' . $operation . ' with local job id <' . $path['ljid'] . '> for target rule <' . $target . '>', 3 ); |
||
| 276 | |||
| 277 | return $path; |
||
| 278 | } |
||
| 279 | |||
| 280 | public function ao_ccss_job_id( $length = 6 ) { |
||
| 281 | // Generate random strings for the local job ID |
||
| 282 | // Based on https://stackoverflow.com/a/4356295 . |
||
| 283 | $characters = '0123456789abcdefghijklmnopqrstuvwxyz'; |
||
| 284 | $characters_length = strlen( $characters ); |
||
| 285 | $random_string = 'j-'; |
||
| 286 | for ( $i = 0; $i < $length; $i++ ) { |
||
| 287 | $random_string .= $characters[ rand( 0, $characters_length - 1 ) ]; |
||
| 288 | } |
||
| 289 | return $random_string; |
||
| 290 | } |
||
| 291 | |||
| 292 | public function ao_ccss_ua() { |
||
| 293 | // Check for criticalcss.com user agent. |
||
| 294 | $agent = ''; |
||
| 295 | if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { |
||
| 296 | $agent = $_SERVER['HTTP_USER_AGENT']; |
||
| 297 | } |
||
| 298 | |||
| 299 | // Check for UA and return TRUE when criticalcss.com is the detected UA, false when not. |
||
| 300 | $rtn = strpos( $agent, AO_CCSS_URL ); |
||
| 301 | if ( 0 === $rtn ) { |
||
| 302 | $rtn = true; |
||
| 303 | } else { |
||
| 304 | $rtn = false; |
||
| 305 | } |
||
| 306 | return ( $rtn ); |
||
| 307 | } |
||
| 308 | } |
||
| 309 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.