PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.17.6
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.17.6
V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 2.10.2 All 137 releases
bit-form / includes / Core / Util / FileHandler.php

FileHandler.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 2.17.6, at includes/Core/Util/FileHandler.php

366 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace BitCode\BitForm\Core\Util;
4
5 use BitCode\BitForm\Admin\Form\Helpers;
6 use BitCode\BitForm\Core\Form\FormManager;
7 use BitCode\BitForm\enshrined\svgSanitize\Sanitizer;
8
9 final class FileHandler
10 {
11 public function rmrf($dir)
12 {
13 if (is_dir($dir)) {
14 $objects = scandir($dir);
15 foreach ($objects as $object) {
16 if ('.' !== $object && '..' !== $object) {
17 if (is_dir($dir . DIRECTORY_SEPARATOR . $object) && !is_link($dir . DIRECTORY_SEPARATOR . $object)) {
18 $this->rmrf($dir . DIRECTORY_SEPARATOR . $object);
19 } else {
20 wp_delete_file($dir . DIRECTORY_SEPARATOR . $object);
21 }
22 }
23 }
24 rmdir($dir);
25 } else {
26 wp_delete_file($dir);
27 }
28 }
29
30 public function cpyr($source, $destination)
31 {
32 if (is_dir($source)) {
33 mkdir($destination);
34 // chmod($destination, 0744);
35 $objects = scandir($source);
36 foreach ($objects as $object) {
37 if ('.' !== $object && '..' !== $object) {
38 if (is_dir($source . DIRECTORY_SEPARATOR . $object) && !is_link($source . DIRECTORY_SEPARATOR . $object)) {
39 cpyr($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
40 } elseif (is_file($source . DIRECTORY_SEPARATOR . $object)) {
41 copy($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
42 // chmod($destination. DIRECTORY_SEPARATOR .$object, 0644);
43 } else {
44 symlink($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
45 }
46 }
47 }
48 } else {
49 copy($source, $destination);
50 }
51 }
52
53 public function moveUploadedFiles($file_details, $form_id, $entry_id)
54 {
55 $file_upoalded = [];
56 $_upload_dir = self::getEntriesFileUploadDir($form_id, $entry_id);
57 $this::createIndexFile($_upload_dir);
58 if (is_array($file_details['name'])) {
59 foreach ($file_details['name'] as $key => $value) {
60 //check accepted filetype in_array($file_details['name'][$key], $supported_files) else \
61 if (!empty($value)) {
62 $fileNameCount = 1;
63 // $file_upoalded[$key] = time()."_$value";
64 $file_upoalded[$key] = sanitize_file_name($value);
65 while (file_exists($_upload_dir . DIRECTORY_SEPARATOR . $file_upoalded[$key])) {
66 $fileNameWithSeparator = BITFORMS_BF_SEPARATOR . $fileNameCount;
67 $file_upoalded[$key] = sanitize_file_name(preg_replace('/(.[a-z A-Z 0-9]+)$/', "{$fileNameWithSeparator}$1", $value));
68 $fileNameCount = $fileNameCount + 1;
69 if (11 === $fileNameCount) {
70 break;
71 }
72 }
73 $move_status = \move_uploaded_file($file_details['tmp_name'][$key], $_upload_dir . DIRECTORY_SEPARATOR . $file_upoalded[$key]);
74 if (!$move_status) {
75 unset($file_upoalded[$key]);
76 }
77 }
78 }
79 } else {
80 if (!empty($file_details['name'])) {
81 $fileNameCount = 1;
82 $file_upoalded[0] = sanitize_file_name($file_details['name']);
83 while (file_exists($_upload_dir . DIRECTORY_SEPARATOR . $file_upoalded[0])) {
84 $fileNameWithSeparator = BITFORMS_BF_SEPARATOR . $fileNameCount;
85 $file_upoalded[0] = sanitize_file_name(preg_replace('/(.[a-z A-Z 0-9]+)$/', "{$fileNameWithSeparator}$1", $file_details['name']));
86 $fileNameCount = $fileNameCount + 1;
87 if (11 === $fileNameCount) {
88 break;
89 }
90 }
91 $move_status = \move_uploaded_file($file_details['tmp_name'], $_upload_dir . DIRECTORY_SEPARATOR . $file_upoalded[0]);
92 if (!$move_status) {
93 unset($file_upoalded[0]);
94 }
95 }
96 }
97 return $file_upoalded;
98 }
99
100 public function deleteFiles($form_id, $entry_id, $files)
101 {
102 $_upload_dir = self::getEntriesFileUploadDir($form_id, $entry_id);
103 foreach ($files as $name) {
104 wp_delete_file($_upload_dir . DIRECTORY_SEPARATOR . $name);
105 }
106 }
107
108 public static function getFileUploadError($code)
109 {
110 $errors = [
111 0 => __('Unknown upload error', 'bit-form'),
112 1 => __('The uploaded file exceeds the upload_max_filesize directive in php.ini.', 'bit-form'),
113 2 => __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'bit-form'),
114 3 => __('The uploaded file was only partially uploaded.', 'bit-form'),
115 4 => __('No file was uploaded.', 'bit-form'),
116 6 => __('Missing a temporary folder.', 'bit-form'),
117 7 => __('Failed to write file to disk.', 'bit-form'),
118 8 => __('A PHP extension stopped the file upload.', 'bit-form'),
119 ];
120 return $errors[$code];
121 }
122
123 public static function fileCopy($tmpdir, $destinationDir, $file)
124 {
125 $tmpFile = $tmpdir . DIRECTORY_SEPARATOR . $file;
126 $newFile = $destinationDir . DIRECTORY_SEPARATOR . $file;
127 if (file_exists($tmpFile)) {
128 copy($tmpFile, $newFile);
129 }
130 }
131
132 public static function tempDirToUploadDir($submitted_data, $fields, $formId, $entryID)
133 {
134 $upload_dir = wp_upload_dir();
135 $tempDir = $upload_dir['basedir'] . '/bitforms/temp';
136 $destinationDir = self::getEntriesFileUploadDir($formId, $entryID) . DIRECTORY_SEPARATOR;
137 self::createIndexFile($destinationDir);
138
139 foreach ($submitted_data as $key => $data) {
140 if (isset($fields[$key]) && 'advanced-file-up' === $fields[$key]['type']) {
141 $files = $data;
142 $fldData = $submitted_data[$key];
143 $files = explode(',', $fldData);
144 if (is_array($files) && count($files) > 0) {
145 foreach ($files as $file) {
146 self::fileCopy($tempDir, $destinationDir, trim($file));
147 }
148 } else {
149 self::fileCopy($tempDir, $destinationDir, trim($files));
150 }
151 if (!empty($files)) {
152 $submitted_data[$key] = $files;
153 }
154 }
155 }
156 array_map('unlink', array_filter(
157 (array) array_merge(glob("$tempDir/*"))
158 ));
159
160 return $submitted_data;
161 }
162
163 private function getByteSizeByUnit($sizeString)
164 {
165 // split 2MB into 2 and MB
166 $size = preg_replace('/[^0-9\.]/', '', $sizeString);
167 $unit = preg_replace('/[^a-zA-Z]/', '', $sizeString);
168 $unit = strtolower($unit);
169 if ('kb' === $unit) {
170 return $size * 1024;
171 } elseif ('mb' === $unit) {
172 return $size * 1024 * 1024;
173 } elseif ('gb' === $unit) {
174 return $size * 1024 * 1024 * 1024;
175 } else {
176 return $size;
177 }
178 }
179
180 public function validation($field_key, $file_details, $form_id)
181 {
182 if (!function_exists('wp_check_filetype_and_ext')) {
183 require_once ABSPATH . 'wp-admin/includes/file.php';
184 }
185
186 $formManager = new FormManager($form_id);
187 $form_contents = $formManager->getFormContent();
188 $field_content_details = $form_contents->fields;
189 $fieldDetail = $field_content_details->{$field_key};
190 $fieldType = $fieldDetail->typ;
191 $maxSizeDetails = [];
192 $allowFileTypes = [];
193 $maxSize = null;
194 if ('file-up' === $fieldType) {
195 $allowFileTypes = !empty($fieldDetail->config->allowedFileType) ? $fieldDetail->config->allowedFileType : [];
196 if (!empty($fieldDetail->config->allowMaxSize)) {
197 if (!empty($fieldDetail->config->maxSize)) {
198 $maxSizeDetails['maxSize'] = $fieldDetail->config->maxSize . $fieldDetail->config->sizeUnit;
199 }
200 if (!empty($fieldDetail->config->isItTotalMax)) {
201 $maxSizeDetails['maxTotalFileSize'] = $fieldDetail->config->maxSize . $fieldDetail->config->sizeUnit;
202 }
203 }
204 if (!empty($allowFileTypes)) {
205 $allowFileTypes = explode(',', $allowFileTypes);
206 }
207 } elseif ('advanced-file-up' === $fieldType) {
208 $allowFileTypes = !empty($fieldDetail->config->allowFileTypeValidation) ? $fieldDetail->config->acceptedFileTypes : [];
209 if (!empty($fieldDetail->config->allowFileSizeValidation)) {
210 if (!empty($fieldDetail->config->maxFileSize)) {
211 $maxSizeDetails['maxSize'] = $fieldDetail->config->maxFileSize;
212 }
213 if (!empty($fieldDetail->config->maxTotalFileSize)) {
214 $maxSizeDetails['maxTotalFileSize'] = $fieldDetail->config->maxTotalFileSize;
215 }
216 }
217 }
218 if (!empty($maxSizeDetails['maxSize'])) {
219 $maxSize = $this->getByteSizeByUnit($maxSizeDetails['maxSize']);
220 }
221 $maxTotalFileSize = null;
222 if (!empty($maxSizeDetails['maxTotalFileSize'])) {
223 $maxTotalFileSize = $this->getByteSizeByUnit($maxSizeDetails['maxTotalFileSize']);
224 }
225
226 if ($formManager->isRepeatedField($field_key)) {
227 foreach ($file_details['name'] as $rowIndex => $file) {
228 if (!empty($file)) {
229 $fileDetails = [
230 'name' => $file,
231 'type' => $file_details['type'][$rowIndex],
232 'tmp_name' => $file_details['tmp_name'][$rowIndex],
233 'error' => $file_details['error'][$rowIndex],
234 'size' => $file_details['size'][$rowIndex],
235 ];
236 $validateState = $this->validateFileInfo($fieldType, $fileDetails, $allowFileTypes, $maxSize, $maxTotalFileSize);
237 if (!empty($validateState) && !empty($validateState['message'])) {
238 return $validateState;
239 }
240 }
241 }
242 } else {
243 return $this->validateFileInfo($fieldType, $file_details, $allowFileTypes, $maxSize, $maxTotalFileSize);
244 }
245 return [];
246 }
247
248 private function validateFileInfo($fieldType, $file_details, $allowFileTypes, $maxSize, $maxTotalFileSize)
249 {
250 $errorMessage = [
251 'message' => '',
252 'error_type'=> '',
253 ];
254 if (is_array($file_details['name'])) {
255 $totalSize = 0;
256 foreach ($file_details['name'] as $key => $file) {
257 if (!empty($file)) {
258 $fileInfo = [
259 'name' => $file,
260 'type' => $file_details['type'][$key],
261 'tmp_name' => $file_details['tmp_name'][$key],
262 'error' => $file_details['error'][$key],
263 'size' => $file_details['size'][$key],
264 ];
265 $totalSize += $fileInfo['size'];
266 $validateState = $this->validateSingleFile($fieldType, $fileInfo, $allowFileTypes, $maxSize);
267 if (!empty($validateState)) {
268 return $validateState;
269 }
270 }
271 }
272 if (isset($maxTotalFileSize) && !is_null($maxTotalFileSize) && $totalSize > $maxTotalFileSize) {
273 $errorMessage['message'] = __('Total File size is too large', 'bit-form');
274 $errorMessage['error_type'] = 'file_size_error';
275 return $errorMessage;
276 }
277 } else {
278 $validateState = $this->validateSingleFile($fieldType, $file_details, $allowFileTypes, $maxSize);
279 if (!empty($validateState)) {
280 return $validateState;
281 }
282 }
283
284 return $errorMessage;
285 }
286
287 private function validateSingleFile($fieldType, &$file, $allowTypes, $maxSize = null)
288 {
289 $fileName = sanitize_file_name($file['name']);
290 if (!empty($fileName)) {
291 $fileSize = $file['size'];
292 if (!empty($maxSize) && $fileSize > $maxSize) {
293 return [
294 'message' => __('File size is too large', 'bit-form'),
295 'error_type'=> 'file_size_error',
296 ];
297 }
298
299 $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
300 $fileExtAllowedByWp = wp_check_filetype_and_ext($file['tmp_name'], $fileName);
301 $isAllowedFileType = in_array('.' . $fileExtension, $allowTypes);
302 if ('advanced-file-up' === $fieldType && !empty($allowTypes)) {
303 if (function_exists('mime_content_type')) {
304 $fileMimeType = mime_content_type($file['tmp_name']);
305 } else {
306 $fileMimeType = $fileExtAllowedByWp['type'];
307 }
308 $isAllowedFileType = in_array($fileMimeType, $allowTypes);
309 }
310 if ((!empty($allowTypes) && !$isAllowedFileType) || (empty($allowTypes) && empty($fileExtAllowedByWp['ext']))) {
311 return [
312 'message' => __(($fileExtension ? ".{$fileExtension}" : 'empty') . ' file extension is not allowed', 'bit-form'),
313 'error_type'=> 'file_type_error',
314 ];
315 }
316 if ('svg' === $fileExtension) {
317 $svg_sanitizer = new Sanitizer();
318 $dirty_svg = file_get_contents($file['tmp_name']);
319 $clean_svg = $svg_sanitizer->sanitize($dirty_svg);
320 if (false === $clean_svg) {
321 return [
322 'message' => __('SVG file is not valid', 'bit-form'),
323 'error_type'=> 'file_type_error',
324 ];
325 }
326 file_put_contents($file['tmp_name'], $clean_svg);
327 }
328 }
329 }
330
331 public static function deleteIsFileExists($path)
332 {
333 if (file_exists($path)) {
334 wp_delete_file($path);
335 }
336 }
337
338 public static function getEntriesFileUploadDir($form_id, $entry_id)
339 {
340 $uploadDir = rtrim(BITFORMS_UPLOAD_DIR, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $form_id . DIRECTORY_SEPARATOR;
341 $previousEntryDirectory = $uploadDir . $entry_id;
342 if (is_dir($previousEntryDirectory)) {
343 return $previousEntryDirectory;
344 }
345 $encrypted_directory = Helpers::getEncryptedEntryId($entry_id);
346 return $uploadDir . $encrypted_directory;
347 }
348
349 public static function createIndexFile($directory)
350 {
351 if (wp_mkdir_p($directory)) {
352 $indexFilePath = rtrim($directory, '/') . '/index.php';
353 if (!file_exists($indexFilePath)) {
354 try {
355 if (false === file_put_contents($indexFilePath, "<?php\n// No direct access allowed.")) {
356 throw new \Exception("Failed to create index.php in $directory");
357 }
358 } catch (\Exception $e) {
359 error_log($e->getMessage()); // Log the error for debugging
360 }
361 }
362 }
363 return false;
364 }
365 }
366