PluginProbe
Elementor Website Builder – more than just a page builder / 3.27.4
Elementor Website Builder – more than just a page builder v3.27.4
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
← All changes | core/files/base.php +3 -310 4.3.0-beta23.27.4 View file →
@@ -3,9 +3,9 @@
3 3
4 4 use Elementor\Plugin;
5 5
6 6 if ( ! defined( 'ABSPATH' ) ) {
7 - exit; // Exit if accessed directly.
7 + exit; // Exit if accessed directly
8 8 }
9 9
10 10 abstract class Base {
11 11
@@ -49,37 +49,10 @@
49 49 * @static
50 50 */
51 51 public static function get_base_uploads_dir() {
52 52 $wp_upload_dir = self::get_wp_uploads_dir();
53 - $dir = $wp_upload_dir['basedir'] . '/' . self::UPLOADS_DIR;
54 53
55 - if ( ! self::is_optimized_css_files_active() ) {
56 - return $dir;
57 - }
58 -
59 - /**
60 - * Elementor files base directory.
61 - *
62 - * Filters the absolute filesystem path of the Elementor files base directory.
63 - * Applies to all `Elementor\Core\Files\Base` consumers (Post CSS, Global CSS,
64 - * Frontend CSS, Google Fonts, atomic CSS, etc.) — not only atomic CSS.
65 - *
66 - * Can be filtered independently of `elementor/files/base_url`:
67 - * - Filter both to relocate Elementor files (e.g. WP VIP where `uploads/` is read-only).
68 - * - Filter only `elementor/files/base_url` (leaving this untouched) to serve files
69 - * from a CDN or an alternate URL (e.g. WPML sub-folder) while keeping local writes.
70 - *
71 - * Only available when the `e_optimized_css_files` experiment is active.
72 - *
73 - * @since 4.4.0
74 - *
75 - * @param string $dir Absolute filesystem path to the Elementor files base directory.
76 - */
77 - $filtered_dir = apply_filters( 'elementor/files/base_dir', $dir );
78 -
79 - $validated_dir = self::validate_base_dir( $filtered_dir );
80 -
81 - return null !== $validated_dir ? $validated_dir : $dir;
54 + return $wp_upload_dir['basedir'] . '/' . self::UPLOADS_DIR;
82 55 }
83 56
84 57 /**
85 58 * @since 2.1.0
@@ -87,38 +60,10 @@
87 60 * @static
88 61 */
89 62 public static function get_base_uploads_url() {
90 63 $wp_upload_dir = self::get_wp_uploads_dir();
91 - $url = $wp_upload_dir['baseurl'] . '/' . self::UPLOADS_DIR;
92 64
93 - if ( ! self::is_optimized_css_files_active() ) {
94 - return $url;
95 - }
96 -
97 - /**
98 - * Elementor files base URL.
99 - *
100 - * Filters the public URL of the Elementor files base directory.
101 - * Applies to all `Elementor\Core\Files\Base` consumers (Post CSS, Global CSS,
102 - * Frontend CSS, Google Fonts, atomic CSS, etc.) — not only atomic CSS.
103 - *
104 - * Accepts absolute (`https://cdn.example.com/…`) and protocol-relative
105 - * (`//cdn.example.com/…`) URLs. Can be filtered independently of
106 - * `elementor/files/base_dir` — filter only this hook to serve files from a
107 - * CDN or an alternate URL (e.g. WPML sub-folder) while keeping local writes
108 - * at the default location.
109 - *
110 - * Only available when the `e_optimized_css_files` experiment is active.
111 - *
112 - * @since 4.4.0
113 - *
114 - * @param string $url Public URL for the Elementor files base directory.
115 - */
116 - $filtered_url = apply_filters( 'elementor/files/base_url', $url );
117 -
118 - $validated_url = self::validate_base_url( $filtered_url );
119 -
120 - return null !== $validated_url ? $validated_url : $url;
65 + return $wp_upload_dir['baseurl'] . '/' . self::UPLOADS_DIR;
121 66 }
122 67
123 68 /**
124 69 * Use a create function for PhpDoc (@return static).
@@ -354,260 +299,8 @@
354 299 self::$wp_uploads_dir[ $blog_id ] = wp_upload_dir( null, false );
355 300 }
356 301
357 302 return self::$wp_uploads_dir[ $blog_id ];
358 - }
359 -
360 - /**
361 - * Whether the "Optimized CSS Files" experiment is active.
362 - *
363 - * @since 4.4.0
364 - * @access private
365 - * @static
366 - *
367 - * @return bool
368 - */
369 - private static function is_optimized_css_files_active() {
370 - return Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_files' );
371 - }
372 -
373 - /**
374 - * Validate a filtered base directory path.
375 - *
376 - * @since 4.4.0
377 - * @access private
378 - * @static
379 - *
380 - * @param mixed $dir Candidate base directory path.
381 - *
382 - * @return string|null Normalized path on success, or null to fall back to the default.
383 - */
384 - private static function validate_base_dir( $dir ) {
385 - if ( ! is_string( $dir ) || '' === $dir ) {
386 - _doing_it_wrong(
387 - __METHOD__,
388 - 'The `elementor/files/base_dir` filter must return a non-empty string.',
389 - '4.4.0'
390 - );
391 -
392 - return null;
393 - }
394 -
395 - $dir = trailingslashit( wp_normalize_path( $dir ) );
396 -
397 - if ( ! self::is_absolute_path( $dir ) ) {
398 - _doing_it_wrong(
399 - __METHOD__,
400 - 'The `elementor/files/base_dir` filter must return an absolute filesystem path.',
401 - '4.4.0'
402 - );
403 -
404 - return null;
405 - }
406 -
407 - if ( self::path_contains_traversal( $dir ) ) {
408 - _doing_it_wrong(
409 - __METHOD__,
410 - 'The `elementor/files/base_dir` filter must not contain path traversal segments.',
411 - '4.4.0'
412 - );
413 -
414 - return null;
415 - }
416 -
417 - if ( ! self::is_path_within_allowed_roots( $dir ) ) {
418 - _doing_it_wrong(
419 - __METHOD__,
420 - 'The `elementor/files/base_dir` filter must resolve inside `WP_CONTENT_DIR` or the uploads basedir.',
421 - '4.4.0'
422 - );
423 -
424 - return null;
425 - }
426 -
427 - return $dir;
428 - }
429 -
430 - /**
431 - * Validate a filtered base URL.
432 - *
433 - * @since 4.4.0
434 - * @access private
435 - * @static
436 - *
437 - * @param mixed $url Candidate base URL.
438 - *
439 - * @return string|null Normalized URL on success, or null to fall back to the default.
440 - */
441 - private static function validate_base_url( $url ) {
442 - if ( ! is_string( $url ) || '' === $url ) {
443 - _doing_it_wrong(
444 - __METHOD__,
445 - 'The `elementor/files/base_url` filter must return a non-empty string.',
446 - '4.4.0'
447 - );
448 -
449 - return null;
450 - }
451 -
452 - $url = trailingslashit( $url );
453 -
454 - if ( ! self::is_valid_base_url( $url ) ) {
455 - _doing_it_wrong(
456 - __METHOD__,
457 - 'The `elementor/files/base_url` filter must return an absolute or protocol-relative http(s) URL.',
458 - '4.4.0'
459 - );
460 -
461 - return null;
462 - }
463 -
464 - return $url;
465 - }
466 -
467 - /**
468 - * Lightweight structural check for the base URL filter.
469 - *
470 - * Intentionally avoids `wp_http_validate_url()` which performs DNS lookups and
471 - * rejects protocol-relative and RFC1918 URLs — none of which we want when the
472 - * URL is only being prepended to CSS asset paths (CDN endpoints, WPML sub-folder
473 - * rewrites, etc.). We only enforce that the value looks like an absolute or
474 - * protocol-relative http/https URL with a host.
475 - *
476 - * @since 4.4.0
477 - * @access private
478 - * @static
479 - *
480 - * @param string $url Candidate URL (already normalized to a trailing slash).
481 - *
482 - * @return bool
483 - */
484 - private static function is_valid_base_url( $url ) {
485 - $is_protocol_relative = 0 === strpos( $url, '//' );
486 - $parsable = $is_protocol_relative ? 'https:' . $url : $url;
487 -
488 - $parts = wp_parse_url( $parsable );
489 -
490 - if ( ! is_array( $parts ) || empty( $parts['host'] ) ) {
491 - return false;
492 - }
493 -
494 - if ( ! $is_protocol_relative ) {
495 - $scheme = isset( $parts['scheme'] ) ? strtolower( $parts['scheme'] ) : '';
496 -
497 - if ( ! in_array( $scheme, [ 'http', 'https' ], true ) ) {
498 - return false;
499 - }
500 - }
501 -
502 - return true;
503 - }
504 -
505 - /**
506 - * @since 4.4.0
507 - * @access private
508 - * @static
509 - *
510 - * @param string $path Filesystem path.
511 - *
512 - * @return bool
513 - */
514 - private static function is_absolute_path( $path ) {
515 - if ( wp_is_stream( $path ) ) {
516 - return true;
517 - }
518 -
519 - $path = wp_normalize_path( $path );
520 -
521 - return isset( $path[0] ) && ( '/' === $path[0] || preg_match( '#^[a-zA-Z]:/#', $path ) );
522 - }
523 -
524 - /**
525 - * @since 4.4.0
526 - * @access private
527 - * @static
528 - *
529 - * @param string $path Filesystem path.
530 - *
531 - * @return bool
532 - */
533 - private static function path_contains_traversal( $path ) {
534 - $parts = explode( '/', wp_normalize_path( untrailingslashit( $path ) ) );
535 -
536 - return in_array( '..', $parts, true );
537 - }
538 -
539 - /**
540 - * @since 4.4.0
541 - * @access private
542 - * @static
543 - *
544 - * @param string $path Filesystem path.
545 - *
546 - * @return bool
547 - */
548 - private static function is_path_within_allowed_roots( $path ) {
549 - if ( defined( 'ELEMENTOR_FILES_ALLOW_EXTERNAL_BASE_DIR' ) && ELEMENTOR_FILES_ALLOW_EXTERNAL_BASE_DIR ) {
550 - return true;
551 - }
552 -
553 - $resolved_path = self::resolve_deepest_existing( $path );
554 -
555 - if ( false === $resolved_path ) {
556 - return false;
557 - }
558 -
559 - $uploads_basedir = self::get_wp_uploads_dir()['basedir'];
560 - $allowed_roots = array_filter( [
561 - self::resolve_deepest_existing( WP_CONTENT_DIR ),
562 - self::resolve_deepest_existing( $uploads_basedir ),
563 - ] );
564 -
565 - foreach ( $allowed_roots as $root ) {
566 - if ( $resolved_path === $root || 0 === strpos( $resolved_path, $root . '/' ) ) {
567 - return true;
568 - }
569 - }
570 -
571 - return false;
572 - }
573 -
574 - /**
575 - * Resolve the realpath of the deepest existing ancestor of `$path`.
576 - *
577 - * Non-existent targets are common when a host sets the filter to a directory
578 - * that Elementor will create on first write. Walking up to the deepest existing
579 - * ancestor lets us still resolve symlinks and reject paths whose real location
580 - * escapes the allowed roots.
581 - *
582 - * @since 4.4.0
583 - * @access private
584 - * @static
585 - *
586 - * @param string $path Filesystem path.
587 - *
588 - * @return string|false Normalized realpath, or false if none could be resolved.
589 - */
590 - private static function resolve_deepest_existing( $path ) {
591 - $current = wp_normalize_path( untrailingslashit( (string) $path ) );
592 -
593 - while ( '' !== $current && ! file_exists( $current ) ) {
594 - $parent = wp_normalize_path( dirname( $current ) );
595 -
596 - if ( $parent === $current ) {
597 - return false;
598 - }
599 -
600 - $current = $parent;
601 - }
602 -
603 - if ( '' === $current ) {
604 - return false;
605 - }
606 -
607 - $real = realpath( $current );
608 -
609 - return $real ? untrailingslashit( wp_normalize_path( $real ) ) : false;
610 303 }
611 304
612 305 /**
613 306 * @since 2.1.0