| Server IP : 104.26.5.103 / Your IP : 216.73.217.51 Web Server : nginx/1.27.1 System : Linux in-5 5.15.0-191-generic #201-Ubuntu SMP Fri Aug 7 18:39:04 UTC 2026 x86_64 User : arabianexpress ( 1872) PHP Version : 8.0.30 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,parse_ini_file,show_source MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /storage/v9321/leapdubai/public_html/wp-content/plugins/kirki/app/Services/ |
Upload File : |
<?php
namespace Kirki\App\Services;
defined('ABSPATH') || exit;
use Exception;
use Kirki\App\DTO\GoogleFontDTO;
use Kirki\App\Supports\Facades\GlobalData;
use Kirki\App\Supports\FileHandler;
use Kirki\Framework\Http\Response;
use Kirki\Framework\Supports\Facades\File;
use Kirki\Framework\Supports\Facades\Http;
use function Kirki\App\get_upload_directory;
use function Kirki\App\get_upload_directory_url;
use function Kirki\Framework\clean_path;
class FontService
{
public function download_google_font(GoogleFontDTO $payload)
{
// Extra security: keep only a-z, 0-9, and hyphens
$font_family_slug = preg_replace('/[^a-z0-9\-]/i', '', sanitize_title_with_dashes(basename($payload->family)));
if (empty($font_family_slug) || strpos($font_family_slug, '..') !== false) {
throw new Exception(esc_html__('Not valid font family.', 'kirki'), Response::FORBIDDEN);
}
$has_write_permission = File::is_writable(get_upload_directory());
if (!$has_write_permission) {
throw new Exception(esc_html__('Upload directory is not writable.', 'kirki'), Response::FORBIDDEN);
}
$font_dir = clean_path(get_upload_directory() . "/kirki-fonts/{$font_family_slug}", false);
$css_file_path = clean_path($font_dir . "/{$font_family_slug}.css", false);
FileHandler::verify_directory_traversal($css_file_path);
if (File::exists($css_file_path)) {
throw new Exception(esc_html__('Font already downloaded.', 'kirki'), Response::FORBIDDEN);
}
$font_url_parts = wp_parse_url($payload->fontUrl);
if (!$font_url_parts) {
throw new Exception(esc_html__('Invalid URL.', 'kirki'));
}
if (($font_url_parts['scheme'] ?? '') !== 'https') {
throw new Exception(esc_html__('Only HTTPS is allowed.', 'kirki'));
}
if (($font_url_parts['host'] ?? '') !== 'fonts.googleapis.com') {
throw new Exception(esc_html__('Only Google Fonts is supported.', 'kirki'));
}
try {
if (!File::is_directory($font_dir)) {
File::make_dir($font_dir);
}
$response = Http::with_options([
'redirection' => 0
])->get($payload->fontUrl);
if ($response->failed()) {
throw new Exception(esc_html__('Failed to fetch Google Fonts CSS.', 'kirki'));
}
$formats = [
'woff2' => 'woff2',
'woff' => 'woff',
'ttf' => 'truetype',
'otf' => 'opentype',
];
// Keep Google's CSS verbatim (all weights, styles and unicode-range)
// and only swap the remote font files for their local counterparts.
$css = $response->body();
if (!preg_match_all('/url\(\s*["\']?([^"\'()]+)["\']?\s*\)/i', $css, $matches)) {
throw new Exception(esc_html__('No usable font files were downloaded.', 'kirki'));
}
$local_files = [];
foreach (array_unique($matches[1]) as $url) {
$url_parts = wp_parse_url($url);
if (!$url_parts) {
throw new Exception(esc_html__('Invalid URL.', 'kirki'));
}
if (($url_parts['scheme'] ?? '') !== 'https') {
throw new Exception(esc_html__('Only HTTPS is allowed.', 'kirki'));
}
if (($url_parts['host'] ?? '') !== 'fonts.gstatic.com') {
throw new Exception(esc_html__('Only Google Fonts is supported.', 'kirki'));
}
$extension = strtolower(pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION));
if (!array_key_exists($extension, $formats)) {
/* translators: %s: file extension */
throw new Exception(sprintf(esc_html__('Invalid or unsafe file extension: %s.', 'kirki'), $extension));
}
$file_name = preg_replace('/[^a-zA-Z0-9._-]/', '', basename(parse_url($url, PHP_URL_PATH)));
if (empty($file_name)) {
throw new Exception(esc_html__('Invalid file name.', 'kirki'));
}
$file_path = clean_path($font_dir . '/' . $file_name, false);
FileHandler::verify_directory_traversal($file_path);
if (!File::exists($file_path)) {
$font_response = Http::with_options([
'redirection' => 0
])->get($url);
if ($font_response->failed()) {
throw new Exception(esc_html__('Failed to fetch font file.', 'kirki'));
}
File::put($file_path, $font_response->__toString());
}
$local_files[$url] = $file_name;
}
$local_css = str_replace(array_keys($local_files), array_values($local_files), $css);
if (empty($local_css)) {
throw new Exception(esc_html__('No usable font files were downloaded.', 'kirki'));
}
File::put($css_file_path, $local_css);
$payload->localUrl = clean_path(get_upload_directory_url() . "/kirki-fonts/{$font_family_slug}/{$font_family_slug}.css", false);
$this->save_google_font_into_global_custom_fonts($payload);
return $payload;
} catch (Exception $exception) {
if (File::is_directory($font_dir)) {
File::delete($font_dir);
}
throw $exception;
}
}
public function remove_google_font(GoogleFontDTO $payload) {
$font_family_slug = sanitize_title_with_dashes(basename($payload->family));
$font_dir = clean_path(get_upload_directory() . "/kirki-fonts/{$font_family_slug}", false);
FileHandler::verify_directory_traversal($font_dir);
if (File::is_directory($font_dir)) {
File::delete($font_dir);
}
$payload->exclude(['localUrl']);
$this->save_google_font_into_global_custom_fonts($payload);
return true;
}
protected function save_google_font_into_global_custom_fonts(GoogleFontDTO $font) {
// first get the font data
$custom_fonts = GlobalData::get_global_custom_fonts();
if (empty($custom_fonts)) {
$custom_fonts = [];
}
if (!empty($font->family)) {
$custom_fonts[$font->family] = $font->to_array();
GlobalData::update_global_custom_fonts($custom_fonts);
}
}
public function remove_custom_fonts_permanently_from_directory(array $fonts)
{
foreach ($fonts as $font) {
// Remove font from local.
$font_family_slug = sanitize_title_with_dashes(basename($font['family']));
$font_local_dir = clean_path(get_upload_directory() . "/kirki-fonts/{$font_family_slug}", false);
FileHandler::verify_directory_traversal($font_local_dir);
if (File::is_directory($font_local_dir)) {
File::delete($font_local_dir);
}
}
}
}