PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.0
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / app / Supports / FileHandler.php
kirki / app / Supports Last commit date
Facades 3 days ago Canvas.php 3 weeks ago CollectionItem.php 3 weeks ago ContentManager.php 3 weeks ago DateTime.php 3 weeks ago EditorPreview.php 3 days ago FileHandler.php 3 days ago FilterHooks.php 3 days ago PageUrl.php 3 days ago Role.php 3 weeks ago Template.php 3 days ago
FileHandler.php
146 lines
1 <?php
2
3 namespace Kirki\App\Supports;
4
5 defined('ABSPATH') || exit;
6
7 use Exception;
8 use Kirki\Framework\Supports\Facades\File as FileHelper;
9 use Kirki\Framework\Supports\Facades\Http;
10 use PclZip;
11
12 use function Kirki\App\get_upload_directory;
13 use function Kirki\Framework\clean_path;
14 use function Kirki\Framework\Polyfill\array_last;
15
16 class FileHandler
17 {
18 public static function get_temp_folder_path()
19 {
20 $temp_folder = 'kirki_temp';
21
22 return get_upload_directory() . '/' . $temp_folder;
23 }
24
25 /**
26 * Download zip file from remote server
27 *
28 * @param string $remote_file_url
29 * @param string $file_name
30 * @return string|false -- if failed return false
31 */
32 public static function download_zip_from_remote(string $remote_file_url, string $file_name)
33 {
34 $file_ext = explode('.', $remote_file_url); // ['file', 'ext']
35 $file_ext = strtolower(array_last($file_ext)); // 'ext'
36 $allowed = ['zip'];
37
38 if (!in_array($file_ext, $allowed)) {
39 return false;
40 }
41
42 // Download the file from the remote server.
43 $response = Http::timeout(120)
44 ->with_options([
45 'redirection' => 0
46 ])
47 ->with_user_agent('WordPress')
48 ->get($remote_file_url);
49
50 if ($response->failed()) {
51 return false;
52 }
53
54 // Save the file locally.
55 // Local path to save the downloaded file.
56 $local_file_path = clean_path(get_upload_directory() . '/' . $file_name, false);
57
58 static::verify_directory_traversal($local_file_path);
59
60 $is_downloaded = FileHelper::put($local_file_path, $response->body());
61
62 if (!$is_downloaded) {
63 return false;
64 }
65
66 return $local_file_path;
67 }
68
69 /**
70 * @return array|false
71 * return false on failure
72 */
73 public static function extract_zip_file(string $zip_file_path, string $destination_dir)
74 {
75 if (!class_exists('PclZip')) {
76 require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';
77 }
78
79 $zip_file_path = clean_path($zip_file_path, false);
80
81 if (FileHelper::missing($zip_file_path)) {
82 return false;
83 }
84
85 if (!FileHelper::is_directory($destination_dir)) {
86 FileHelper::make_dir($destination_dir);
87 }
88
89 $zip = new PclZip($zip_file_path);
90
91 static::validate_zip_file($zip);
92
93 $result = $zip->extract(
94 PCLZIP_OPT_PATH,
95 $destination_dir
96 );
97
98 if (is_array($result)) {
99 return $result;
100 }
101
102 return false;
103 }
104
105 public static function validate_zip_file(PclZip $zip)
106 {
107 $list = $zip->listContent();
108
109 if (!is_array($list)) {
110 throw new Exception(esc_html__('Failed to read ZIP file.', 'kirki'));
111 }
112
113 foreach ($list as $entry) {
114 if (!isset($entry['filename'])) {
115 throw new Exception(esc_html__('Invalid ZIP file.', 'kirki'));
116 }
117
118 static::validate_zip_entry($entry['filename']);
119 }
120 }
121
122 private static function validate_zip_entry(string $entry_filename)
123 {
124 $entry_filename = clean_path($entry_filename, false);
125
126 if (
127 $entry_filename === '' ||
128 str_contains($entry_filename, "\0") ||
129 str_starts_with($entry_filename, '/') ||
130 preg_match('/^[A-Za-z]:\//', $entry_filename)
131 ) {
132 throw new Exception(esc_html__('Invalid ZIP file.', 'kirki'));
133 }
134
135 return static::verify_directory_traversal($entry_filename);
136 }
137
138 Public static function verify_directory_traversal(string $path) {
139 if (preg_match('#(^|/)\.\.(/|$)#', clean_path($path, false))) {
140 /* translators: %s: File Path */
141 throw new Exception(sprintf(esc_html__('Directory traversal detected in %s.', 'kirki'), $path));
142 }
143
144 return true;
145 }
146 }