| 1 | <?php |
| 2 | |
| 3 | use Automattic\Jetpack_Boost\Lib\Minify; |
| 4 | use Automattic\Jetpack_Boost\Lib\Minify\Config; |
| 5 | use Automattic\Jetpack_Boost\Lib\Minify\Dependency_Path_Mapping; |
| 6 | use Automattic\Jetpack_Boost\Lib\Minify\File_Paths; |
| 7 | use Automattic\Jetpack_Boost\Lib\Minify\Utils; |
| 8 | |
| 9 | function jetpack_boost_page_optimize_types() { |
| 10 | return array( |
| 11 | 'css' => 'text/css', |
| 12 | 'js' => 'application/javascript', |
| 13 | ); |
| 14 | } |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | function jetpack_boost_page_optimize_limits() { |
| 22 | return array( |
| 23 | 'encoded_list' => 64 * 1024, |
| 24 | 'decoded_list' => 256 * 1024, |
| 25 | 'files_read' => 16 * 1024 * 1024, |
| 26 | 'output' => 16 * 1024 * 1024, |
| 27 | ); |
| 28 | } |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | function jetpack_boost_page_optimize_check_files_size( $uris ) { |
| 38 | $total_bytes = 0; |
| 39 | |
| 40 | foreach ( $uris as $uri ) { |
| 41 | $fullpath = jetpack_boost_page_optimize_get_path( $uri ); |
| 42 | |
| 43 | if ( ! in_array( jetpack_boost_page_optimize_get_mime_type( $fullpath ), jetpack_boost_page_optimize_types(), true ) ) { |
| 44 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 45 | } |
| 46 | |
| 47 | |
| 48 | $total_bytes += file_exists( $fullpath ) ? (int) filesize( $fullpath ) : 0; |
| 49 | } |
| 50 | |
| 51 | if ( $total_bytes > jetpack_boost_page_optimize_limits()['files_read'] ) { |
| 52 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | |
| 63 | function jetpack_boost_page_optimize_check_output_size( $size ) { |
| 64 | if ( $size > jetpack_boost_page_optimize_limits()['output'] ) { |
| 65 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | |
| 74 | function jetpack_boost_page_optimize_cache_max_bytes() { |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | return (int) apply_filters( 'jetpack_boost_minify_cache_max_bytes', 1024 * 1024 * 1024 ); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | |
| 89 | |
| 90 | |
| 91 | |
| 92 | |
| 93 | |
| 94 | |
| 95 | function jetpack_boost_page_optimize_cache_has_room( $pattern, $bytes ) { |
| 96 | $total_bytes = $bytes; |
| 97 | |
| 98 | foreach ( (array) glob( $pattern ) as $file ) { |
| 99 | $total_bytes += file_exists( (string) $file ) ? (int) filesize( $file ) : 0; |
| 100 | } |
| 101 | |
| 102 | return $total_bytes <= jetpack_boost_page_optimize_cache_max_bytes(); |
| 103 | } |
| 104 | |
| 105 | |
| 106 | |
| 107 | |
| 108 | |
| 109 | |
| 110 | |
| 111 | |
| 112 | |
| 113 | function jetpack_boost_page_optimize_write_cache_file( $path, $content ) { |
| 114 | |
| 115 | $temp_path = $path . '.' . uniqid( 'tmp-', true ); |
| 116 | |
| 117 | |
| 118 | if ( strlen( $content ) === file_put_contents( $temp_path, $content ) && rename( $temp_path, $path ) ) { |
| 119 | return true; |
| 120 | } |
| 121 | |
| 122 | if ( file_exists( $temp_path ) ) { |
| 123 | wp_delete_file( $temp_path ); |
| 124 | } |
| 125 | |
| 126 | return false; |
| 127 | } |
| 128 | |
| 129 | |
| 130 | |
| 131 | |
| 132 | |
| 133 | |
| 134 | |
| 135 | |
| 136 | function jetpack_boost_page_optimize_get_subdir_prefix( $request_uri ) { |
| 137 | $use_wp = defined( 'JETPACK_BOOST_CONCAT_USE_WP' ) && JETPACK_BOOST_CONCAT_USE_WP; |
| 138 | $request_path = ( new Utils( $use_wp ) )->parse_url( $request_uri, PHP_URL_PATH ); |
| 139 | $_static_index = strpos( $request_path, jetpack_boost_get_static_prefix() ); |
| 140 | |
| 141 | return $_static_index > 0 ? substr( $request_path, 0, $_static_index ) : ''; |
| 142 | } |
| 143 | |
| 144 | |
| 145 | |
| 146 | |
| 147 | |
| 148 | |
| 149 | |
| 150 | |
| 151 | |
| 152 | function jetpack_boost_page_optimize_get_cache_key( $list_id, $request_uri ) { |
| 153 | $use_wp = defined( 'JETPACK_BOOST_CONCAT_USE_WP' ) && JETPACK_BOOST_CONCAT_USE_WP; |
| 154 | $utils = new Utils( $use_wp ); |
| 155 | $prefix = jetpack_boost_page_optimize_get_subdir_prefix( $request_uri ); |
| 156 | |
| 157 | |
| 158 | $site_url = apply_filters( 'page_optimize_site_url', site_url() ); |
| 159 | |
| 160 | |
| 161 | |
| 162 | if ( '' !== $prefix && rtrim( (string) $utils->parse_url( $site_url, PHP_URL_PATH ), '/' ) !== $prefix ) { |
| 163 | return false; |
| 164 | } |
| 165 | |
| 166 | return md5( $prefix . '|' . $list_id ); |
| 167 | } |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | |
| 175 | |
| 176 | function jetpack_boost_page_optimize_get_request_cache_key( $request_uri ) { |
| 177 | $list = jetpack_boost_page_optimize_get_request_list( $request_uri ); |
| 178 | $list_id = File_Paths::is_id( $list ) ? $list : jetpack_boost_page_optimize_get_issued_list( $list )->get_cache_id(); |
| 179 | |
| 180 | return jetpack_boost_page_optimize_get_cache_key( $list_id, $request_uri ); |
| 181 | } |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | |
| 188 | function jetpack_boost_page_optimize_service_request() { |
| 189 | $use_wp = defined( 'JETPACK_BOOST_CONCAT_USE_WP' ) && JETPACK_BOOST_CONCAT_USE_WP; |
| 190 | $utils = new Utils( $use_wp ); |
| 191 | |
| 192 | |
| 193 | if ( ! defined( 'DONOTCACHEPAGE' ) ) { |
| 194 | define( 'DONOTCACHEPAGE', true ); |
| 195 | } |
| 196 | |
| 197 | |
| 198 | $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $utils->unslash( $_SERVER['REQUEST_URI'] ) : ''; |
| 199 | $cache_key = jetpack_boost_page_optimize_get_request_cache_key( $request_uri ); |
| 200 | |
| 201 | $use_cache = false !== $cache_key && Config::can_use_cache(); |
| 202 | $cache_file = ''; |
| 203 | $cache_file_meta = ''; |
| 204 | |
| 205 | if ( $use_cache ) { |
| 206 | $cache_dir = Config::get_legacy_cache_dir_path(); |
| 207 | $cache_file = $cache_dir . "/page-optimize-cache-$cache_key"; |
| 208 | $cache_file_meta = $cache_dir . "/page-optimize-cache-meta-$cache_key"; |
| 209 | |
| 210 | |
| 211 | $cached = jetpack_boost_page_optimize_read_cached_response( $cache_file, $cache_file_meta ); |
| 212 | if ( false !== $cached ) { |
| 213 | if ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { |
| 214 | |
| 215 | if ( strtotime( $utils->unslash( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) < filemtime( $cache_file ) ) { |
| 216 | header( 'HTTP/1.1 304 Not Modified' ); |
| 217 | exit( 0 ); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | foreach ( $cached['headers'] as $header ) { |
| 222 | header( $header ); |
| 223 | } |
| 224 | |
| 225 | $etag = '"' . md5( $cached['content'] ) . '"'; |
| 226 | |
| 227 | |
| 228 | if ( defined( 'ATOMIC_CLIENT_ID' ) ) { |
| 229 | header( 'A8c-Edge-Cache: cache' ); |
| 230 | } |
| 231 | header( 'X-Page-Optimize: cached' ); |
| 232 | header( 'Cache-Control: max-age=' . 31536000 ); |
| 233 | header( 'ETag: ' . $etag ); |
| 234 | |
| 235 | echo $cached['content']; |
| 236 | die( 0 ); |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | |
| 241 | $output = jetpack_boost_page_optimize_build_output(); |
| 242 | $content = $output['content']; |
| 243 | $headers = $output['headers']; |
| 244 | |
| 245 | foreach ( $headers as $header ) { |
| 246 | header( $header ); |
| 247 | } |
| 248 | |
| 249 | if ( defined( 'ATOMIC_CLIENT_ID' ) ) { |
| 250 | header( 'A8c-Edge-Cache: cache' ); |
| 251 | } |
| 252 | header( 'X-Page-Optimize: uncached' ); |
| 253 | header( 'Cache-Control: max-age=' . 31536000 ); |
| 254 | header( 'ETag: "' . md5( $content ) . '"' ); |
| 255 | |
| 256 | echo $content; |
| 257 | |
| 258 | |
| 259 | if ( $use_cache ) { |
| 260 | jetpack_boost_page_optimize_store_cached_response( $cache_file, $cache_file_meta, $output ); |
| 261 | } |
| 262 | |
| 263 | die( 0 ); |
| 264 | } |
| 265 | |
| 266 | |
| 267 | |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | |
| 273 | |
| 274 | function jetpack_boost_page_optimize_read_cached_response( $cache_file, $cache_file_meta ) { |
| 275 | if ( ! file_exists( $cache_file ) || ! file_exists( $cache_file_meta ) ) { |
| 276 | return false; |
| 277 | } |
| 278 | |
| 279 | |
| 280 | |
| 281 | $content = @file_get_contents( $cache_file ); |
| 282 | |
| 283 | $meta = json_decode( (string) @file_get_contents( $cache_file_meta ), true ); |
| 284 | |
| 285 | if ( false === $content || empty( $meta['headers'] ) ) { |
| 286 | return false; |
| 287 | } |
| 288 | |
| 289 | return array( |
| 290 | 'content' => $content, |
| 291 | 'headers' => $meta['headers'], |
| 292 | ); |
| 293 | } |
| 294 | |
| 295 | |
| 296 | |
| 297 | |
| 298 | |
| 299 | |
| 300 | |
| 301 | |
| 302 | |
| 303 | |
| 304 | function jetpack_boost_page_optimize_store_cached_response( $cache_file, $cache_file_meta, $output ) { |
| 305 | $meta = wp_json_encode( array( 'headers' => $output['headers'] ), JSON_UNESCAPED_SLASHES ); |
| 306 | |
| 307 | if ( ! jetpack_boost_page_optimize_cache_has_room( dirname( $cache_file ) . '/page-optimize-cache-*', strlen( $output['content'] ) + strlen( $meta ) ) ) { |
| 308 | return; |
| 309 | } |
| 310 | |
| 311 | |
| 312 | if ( jetpack_boost_page_optimize_write_cache_file( $cache_file_meta, $meta ) ) { |
| 313 | jetpack_boost_page_optimize_write_cache_file( $cache_file, $output['content'] ); |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | |
| 318 | |
| 319 | |
| 320 | function jetpack_boost_strip_parent_path( $parent_path, $path ) { |
| 321 | $trimmed_parent = ltrim( $parent_path, '/' ); |
| 322 | |
| 323 | $trimmed_path = ltrim( rtrim( preg_replace( '#/(?:\./|/)+#', '/', $path . '/' ), '/' ), '/' ); |
| 324 | |
| 325 | if ( substr( $trimmed_path, 0, strlen( $trimmed_parent ) ) === $trimmed_parent ) { |
| 326 | $trimmed_path = substr( $trimmed_path, strlen( $trimmed_parent ) ); |
| 327 | } |
| 328 | |
| 329 | return str_starts_with( $trimmed_path, '/' ) ? $trimmed_path : '/' . $trimmed_path; |
| 330 | } |
| 331 | |
| 332 | |
| 333 | |
| 334 | |
| 335 | |
| 336 | function jetpack_boost_page_optimize_build_output() { |
| 337 | $use_wp = defined( 'JETPACK_BOOST_CONCAT_USE_WP' ) && JETPACK_BOOST_CONCAT_USE_WP; |
| 338 | $utils = new Utils( $use_wp ); |
| 339 | |
| 340 | $jetpack_boost_page_optimize_types = jetpack_boost_page_optimize_types(); |
| 341 | |
| 342 | |
| 343 | $concat_max_files = jetpack_boost_minify_concat_max_files(); |
| 344 | $concat_unique = true; |
| 345 | |
| 346 | |
| 347 | |
| 348 | $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $utils->unslash( $_SERVER['REQUEST_URI'] ) : ''; |
| 349 | |
| 350 | $args = jetpack_boost_page_optimize_get_issued_list( jetpack_boost_page_optimize_get_request_list( $request_uri ) )->get_paths(); |
| 351 | |
| 352 | |
| 353 | if ( 0 === count( $args ) || count( $args ) > $concat_max_files ) { |
| 354 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 355 | } |
| 356 | |
| 357 | jetpack_boost_page_optimize_check_files_size( $args ); |
| 358 | |
| 359 | |
| 360 | |
| 361 | $subdir_path_prefix = jetpack_boost_page_optimize_get_subdir_prefix( $request_uri ); |
| 362 | |
| 363 | $last_modified = 0; |
| 364 | $pre_output = ''; |
| 365 | $output = ''; |
| 366 | $total_bytes = 0; |
| 367 | $limits = jetpack_boost_page_optimize_limits(); |
| 368 | |
| 369 | foreach ( $args as $uri ) { |
| 370 | $fullpath = jetpack_boost_page_optimize_get_path( $uri ); |
| 371 | |
| 372 | if ( ! file_exists( $fullpath ) ) { |
| 373 | jetpack_boost_page_optimize_status_exit( 404 ); |
| 374 | } |
| 375 | |
| 376 | $mime_type = jetpack_boost_page_optimize_get_mime_type( $fullpath ); |
| 377 | if ( ! in_array( $mime_type, $jetpack_boost_page_optimize_types, true ) ) { |
| 378 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 379 | } |
| 380 | |
| 381 | if ( $concat_unique ) { |
| 382 | if ( ! isset( $last_mime_type ) ) { |
| 383 | $last_mime_type = $mime_type; |
| 384 | } |
| 385 | |
| 386 | if ( $last_mime_type !== $mime_type ) { |
| 387 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | $stat = stat( $fullpath ); |
| 392 | if ( false === $stat ) { |
| 393 | jetpack_boost_page_optimize_status_exit( 500 ); |
| 394 | } |
| 395 | |
| 396 | if ( $stat['mtime'] > $last_modified ) { |
| 397 | $last_modified = $stat['mtime']; |
| 398 | } |
| 399 | |
| 400 | $total_bytes += $stat['size']; |
| 401 | if ( $total_bytes > $limits['files_read'] ) { |
| 402 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 403 | } |
| 404 | |
| 405 | |
| 406 | $buf = file_get_contents( $fullpath ); |
| 407 | if ( false === $buf ) { |
| 408 | jetpack_boost_page_optimize_status_exit( 500 ); |
| 409 | } |
| 410 | |
| 411 | if ( 'text/css' === $mime_type ) { |
| 412 | $dirpath = jetpack_boost_strip_parent_path( $subdir_path_prefix, dirname( $uri ) ); |
| 413 | |
| 414 | |
| 415 | $buf = jetpack_boost_page_optimize_relative_path_replace( $buf, $dirpath ); |
| 416 | |
| 417 | |
| 418 | |
| 419 | $buf = preg_replace( |
| 420 | '/(Microsoft.AlphaImageLoader\s*\([^\)]*src=(?:\'|")?)([^\/\'"\s\)](?:(?<!http:|https:).)*)\)/isU', |
| 421 | '$1' . ( $dirpath === '/' ? '/' : $dirpath . '/' ) . '$2)', |
| 422 | $buf |
| 423 | ); |
| 424 | |
| 425 | |
| 426 | if ( str_starts_with( $buf, '@charset' ) ) { |
| 427 | $buf = preg_replace_callback( |
| 428 | '/(?P<charset_rule>@charset\s+[\'"][^\'"]+[\'"];)/i', |
| 429 | function ( $match ) use ( &$pre_output ) { |
| 430 | if ( str_starts_with( $pre_output, '@charset' ) ) { |
| 431 | return ''; |
| 432 | } |
| 433 | |
| 434 | $pre_output = $match[0] . "\n" . $pre_output; |
| 435 | |
| 436 | return ''; |
| 437 | }, |
| 438 | $buf |
| 439 | ); |
| 440 | } |
| 441 | |
| 442 | |
| 443 | |
| 444 | if ( str_contains( $buf, '@import' ) ) { |
| 445 | $buf = preg_replace_callback( |
| 446 | '/(?P<pre_path>@import\s+(?:url\s*\()?[\'"\s]*)(?P<path>[^\'"\s](?:https?:\/\/.+\/?)?.+?)(?P<post_path>[\'"\s\)]*;)/i', |
| 447 | function ( $match ) use ( $dirpath, &$pre_output ) { |
| 448 | if ( ! str_starts_with( $match['path'], 'http' ) && '/' !== $match['path'][0] ) { |
| 449 | $pre_output .= $match['pre_path'] . ( $dirpath === '/' ? '/' : $dirpath . '/' ) . |
| 450 | $match['path'] . $match['post_path'] . "\n"; |
| 451 | } else { |
| 452 | $pre_output .= $match[0] . "\n"; |
| 453 | } |
| 454 | |
| 455 | return ''; |
| 456 | }, |
| 457 | $buf |
| 458 | ); |
| 459 | } |
| 460 | |
| 461 | |
| 462 | jetpack_boost_page_optimize_check_output_size( strlen( $pre_output ) + strlen( $output ) + strlen( $buf ) ); |
| 463 | |
| 464 | |
| 465 | if ( ! jetpack_boost_page_optimize_is_already_minified( $fullpath ) ) { |
| 466 | |
| 467 | $buf = Minify::css( $buf ); |
| 468 | } |
| 469 | $output .= "$buf"; |
| 470 | } else { |
| 471 | |
| 472 | if ( ! jetpack_boost_page_optimize_is_already_minified( $fullpath ) ) { |
| 473 | |
| 474 | $buf = Minify::js( $buf ); |
| 475 | } |
| 476 | |
| 477 | $output .= "$buf;\n"; |
| 478 | } |
| 479 | |
| 480 | jetpack_boost_page_optimize_check_output_size( strlen( $pre_output ) + strlen( $output ) ); |
| 481 | } |
| 482 | |
| 483 | |
| 484 | |
| 485 | $output = rtrim( $output ); |
| 486 | |
| 487 | $headers = array( |
| 488 | 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $last_modified ) . ' GMT', |
| 489 | "Content-Type: $mime_type", |
| 490 | ); |
| 491 | |
| 492 | return array( |
| 493 | 'headers' => $headers, |
| 494 | 'content' => $pre_output . $output, |
| 495 | ); |
| 496 | } |
| 497 | |
| 498 | |
| 499 | |
| 500 | |
| 501 | |
| 502 | |
| 503 | |
| 504 | |
| 505 | function jetpack_boost_page_optimize_get_request_list( $request_uri ) { |
| 506 | $use_wp = defined( 'JETPACK_BOOST_CONCAT_USE_WP' ) && JETPACK_BOOST_CONCAT_USE_WP; |
| 507 | $utils = new Utils( $use_wp ); |
| 508 | |
| 509 | |
| 510 | $method = isset( $_SERVER['REQUEST_METHOD'] ) ? $utils->unslash( $_SERVER['REQUEST_METHOD'] ) : 'GET'; |
| 511 | if ( ! in_array( $method, array( 'GET', 'HEAD' ), true ) ) { |
| 512 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 513 | } |
| 514 | |
| 515 | |
| 516 | |
| 517 | |
| 518 | |
| 519 | |
| 520 | |
| 521 | $query = $utils->parse_url( $request_uri, PHP_URL_QUERY ); |
| 522 | if ( ! $query || ! str_contains( $query, '?' ) ) { |
| 523 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 524 | } |
| 525 | |
| 526 | return substr( $query, strpos( $query, '?' ) + 1 ); |
| 527 | } |
| 528 | |
| 529 | |
| 530 | |
| 531 | |
| 532 | |
| 533 | |
| 534 | |
| 535 | |
| 536 | |
| 537 | function jetpack_boost_page_optimize_get_issued_list( $list ) { |
| 538 | if ( strlen( $list ) > jetpack_boost_page_optimize_limits()['encoded_list'] ) { |
| 539 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 540 | } |
| 541 | |
| 542 | if ( File_Paths::is_id( $list ) ) { |
| 543 | $issued = File_Paths::get_issued( $list ); |
| 544 | if ( ! $issued ) { |
| 545 | jetpack_boost_page_optimize_status_exit( 404 ); |
| 546 | } |
| 547 | } else { |
| 548 | $issued = jetpack_boost_page_optimize_find_older_list( jetpack_boost_page_optimize_decode_older_list( $list ) ); |
| 549 | if ( ! $issued ) { |
| 550 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | if ( ! is_array( $issued->get_paths() ) ) { |
| 555 | |
| 556 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 557 | } |
| 558 | |
| 559 | return $issued; |
| 560 | } |
| 561 | |
| 562 | |
| 563 | |
| 564 | |
| 565 | |
| 566 | |
| 567 | |
| 568 | |
| 569 | function jetpack_boost_page_optimize_decode_older_list( $list ) { |
| 570 | $limits = jetpack_boost_page_optimize_limits(); |
| 571 | |
| 572 | |
| 573 | |
| 574 | if ( str_starts_with( $list, '-' ) ) { |
| 575 | |
| 576 | |
| 577 | $list = @gzuncompress( base64_decode( substr( $list, 1 ) ), $limits['decoded_list'] ); |
| 578 | |
| 579 | if ( false === $list || strlen( $list ) > $limits['decoded_list'] ) { |
| 580 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 581 | } |
| 582 | } |
| 583 | |
| 584 | |
| 585 | |
| 586 | $version_string_pos = strpos( $list, '?' ); |
| 587 | if ( false !== $version_string_pos ) { |
| 588 | $list = substr( $list, 0, $version_string_pos ); |
| 589 | } |
| 590 | |
| 591 | |
| 592 | return explode( ',', $list, min( jetpack_boost_minify_concat_max_files(), PHP_INT_MAX - 1 ) + 1 ); |
| 593 | } |
| 594 | |
| 595 | |
| 596 | |
| 597 | |
| 598 | |
| 599 | |
| 600 | |
| 601 | |
| 602 | function jetpack_boost_page_optimize_find_older_list( $paths ) { |
| 603 | $mtime = 0; |
| 604 | |
| 605 | foreach ( $paths as $uri ) { |
| 606 | $fullpath = jetpack_boost_page_optimize_get_path( $uri ); |
| 607 | if ( ! file_exists( $fullpath ) ) { |
| 608 | jetpack_boost_page_optimize_status_exit( 404 ); |
| 609 | } |
| 610 | $mtime = max( $mtime, (int) filemtime( $fullpath ) ); |
| 611 | } |
| 612 | |
| 613 | return File_Paths::find_issued( $paths, $mtime, jetpack_boost_minify_cache_buster() ); |
| 614 | } |
| 615 | |
| 616 | |
| 617 | |
| 618 | |
| 619 | |
| 620 | |
| 621 | |
| 622 | |
| 623 | function jetpack_boost_page_optimize_status_exit( $status ) { |
| 624 | http_response_code( $status ); |
| 625 | exit( 0 ); |
| 626 | } |
| 627 | |
| 628 | function jetpack_boost_page_optimize_get_mime_type( $file ) { |
| 629 | $jetpack_boost_page_optimize_types = jetpack_boost_page_optimize_types(); |
| 630 | |
| 631 | $lastdot_pos = strrpos( $file, '.' ); |
| 632 | if ( false === $lastdot_pos ) { |
| 633 | return false; |
| 634 | } |
| 635 | |
| 636 | $ext = substr( $file, $lastdot_pos + 1 ); |
| 637 | if ( ! isset( $jetpack_boost_page_optimize_types[ $ext ] ) ) { |
| 638 | return false; |
| 639 | } |
| 640 | |
| 641 | return $jetpack_boost_page_optimize_types[ $ext ]; |
| 642 | } |
| 643 | |
| 644 | function jetpack_boost_page_optimize_relative_path_replace( $buf, $dirpath ) { |
| 645 | |
| 646 | $buf = preg_replace( |
| 647 | '/(:?\s*url\s*\()\s*(?:\'|")?\s*([^\/\'"\s\)](?:(?<!data:|http:|https:|[\(\'"]#|%23).)*)[\'"\s]*\)/isU', |
| 648 | '$1' . ( $dirpath === '/' ? '/' : $dirpath . '/' ) . '$2)', |
| 649 | $buf |
| 650 | ); |
| 651 | |
| 652 | return $buf; |
| 653 | } |
| 654 | |
| 655 | function jetpack_boost_page_optimize_get_path( $uri ) { |
| 656 | static $dependency_path_mapping; |
| 657 | |
| 658 | if ( ! strlen( $uri ) ) { |
| 659 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 660 | } |
| 661 | |
| 662 | if ( str_contains( $uri, '..' ) || str_contains( $uri, "\0" ) ) { |
| 663 | jetpack_boost_page_optimize_status_exit( 400 ); |
| 664 | } |
| 665 | |
| 666 | if ( defined( 'PAGE_OPTIMIZE_CONCAT_BASE_DIR' ) ) { |
| 667 | $path = realpath( PAGE_OPTIMIZE_CONCAT_BASE_DIR . "/$uri" ); |
| 668 | |
| 669 | if ( false === $path ) { |
| 670 | $path = realpath( Config::get_abspath() . "/$uri" ); |
| 671 | } |
| 672 | } else { |
| 673 | if ( empty( $dependency_path_mapping ) ) { |
| 674 | $dependency_path_mapping = new Dependency_Path_Mapping(); |
| 675 | } |
| 676 | $path = $dependency_path_mapping->uri_path_to_fs_path( $uri ); |
| 677 | } |
| 678 | |
| 679 | if ( false === $path ) { |
| 680 | jetpack_boost_page_optimize_status_exit( 404 ); |
| 681 | } |
| 682 | |
| 683 | return $path; |
| 684 | } |