PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.2.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.2.0
6.2.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 5 days ago Form 5 days ago ActionHooks.php 5 days ago Canvas.php 1 month ago CollectionItem.php 5 days ago ContentManager.php 1 month ago DateTime.php 1 month ago EditorPreview.php 2 weeks ago FileHandler.php 2 weeks ago FilterHooks.php 2 weeks ago PageUrl.php 5 days ago Recaptcha.php 5 days ago Role.php 1 month ago Session.php 5 days ago Template.php 5 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 }